From a7b727dab3aff466fc88c3ce0916817dc2d093bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Feb 2020 13:34:00 -0800 Subject: [PATCH] Account for bounds when denying `_` in type parameters --- src/librustc_typeck/astconv.rs | 22 +++++++- src/test/ui/did_you_mean/bad-assoc-ty.rs | 4 ++ src/test/ui/did_you_mean/bad-assoc-ty.stderr | 10 +++- .../ui/typeck/typeck_type_placeholder_item.rs | 5 ++ .../typeck_type_placeholder_item.stderr | 50 +++++++++++++++---- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 49f38d86d916..d1a6163df2d0 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -514,7 +514,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Option>, arg_count_correct: bool, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), - provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, + mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( Option<&[subst::GenericArg<'tcx>]>, &GenericParamDef, @@ -751,6 +751,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let mut missing_type_params = vec![]; + let mut inferred_params = vec![]; let substs = Self::create_substs_for_generic_args( tcx, def_id, @@ -773,7 +774,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(<, Some(param)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.ast_ty_to_ty(&ty).into() + if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) { + inferred_params.push(ty.span); + tcx.types.err.into() + } else { + self.ast_ty_to_ty(&ty).into() + } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into() @@ -832,6 +838,18 @@ 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, 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 fccfb7911cec..00845a17b116 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -45,4 +45,8 @@ type I = ty!()::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR ambiguous associated type +trait K {} +fn foo>(x: X) {} +//~^ 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 64e49934d876..6d5f3d9f1434 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -122,7 +122,15 @@ error[E0223]: ambiguous associated type LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 19 previous errors +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:49:13 + | +LL | fn foo>(x: X) {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 20 previous errors Some errors have detailed explanations: E0121, E0223. 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 86c7c52b2716..8ee46343d2d5 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -157,9 +157,12 @@ 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!() } @@ -174,12 +177,14 @@ 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 95e8f94c6f3e..18317d2b9748 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:166:19 + --> $DIR/typeck_type_placeholder_item.rs:169:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:174:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -343,6 +343,18 @@ 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:158: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:158: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:158:15 | @@ -357,13 +369,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:161:34 + --> $DIR/typeck_type_placeholder_item.rs:163: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:166:25 + --> $DIR/typeck_type_placeholder_item.rs:169:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -374,7 +386,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 + --> $DIR/typeck_type_placeholder_item.rs:174:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -385,7 +397,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:14 + --> $DIR/typeck_type_placeholder_item.rs:178: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:178:14 | LL | type X = Box<_>; | ^ not allowed in type signatures @@ -505,7 +523,19 @@ 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:181:21 + --> $DIR/typeck_type_placeholder_item.rs:163: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:185: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:185:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures @@ -546,7 +576,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 58 previous errors +error: aborting due to 63 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`.