Skip to content

Commit 71bb0ff

Browse files
committed
Auto merge of #67597 - estebank:placeholder-type, r=oli-obk
Suggest type param when encountering `_` in item signatures Fix #27435.
2 parents bf2d145 + 261b606 commit 71bb0ff

9 files changed

+516
-119
lines changed

src/librustc/query/mod.rs

+10
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

+31-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
33
//! instance of `AstConv`.
44
5+
use crate::collect::PlaceholderHirTyCollector;
56
use crate::hir::def::{CtorOf, DefKind, Res};
67
use crate::hir::def_id::DefId;
8+
use crate::hir::intravisit::Visitor;
79
use crate::hir::print;
810
use crate::hir::{self, ExprKind, GenericArg, GenericArgs};
911
use crate::lint;
@@ -65,6 +67,9 @@ pub trait AstConv<'tcx> {
6567
/// Returns the type to use when a type is omitted.
6668
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
6769

70+
/// Returns `true` if `_` is allowed in type signatures in the current context.
71+
fn allow_ty_infer(&self) -> bool;
72+
6873
/// Returns the const to use when a const is omitted.
6974
fn ct_infer(
7075
&self,
@@ -2591,7 +2596,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25912596
}
25922597
hir::TyKind::BareFn(ref bf) => {
25932598
require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
2594-
tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl))
2599+
tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None))
25952600
}
25962601
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
25972602
self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime)
@@ -2756,14 +2761,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27562761
unsafety: hir::Unsafety,
27572762
abi: abi::Abi,
27582763
decl: &hir::FnDecl<'_>,
2764+
generic_params: &[hir::GenericParam<'_>],
2765+
ident_span: Option<Span>,
27592766
) -> ty::PolyFnSig<'tcx> {
27602767
debug!("ty_of_fn");
27612768

27622769
let tcx = self.tcx();
2763-
let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
27642770

2771+
// We proactively collect all the infered type params to emit a single error per fn def.
2772+
let mut visitor = PlaceholderHirTyCollector::default();
2773+
for ty in decl.inputs {
2774+
visitor.visit_ty(ty);
2775+
}
2776+
let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None));
27652777
let output_ty = match decl.output {
2766-
hir::Return(ref output) => self.ast_ty_to_ty(output),
2778+
hir::Return(ref output) => {
2779+
visitor.visit_ty(output);
2780+
self.ast_ty_to_ty(output)
2781+
}
27672782
hir::DefaultReturn(..) => tcx.mk_unit(),
27682783
};
27692784

@@ -2772,6 +2787,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
27722787
let bare_fn_ty =
27732788
ty::Binder::bind(tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, unsafety, abi));
27742789

2790+
if !self.allow_ty_infer() {
2791+
// We always collect the spans for placeholder types when evaluating `fn`s, but we
2792+
// only want to emit an error complaining about them if infer types (`_`) are not
2793+
// allowed. `allow_ty_infer` gates this behavior.
2794+
crate::collect::placeholder_type_error(
2795+
tcx,
2796+
ident_span.unwrap_or(DUMMY_SP),
2797+
generic_params,
2798+
visitor.0,
2799+
ident_span.is_some(),
2800+
);
2801+
}
2802+
27752803
// Find any late-bound regions declared in return type that do
27762804
// not appear in the arguments. These are not well-formed.
27772805
//

src/librustc_typeck/check/mod.rs

+33-3
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,31 @@ 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+
assert!(def_id.is_local());
957+
let fallback = move || {
958+
let span = tcx.hir().span(tcx.hir().as_local_hir_id(def_id).unwrap());
959+
tcx.sess.delay_span_bug(span, "diagnostic only typeck table used");
960+
tcx.types.err
961+
};
962+
typeck_tables_of_with_fallback(tcx, def_id, fallback)
963+
}
964+
965+
fn typeck_tables_of_with_fallback<'tcx>(
966+
tcx: TyCtxt<'tcx>,
967+
def_id: DefId,
968+
fallback: impl Fn() -> Ty<'tcx> + 'tcx,
969+
) -> &'tcx ty::TypeckTables<'tcx> {
945970
// Closures' tables come from their outermost function,
946971
// as they are part of the same "inference environment".
947972
let outer_def_id = tcx.closure_base_def_id(def_id);
@@ -963,7 +988,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
963988
let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) {
964989
let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
965990
let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
966-
AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl)
991+
AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None)
967992
} else {
968993
tcx.fn_sig(def_id)
969994
};
@@ -990,7 +1015,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
9901015
hir::TyKind::Infer => Some(AstConv::ast_ty_to_ty(&fcx, ty)),
9911016
_ => None,
9921017
})
993-
.unwrap_or_else(|| tcx.type_of(def_id));
1018+
.unwrap_or_else(fallback);
9941019
let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type);
9951020
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
9961021

@@ -1069,6 +1094,7 @@ fn typeck_tables_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TypeckTables<'_> {
10691094
let ty = fcx.normalize_ty(span, ty);
10701095
fcx.require_type_is_sized(ty, span, code);
10711096
}
1097+
10721098
fcx.select_all_obligations_or_error();
10731099

10741100
if fn_decl.is_some() {
@@ -2563,6 +2589,10 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
25632589
Some(self.next_region_var(v))
25642590
}
25652591

2592+
fn allow_ty_infer(&self) -> bool {
2593+
true
2594+
}
2595+
25662596
fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
25672597
if let Some(param) = param {
25682598
if let GenericArgKind::Type(ty) = self.var_for_def(span, param).unpack() {

0 commit comments

Comments
 (0)