From e75158d4861e8cd0b0f8a11f360714c56577ba1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 22 Mar 2020 18:50:30 -0700 Subject: [PATCH] Account for bad placeholder types in where clauses --- src/librustc_typeck/astconv.rs | 34 +++--- src/librustc_typeck/check/mod.rs | 9 +- src/librustc_typeck/collect.rs | 22 ++-- src/test/ui/did_you_mean/bad-assoc-ty.rs | 32 +++++ src/test/ui/did_you_mean/bad-assoc-ty.stderr | 110 +++++++++++++++++- .../ui/typeck/typeck_type_placeholder_item.rs | 5 - .../typeck_type_placeholder_item.stderr | 66 +++-------- 7 files changed, 192 insertions(+), 86 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3ee6d5df7356b..378a68315b289 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -20,7 +20,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{walk_generics, Visitor}; use rustc_hir::print; use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; @@ -838,18 +838,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }, ); - if !inferred_params.is_empty() { - // We always collect the spans for placeholder types when evaluating `fn`s, but we - // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_ty_infer` gates this behavior. - crate::collect::placeholder_type_error( - tcx, - inferred_params[0], - &[], - inferred_params, - false, - ); - } self.complain_about_missing_type_params( missing_type_params, @@ -2739,7 +2727,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::TyKind::BareFn(ref bf) => { require_c_abi_if_c_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn(bf.unsafety, bf.abi, &bf.decl, &[], None)) + tcx.mk_fn_ptr(self.ty_of_fn( + bf.unsafety, + bf.abi, + &bf.decl, + &hir::Generics::empty(), + None, + )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) @@ -2922,7 +2916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { unsafety: hir::Unsafety, abi: abi::Abi, decl: &hir::FnDecl<'_>, - generic_params: &[hir::GenericParam<'_>], + generics: &hir::Generics<'_>, ident_span: Option, ) -> ty::PolyFnSig<'tcx> { debug!("ty_of_fn"); @@ -2934,6 +2928,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for ty in decl.inputs { visitor.visit_ty(ty); } + walk_generics(&mut visitor, generics); + let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { hir::FnRetTy::Return(ref output) => { @@ -2955,7 +2951,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { crate::collect::placeholder_type_error( tcx, ident_span.map(|sp| sp.shrink_to_hi()).unwrap_or(DUMMY_SP), - generic_params, + &generics.params[..], visitor.0, ident_span.is_some(), ); @@ -2981,8 +2977,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.sess, decl.output.span(), E0581, - "return type references {} \ - which is not constrained by the fn input types", + "return type references {} which is not constrained by the fn input types", lifetime_name ); if let ty::BrAnon(_) = *br { @@ -2993,8 +2988,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // though we can easily give a hint that ought to be // relevant. err.note( - "lifetimes appearing in an associated type \ - are not considered constrained", + "lifetimes appearing in an associated type are not considered constrained", ); } err.emit(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e4bd42f61c321..ce0be5083573c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1003,7 +1003,14 @@ fn typeck_tables_of_with_fallback<'tcx>( let fcx = if let (Some(header), Some(decl)) = (fn_header, fn_decl) { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); - AstConv::ty_of_fn(&fcx, header.unsafety, header.abi, decl, &[], None) + AstConv::ty_of_fn( + &fcx, + header.unsafety, + header.abi, + decl, + &hir::Generics::empty(), + None, + ) } else { tcx.fn_sig(def_id) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a79c065307796..2de43a6b1ef15 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1502,7 +1502,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { sig.header.unsafety, sig.header.abi, &sig.decl, - &generics.params[..], + &generics, Some(ident.span), ), } @@ -1513,14 +1513,9 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ident, generics, .. - }) => AstConv::ty_of_fn( - &icx, - header.unsafety, - header.abi, - decl, - &generics.params[..], - Some(ident.span), - ), + }) => { + AstConv::ty_of_fn(&icx, header.unsafety, header.abi, decl, &generics, Some(ident.span)) + } ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(ref fn_decl, _, _), .. }) => { let abi = tcx.hir().get_foreign_abi(hir_id); @@ -2142,7 +2137,14 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; - let fty = AstConv::ty_of_fn(&ItemCtxt::new(tcx, def_id), unsafety, abi, decl, &[], None); + let fty = AstConv::ty_of_fn( + &ItemCtxt::new(tcx, def_id), + unsafety, + abi, + decl, + &hir::Generics::empty(), + None, + ); // Feature gate SIMD types in FFI, since I am not sure that the // ABIs are handled at all correctly. -huonw diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index 00845a17b116b..e66b432ede20c 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -49,4 +49,36 @@ trait K {} fn foo>(x: X) {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +fn bar(_: F) where F: Fn() -> _ {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +fn baz _>(_: F) {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + +struct L(F) where F: Fn() -> _; +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +struct M where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + a: F, +} +enum N where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + Foo(F), +} + +union O where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR unions with non-`Copy` fields are unstable + foo: F, +} + +trait P where F: Fn() -> _ { +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + +trait Q { + fn foo(_: F) where F: Fn() -> _ {} + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} + fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 6d5f3d9f14348..875c02bae4ae0 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -57,6 +57,19 @@ LL | type J = ty!(u8); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +error[E0658]: unions with non-`Copy` fields are unstable + --> $DIR/bad-assoc-ty.rs:69:1 + | +LL | / union O where F: Fn() -> _ { +LL | | +LL | | +LL | | foo: F, +LL | | } + | |_^ + | + = note: see issue #55149 for more information + = help: add `#![feature(untagged_unions)]` to the crate attributes to enable + error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:1:10 | @@ -129,8 +142,101 @@ LL | fn foo>(x: X) {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo>(x: X) {} + | ^^^ ^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:52:34 + | +LL | fn bar(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn bar(_: F) where F: Fn() -> T {} + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:55:19 + | +LL | fn baz _>(_: F) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn baz T>(_: F) {} + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:58:33 + | +LL | struct L(F) where F: Fn() -> _; + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct L(F) where F: Fn() -> T; + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:60:30 + | +LL | struct M where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | struct M where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:64:28 + | +LL | enum N where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | enum N where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:69:29 + | +LL | union O where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | union O where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:75:29 + | +LL | trait P where F: Fn() -> _ { + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | trait P where F: Fn() -> T { + | ^^^ ^ + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:80:38 + | +LL | fn foo(_: F) where F: Fn() -> _ {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn foo(_: F) where F: Fn() -> T {} + | ^^^ ^ -error: aborting due to 20 previous errors +error: aborting due to 29 previous errors -Some errors have detailed explanations: E0121, E0223. +Some errors have detailed explanations: E0121, E0223, E0658. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 6cd2b8c75b639..5444fc62d8211 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -158,12 +158,9 @@ trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -178,14 +175,12 @@ struct BadStruct2<_, T>(_, T); type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index dc86ab30dfe41..955765e1175ce 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -11,25 +11,25 @@ LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:19 + --> $DIR/typeck_type_placeholder_item.rs:167:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:167:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:175:19 + --> $DIR/typeck_type_placeholder_item.rs:172:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:208:5 + --> $DIR/typeck_type_placeholder_item.rs:203:5 | LL | const C: _; | ^^^^^^^^^^- @@ -37,7 +37,7 @@ LL | const C: _; | help: provide a definition for the constant: `= ;` error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:170:22 + --> $DIR/typeck_type_placeholder_item.rs:167:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -351,18 +351,6 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:32 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:159:15 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:159:15 | @@ -377,13 +365,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 + --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:25 + --> $DIR/typeck_type_placeholder_item.rs:167:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -394,7 +382,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:25 + --> $DIR/typeck_type_placeholder_item.rs:172:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -405,13 +393,7 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 - | -LL | type X = Box<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:14 + --> $DIR/typeck_type_placeholder_item.rs:176:14 | LL | type X = Box<_>; | ^ not allowed in type signatures @@ -531,37 +513,25 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:34 - | -LL | fn impl_trait() -> impl BadTrait<_> { - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 - | -LL | type Y = impl Trait<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:186:21 + --> $DIR/typeck_type_placeholder_item.rs:182:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:195:14 + --> $DIR/typeck_type_placeholder_item.rs:190:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:197:14 + --> $DIR/typeck_type_placeholder_item.rs:192:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:199:14 + --> $DIR/typeck_type_placeholder_item.rs:194:14 | LL | const D: _ = 42; | ^ @@ -606,25 +576,25 @@ LL | fn clone(&self) -> _ { FnTest9 } | help: replace with the correct return type: `main::FnTest9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:204:14 + --> $DIR/typeck_type_placeholder_item.rs:199:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:206:14 + --> $DIR/typeck_type_placeholder_item.rs:201:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:203:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:211:14 + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | const D: _ = 42; | ^ @@ -632,7 +602,7 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace `_` with the correct type: `i32` -error: aborting due to 71 previous errors +error: aborting due to 66 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`.