Skip to content

Commit cfa0b07

Browse files
committed
clean up logic
1 parent e843245 commit cfa0b07

File tree

8 files changed

+150
-142
lines changed

8 files changed

+150
-142
lines changed

src/librustc/query/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,16 @@ rustc_queries! {
398398
typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
399399
}
400400
}
401+
query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> {
402+
cache_on_disk_if { key.is_local() }
403+
load_cached(tcx, id) {
404+
let typeck_tables: Option<ty::TypeckTables<'tcx>> = tcx
405+
.queries.on_disk_cache
406+
.try_load_query_result(tcx, id);
407+
408+
typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
409+
}
410+
}
401411
}
402412

403413
Other {

src/librustc_typeck/astconv.rs

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,30 +2770,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27702770
let tcx = self.tcx();
27712771

27722772
// We proactively collect all the infered type params to emit a single error per fn def.
2773-
let mut placeholder_types = vec![];
2774-
let mut output_placeholder_types = vec![];
2775-
2776-
let input_tys = decl.inputs.iter().map(|a| {
2777-
let mut visitor = PlaceholderHirTyCollector::new();
2778-
visitor.visit_ty(&a);
2779-
if visitor.0.is_empty() || self.allow_ty_infer() {
2780-
self.ty_of_arg(a, None)
2781-
} else {
2782-
placeholder_types.extend(visitor.0);
2783-
tcx.types.err
2784-
}
2785-
});
2773+
let mut visitor = PlaceholderHirTyCollector::new();
2774+
for ty in &decl.inputs {
2775+
visitor.visit_ty(ty);
2776+
}
2777+
let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
27862778
let output_ty = match decl.output {
27872779
hir::Return(ref output) => {
2788-
let mut visitor = PlaceholderHirTyCollector::new();
27892780
visitor.visit_ty(output);
2790-
let is_infer = if let hir::TyKind::Infer = output.kind { true } else { false };
2791-
if (is_infer || !visitor.0.is_empty()) && !self.allow_ty_infer() {
2792-
output_placeholder_types.extend(visitor.0);
2793-
tcx.types.err
2794-
} else {
2795-
self.ast_ty_to_ty(output)
2796-
}
2781+
self.ast_ty_to_ty(output)
27972782
}
27982783
hir::DefaultReturn(..) => tcx.mk_unit(),
27992784
};
@@ -2803,15 +2788,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
28032788
let bare_fn_ty =
28042789
ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
28052790

2806-
placeholder_types.extend(output_placeholder_types);
2807-
2808-
crate::collect::placeholder_type_error(
2809-
tcx,
2810-
ident_span.unwrap_or(DUMMY_SP),
2811-
generic_params,
2812-
placeholder_types,
2813-
ident_span.is_some(),
2814-
);
2791+
if !self.allow_ty_infer() {
2792+
crate::collect::placeholder_type_error(
2793+
tcx,
2794+
ident_span.unwrap_or(DUMMY_SP),
2795+
generic_params,
2796+
visitor.0,
2797+
ident_span.is_some(),
2798+
);
2799+
}
28152800

28162801
// Find any late-bound regions declared in return type that do
28172802
// not appear in the arguments. These are not well-formed.

src/librustc_typeck/check/mod.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ pub fn provide(providers: &mut Providers<'_>) {
756756
*providers = Providers {
757757
typeck_item_bodies,
758758
typeck_tables_of,
759+
diagnostic_only_typeck_tables_of,
759760
has_typeck_tables,
760761
adt_destructor,
761762
used_trait_imports,
@@ -941,7 +942,26 @@ where
941942
val.fold_with(&mut FixupFolder { tcx })
942943
}
943944

944-
fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
945+
fn typeck_tables_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &ty::TypeckTables<'tcx> {
946+
let fallback = move || tcx.type_of(def_id);
947+
typeck_tables_of_with_fallback(tcx, def_id, fallback)
948+
}
949+
950+
/// Used only to get `TypeckTables` for type inference during error recovery.
951+
/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
952+
fn diagnostic_only_typeck_tables_of<'tcx>(
953+
tcx: TyCtxt<'tcx>,
954+
def_id: DefId,
955+
) -> &ty::TypeckTables<'tcx> {
956+
let fallback = move || tcx.types.err;
957+
typeck_tables_of_with_fallback(tcx, def_id, fallback)
958+
}
959+
960+
fn typeck_tables_of_with_fallback<'tcx>(
961+
tcx: TyCtxt<'tcx>,
962+
def_id: DefId,
963+
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
964+
) -> &'tcx ty::TypeckTables<'tcx> {
945965
// Closures' tables come from their outermost function,
946966
// as they are part of the same "inference environment".
947967
let outer_def_id = tcx.closure_base_def_id(def_id);
@@ -990,7 +1010,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
9901010
hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)),
9911011
_ => None,
9921012
})
993-
.unwrap_or_else(|| tcx.type_of(def_id));
1013+
.unwrap_or_else(fallback);
9941014
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
9951015
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
9961016

src/librustc_typeck/collect.rs

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,7 @@ crate fn placeholder_type_error(
160160
format!(", {}", type_name),
161161
));
162162
}
163-
let mut err = struct_span_err!(
164-
tcx.sess,
165-
placeholder_types.clone(),
166-
E0121,
167-
"the type placeholder `_` is not allowed within types on item signatures",
168-
);
169-
for span in &placeholder_types {
170-
err.span_label(*span, "not allowed in type signatures");
171-
}
163+
let mut err = bad_placeholder_type(tcx, placeholder_types);
172164
if suggest {
173165
err.multipart_suggestion(
174166
"use type parameters instead",
@@ -184,14 +176,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
184176
hir::ItemKind::Union(_, generics)
185177
| hir::ItemKind::Enum(_, generics)
186178
| hir::ItemKind::Struct(_, generics) => (&generics.params[..], true),
187-
hir::ItemKind::Static(ty, ..) => {
188-
if let hir::TyKind::Infer = ty.kind {
189-
return; // We handle it elsewhere to attempt to suggest an appropriate type.
190-
} else {
191-
(&[][..], false)
192-
}
193-
}
194179
hir::ItemKind::TyAlias(_, generics) => (&generics.params[..], false),
180+
// hir::ItemKind::Static(ty, ..) => {
195181
// hir::ItemKind::Fn(..) |
196182
// hir::ItemKind::Const(..) => {} // We handle these elsewhere to suggest appropriate type.
197183
_ => return,
@@ -255,15 +241,21 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
255241
///////////////////////////////////////////////////////////////////////////
256242
// Utility types and common code for the above passes.
257243

258-
fn bad_placeholder_type(tcx: TyCtxt<'tcx>, span: Span) -> errors::DiagnosticBuilder<'tcx> {
259-
let mut diag = struct_span_err!(
244+
fn bad_placeholder_type(
245+
tcx: TyCtxt<'tcx>,
246+
mut spans: Vec<Span>,
247+
) -> errors::DiagnosticBuilder<'tcx> {
248+
spans.sort();
249+
let mut err = struct_span_err!(
260250
tcx.sess,
261-
span,
251+
spans.clone(),
262252
E0121,
263253
"the type placeholder `_` is not allowed within types on item signatures",
264254
);
265-
diag.span_label(span, "not allowed in type signatures");
266-
diag
255+
for span in spans {
256+
err.span_label(span, "not allowed in type signatures");
257+
}
258+
err
267259
}
268260

269261
impl ItemCtxt<'tcx> {
@@ -298,7 +290,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
298290
}
299291

300292
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
301-
self.tcx().sess.delay_span_bug(span, "bad placeholder type, but no error was emitted");
293+
self.tcx().sess.delay_span_bug(span, "bad placeholder type");
302294
self.tcx().types.err
303295
}
304296

@@ -308,7 +300,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
308300
_: Option<&ty::GenericParamDef>,
309301
span: Span,
310302
) -> &'tcx Const<'tcx> {
311-
bad_placeholder_type(self.tcx(), span).emit();
303+
bad_placeholder_type(self.tcx(), vec![span]).emit();
312304

313305
self.tcx().consts.err
314306
}
@@ -1233,7 +1225,7 @@ fn infer_placeholder_type(
12331225
span: Span,
12341226
item_ident: Ident,
12351227
) -> Ty<'_> {
1236-
let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id);
1228+
let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id);
12371229

12381230
// If this came from a free `const` or `static mut?` item,
12391231
// then the user may have written e.g. `const A = 42;`.
@@ -1253,7 +1245,7 @@ fn infer_placeholder_type(
12531245
.emit();
12541246
}
12551247
None => {
1256-
let mut diag = bad_placeholder_type(tcx, span);
1248+
let mut diag = bad_placeholder_type(tcx, vec![span]);
12571249
if ty != tcx.types.err {
12581250
diag.span_suggestion(
12591251
span,
@@ -1284,12 +1276,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
12841276
}
12851277
TraitItemKind::Const(ref ty, body_id) => body_id
12861278
.and_then(|body_id| {
1287-
if let hir::TyKind::Infer = ty.kind {
1279+
if is_infer_ty(ty) {
12881280
Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident))
1289-
} else if is_infer_ty(ty) {
1290-
// Infering this would cause a cycle error.
1291-
tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted");
1292-
Some(tcx.types.err)
12931281
} else {
12941282
None
12951283
}
@@ -1307,12 +1295,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
13071295
tcx.mk_fn_def(def_id, substs)
13081296
}
13091297
ImplItemKind::Const(ref ty, body_id) => {
1310-
if let hir::TyKind::Infer = ty.kind {
1298+
if is_infer_ty(ty) {
13111299
infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
1312-
} else if is_infer_ty(ty) {
1313-
// Infering this would cause a cycle error.
1314-
tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted");
1315-
tcx.types.err
13161300
} else {
13171301
icx.to_ty(ty)
13181302
}
@@ -1336,12 +1320,8 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
13361320
Node::Item(item) => {
13371321
match item.kind {
13381322
ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => {
1339-
if let hir::TyKind::Infer = ty.kind {
1323+
if is_infer_ty(ty) {
13401324
infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)
1341-
} else if is_infer_ty(ty) {
1342-
// Infering this would cause a cycle error.
1343-
tcx.sess.delay_span_bug(ty.span, "`_` placeholder but no error emitted");
1344-
tcx.types.err
13451325
} else {
13461326
icx.to_ty(ty)
13471327
}
@@ -1818,7 +1798,7 @@ crate fn is_infer_ty(ty: &hir::Ty<'_>) -> bool {
18181798
hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) => is_infer_ty(ty),
18191799
hir::TyKind::Tup(tys)
18201800
if !tys.is_empty()
1821-
&& tys.iter().all(|ty| match ty.kind {
1801+
&& tys.iter().any(|ty| match ty.kind {
18221802
hir::TyKind::Infer => true,
18231803
_ => false,
18241804
}) =>
@@ -1858,12 +1838,14 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
18581838
match get_infer_ret_ty(&sig.decl.output) {
18591839
Some(ty) => {
18601840
let fn_sig = tcx.typeck_tables_of(def_id).liberated_fn_sigs()[hir_id];
1861-
let mut diag = bad_placeholder_type(tcx, ty.span);
1841+
let mut visitor = PlaceholderHirTyCollector::new();
1842+
visitor.visit_ty(ty);
1843+
let mut diag = bad_placeholder_type(tcx, visitor.0);
18621844
let ret_ty = fn_sig.output();
18631845
if ret_ty != tcx.types.err {
18641846
diag.span_suggestion(
18651847
ty.span,
1866-
"replace this with the correct return type",
1848+
"replace with the correct return type",
18671849
ret_ty.to_string(),
18681850
Applicability::MaybeIncorrect,
18691851
);

src/test/ui/error-codes/E0121.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | fn foo() -> _ { 5 }
55
| ^
66
| |
77
| not allowed in type signatures
8-
| help: replace this with the correct return type: `i32`
8+
| help: replace with the correct return type: `i32`
99

1010
error[E0121]: the type placeholder `_` is not allowed within types on item signatures
1111
--> $DIR/E0121.rs:3:13

src/test/ui/typeck/typeck_type_placeholder_item.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ fn test7(x: _) { let _x: usize = x; }
3030

3131
fn test8(_f: fn() -> _) { }
3232
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
33+
//~| ERROR the type placeholder `_` is not allowed within types on item signatures
3334

3435
struct Test9;
3536

@@ -79,6 +80,7 @@ pub fn main() {
7980

8081
fn fn_test8(_f: fn() -> _) { }
8182
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
83+
//~| ERROR the type placeholder `_` is not allowed within types on item signatures
8284

8385
struct FnTest9;
8486

@@ -128,4 +130,4 @@ trait T {
128130
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
129131
fn assoc_fn_test3() -> _;
130132
//~^ ERROR the type placeholder `_` is not allowed within types on item signatures
131-
}
133+
}

0 commit comments

Comments
 (0)