From b80c1aece9f475da029ca37dcc79cc7cedc553ff Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 7 Jun 2024 15:05:28 +0000 Subject: [PATCH] Use the error variance for unused generic args --- .../rustc_hir_analysis/src/check/wfcheck.rs | 38 +++++++++---------- .../rustc_hir_analysis/src/variance/mod.rs | 6 ++- .../src/infer/relate/generalize.rs | 5 +++ compiler/rustc_infer/src/infer/relate/glb.rs | 6 ++- compiler/rustc_infer/src/infer/relate/lub.rs | 6 ++- .../src/infer/relate/type_relating.rs | 28 +++++++++----- ...rong-projection-self-ty-on-invalid-type.rs | 11 ++++++ ...-projection-self-ty-on-invalid-type.stderr | 25 ++++++++++++ .../dont-collect-stmts-from-parent-body.rs | 1 - ...dont-collect-stmts-from-parent-body.stderr | 16 +------- tests/ui/traits/trait-selection-ice-84727.rs | 1 + .../traits/trait-selection-ice-84727.stderr | 34 ++++++++++++++--- tests/ui/variance/variance-regions-direct.rs | 3 +- .../variance/variance-regions-direct.stderr | 2 +- .../ui/variance/variance-regions-indirect.rs | 12 ++++-- .../variance/variance-regions-indirect.stderr | 8 ++-- tests/ui/variance/variance-trait-bounds.rs | 9 +++-- .../ui/variance/variance-trait-bounds.stderr | 6 +-- 18 files changed, 146 insertions(+), 71 deletions(-) create mode 100644 tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.rs create mode 100644 tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.stderr diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index f9486186f8ddb..b3d836c213f27 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1802,8 +1802,8 @@ fn receiver_is_implemented<'tcx>( pub fn check_variances_for_type_defn<'tcx>( tcx: TyCtxt<'tcx>, item: LocalDefId, - variances: &[ty::Variance], -) -> Result<(), ErrorGuaranteed> { + variances: &'tcx [ty::Variance], +) -> Result<&'tcx [ty::Variance], ErrorGuaranteed> { let identity_args = ty::GenericArgs::identity_for_item(tcx, item); match tcx.def_kind(item) { @@ -1819,7 +1819,7 @@ pub fn check_variances_for_type_defn<'tcx>( ); tcx.type_of(item).skip_binder().error_reported()?; } - _ => return Ok(()), + _ => return Ok(variances), } let ty_predicates = tcx.predicates_of(item); @@ -1856,7 +1856,7 @@ pub fn check_variances_for_type_defn<'tcx>( let ty_generics = tcx.generics_of(item); - let mut res = Ok(()); + let mut variances = variances; for (index, _) in variances.iter().enumerate() { let parameter = Parameter(index as u32); @@ -1868,7 +1868,7 @@ pub fn check_variances_for_type_defn<'tcx>( let ty_param = &ty_generics.own_params[index]; let hir_param = &hir_generics.params[index]; - if ty_param.def_id != hir_param.def_id.into() { + let guar = if ty_param.def_id != hir_param.def_id.into() { // Valid programs always have lifetimes before types in the generic parameter list. // ty_generics are normalized to be in this required order, and variances are built // from ty generics, not from hir generics. but we need hir generics to get @@ -1876,22 +1876,22 @@ pub fn check_variances_for_type_defn<'tcx>( // // If they aren't in the same order, then the user has written invalid code, and already // got an error about it (or I'm wrong about this). - tcx.dcx().span_delayed_bug( - hir_param.span, - "hir generics and ty generics in different order", - ); - continue; - } - - match hir_param.name { - hir::ParamName::Error(guar) => res = Err(guar), - _ => { - let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); - res = Err(report_bivariance(tcx, hir_param, has_explicit_bounds, item)); + tcx.dcx() + .span_delayed_bug(hir_param.span, "hir generics and ty generics in different order") + } else { + match hir_param.name { + hir::ParamName::Error(guar) => guar, + _ => { + let has_explicit_bounds = explicitly_bounded_params.contains(¶meter); + report_bivariance(tcx, hir_param, has_explicit_bounds, item) + } } - } + }; + let mut v = variances.to_vec(); + v[index] = ty::Variance::Errvariant(guar); + variances = tcx.arena.alloc_slice(&v); } - res + Ok(variances) } fn report_bivariance( diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 043fea52d1e3e..0380e547893a3 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -72,8 +72,10 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { } }; - let _ = crate::check::wfcheck::check_variances_for_type_defn(tcx, item_def_id, variances); - variances + match crate::check::wfcheck::check_variances_for_type_defn(tcx, item_def_id, variances) { + Ok(variances) => variances, + Err(guar) => tcx.arena.alloc_from_iter(variances.iter().map(|_| ty::Errvariant(guar))), + } } #[instrument(level = "trace", skip(tcx), ret)] diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 932050b7c9f13..2f0185f7e6fd6 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -501,6 +501,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // `Generalization`. ty::Bivariant => self.has_unconstrained_ty_var = true, + ty::Errvariant(guar) => { + self.infcx.set_tainted_by_errors(guar); + return Ok(Ty::new_error(self.tcx(), guar)); + } + // Co/contravariant: this will be // sufficiently constrained later on. ty::Covariant | ty::Contravariant => (), diff --git a/compiler/rustc_infer/src/infer/relate/glb.rs b/compiler/rustc_infer/src/infer/relate/glb.rs index ec9da095fb038..909303178128b 100644 --- a/compiler/rustc_infer/src/infer/relate/glb.rs +++ b/compiler/rustc_infer/src/infer/relate/glb.rs @@ -40,8 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { match variance { ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b), ty::Covariant => self.relate(a, b), - // TODO: report a new error kind - ty::Errvariant(_) => Ok(a), + ty::Errvariant(guar) => { + self.fields.infcx.set_tainted_by_errors(guar); + Ok(a) + } // FIXME(#41044) -- not correct, need test ty::Bivariant => Ok(a), ty::Contravariant => self.fields.lub().relate(a, b), diff --git a/compiler/rustc_infer/src/infer/relate/lub.rs b/compiler/rustc_infer/src/infer/relate/lub.rs index b2154262bb6ec..ea5ad4338e3da 100644 --- a/compiler/rustc_infer/src/infer/relate/lub.rs +++ b/compiler/rustc_infer/src/infer/relate/lub.rs @@ -40,8 +40,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> { match variance { ty::Invariant => self.fields.equate(StructurallyRelateAliases::No).relate(a, b), ty::Covariant => self.relate(a, b), - // TODO: report a new kind of type error that preserves the `ErrorGuaranteed`? - ty::Errvariant(_) => Ok(a), + ty::Errvariant(guar) => { + self.fields.infcx.set_tainted_by_errors(guar); + Ok(a) + } // FIXME(#41044) -- not correct, need test ty::Bivariant => Ok(a), ty::Contravariant => self.fields.glb().relate(a, b), diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index bb1067f04861f..e7f50d702c262 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -117,7 +117,11 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { ty::Invariant => { infcx.inner.borrow_mut().type_variables().equate(a_id, b_id); } - ty::Errvariant(_) | ty::Bivariant => { + ty::Errvariant(guar) => { + infcx.set_tainted_by_errors(guar); + return Ok(Ty::new_error(self.tcx(), guar)); + } + ty::Bivariant => { unreachable!("Expected bivariance to be handled in relate_with_variance") } } @@ -204,7 +208,11 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { .unwrap_region_constraints() .make_eqregion(origin, a, b); } - ty::Errvariant(_) | ty::Bivariant => { + ty::Errvariant(guar) => { + self.fields.infcx.set_tainted_by_errors(guar); + return Ok(ty::Region::new_error(self.tcx(), guar)); + } + ty::Bivariant => { unreachable!("Expected bivariance to be handled in relate_with_variance") } } @@ -289,15 +297,15 @@ impl<'tcx> TypeRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { self.relate(a, b) })?; } - ty::Errvariant(_) | ty::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - } ty::Errvariant(guar) => { infcx.set_tainted_by_errors(guar); return self.relate(a, b); } ty::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + } + } Ok(a) } @@ -345,13 +353,13 @@ impl<'tcx> ObligationEmittingRelation<'tcx> for TypeRelating<'_, '_, 'tcx> { b.into(), ty::AliasRelationDirection::Equate, ), - ty::Variance::Errvariant(_) | ty::Variance::Bivariant => { - unreachable!("Expected bivariance to be handled in relate_with_variance") - } - })]); ty::Variance::Errvariant(guar) => { self.fields.infcx.set_tainted_by_errors(guar); ty::PredicateKind::Ambiguous } ty::Variance::Bivariant => { + unreachable!("Expected bivariance to be handled in relate_with_variance") + } + })]); + } } diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.rs b/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.rs new file mode 100644 index 0000000000000..5a1eeaa0a85ed --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.rs @@ -0,0 +1,11 @@ +struct Fail; +//~^ ERROR: type parameter `T` is never used + +impl Fail { + const C: () = (); +} + +fn main() { + Fail::<()>::C + //~^ ERROR: no associated item named `C` found for struct `Fail<()>` +} diff --git a/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.stderr b/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.stderr new file mode 100644 index 0000000000000..cd97efeafffaa --- /dev/null +++ b/tests/ui/associated-consts/wrong-projection-self-ty-on-invalid-type.stderr @@ -0,0 +1,25 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/wrong-projection-self-ty-on-invalid-type.rs:1:13 + | +LL | struct Fail; + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0599]: no associated item named `C` found for struct `Fail<()>` in the current scope + --> $DIR/wrong-projection-self-ty-on-invalid-type.rs:9:17 + | +LL | struct Fail; + | -------------- associated item `C` not found for this struct +... +LL | Fail::<()>::C + | ^ associated item not found in `Fail<()>` + | + = note: the associated item was found for + - `Fail` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0599. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/inference/dont-collect-stmts-from-parent-body.rs b/tests/ui/inference/dont-collect-stmts-from-parent-body.rs index 635fe74b8679d..752c595bb9974 100644 --- a/tests/ui/inference/dont-collect-stmts-from-parent-body.rs +++ b/tests/ui/inference/dont-collect-stmts-from-parent-body.rs @@ -8,7 +8,6 @@ fn main() { impl Type { fn new() -> Type { Type - //~^ ERROR type annotations needed } } }; diff --git a/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr b/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr index f82527273fbee..543b834332ca3 100644 --- a/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr +++ b/tests/ui/inference/dont-collect-stmts-from-parent-body.stderr @@ -7,18 +7,6 @@ LL | struct Type; = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error[E0282]: type annotations needed - --> $DIR/dont-collect-stmts-from-parent-body.rs:10:17 - | -LL | Type - | ^^^^ cannot infer type of the type parameter `T` declared on the struct `Type` - | -help: consider specifying the generic argument - | -LL | Type:: - | +++++ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0282, E0392. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/traits/trait-selection-ice-84727.rs b/tests/ui/traits/trait-selection-ice-84727.rs index 08a282892a59c..b7482753be4d5 100644 --- a/tests/ui/traits/trait-selection-ice-84727.rs +++ b/tests/ui/traits/trait-selection-ice-84727.rs @@ -20,6 +20,7 @@ where { fn over(self) -> Cell { //~^ ERROR mismatched types + //~| ERROR `over` has an incompatible type for trait self.over(); } } diff --git a/tests/ui/traits/trait-selection-ice-84727.stderr b/tests/ui/traits/trait-selection-ice-84727.stderr index d4bc4163897c4..83f3b7ad95472 100644 --- a/tests/ui/traits/trait-selection-ice-84727.stderr +++ b/tests/ui/traits/trait-selection-ice-84727.stderr @@ -17,7 +17,7 @@ LL | Self: Over, Cell>, | ^^^^^ not found in this scope error[E0412]: cannot find type `NewBg` in this scope - --> $DIR/trait-selection-ice-84727.rs:32:27 + --> $DIR/trait-selection-ice-84727.rs:33:27 | LL | fn over(self) -> Cell { | ^^^^^ not found in this scope @@ -27,6 +27,30 @@ help: you might be missing a type parameter LL | impl<'b, TopFg, TopBg, BottomFg, BottomBg, NewBg> Over<&Cell, ()> | +++++++ +error[E0053]: method `over` has an incompatible type for trait + --> $DIR/trait-selection-ice-84727.rs:21:22 + | +LL | impl + | ----- ----- expected type parameter + | | + | found type parameter +... +LL | fn over(self) -> Cell { + | ^^^^^^^^^^^ + | | + | expected type parameter `NewBg`, found type parameter `NewFg` + | help: change the output type to match the trait: `Cell` + | +note: type in trait + --> $DIR/trait-selection-ice-84727.rs:12:22 + | +LL | fn over(self) -> Output; + | ^^^^^^ + = note: expected signature `fn(Cell<_, _>) -> Cell<_, NewBg>` + found signature `fn(Cell<_, _>) -> Cell<_, NewFg>` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters + error[E0308]: mismatched types --> $DIR/trait-selection-ice-84727.rs:21:22 | @@ -34,14 +58,14 @@ LL | fn over(self) -> Cell { | ---- ^^^^^^^^^^^ expected `Cell`, found `()` | | | implicitly returns `()` as its body has no tail or `return` expression -LL | +... LL | self.over(); | - help: remove this semicolon to return this value | = note: expected struct `Cell` found unit type `()` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0308, E0412. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0053, E0308, E0412. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/variance/variance-regions-direct.rs b/tests/ui/variance/variance-regions-direct.rs index f1763c403f1a1..9b4a4f1271d00 100644 --- a/tests/ui/variance/variance-regions-direct.rs +++ b/tests/ui/variance/variance-regions-direct.rs @@ -49,7 +49,8 @@ struct Test6<'a, 'b:'a> { //~ ERROR [+, o] // No uses at all is bivariant: #[rustc_variance] -struct Test7<'a> { //~ ERROR [*] +struct Test7<'a> { + //~ ERROR [{error}] //~^ ERROR: `'a` is never used x: isize } diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr index edfc888f65667..5af8217623044 100644 --- a/tests/ui/variance/variance-regions-direct.stderr +++ b/tests/ui/variance/variance-regions-direct.stderr @@ -36,7 +36,7 @@ error: [+, o] LL | struct Test6<'a, 'b:'a> { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: [*] +error: [💥] --> $DIR/variance-regions-direct.rs:52:1 | LL | struct Test7<'a> { diff --git a/tests/ui/variance/variance-regions-indirect.rs b/tests/ui/variance/variance-regions-indirect.rs index 31e25641d8c3a..36f5f02f6f550 100644 --- a/tests/ui/variance/variance-regions-indirect.rs +++ b/tests/ui/variance/variance-regions-indirect.rs @@ -5,7 +5,8 @@ #![feature(rustc_attrs)] #[rustc_variance] -enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] +enum Base<'a, 'b, 'c: 'b, 'd> { + //~ ERROR [-, +, o, {error}] //~^ ERROR: `'d` is never used Test8A(extern "Rust" fn(&'a isize)), Test8B(&'b [isize]), @@ -13,19 +14,22 @@ enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR [-, +, o, *] } #[rustc_variance] -struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR [*, o, +, -] +struct Derived1<'w, 'x: 'y, 'y, 'z> { + //~ ERROR [{error}, o, +, -] //~^ ERROR: `'w` is never used f: Base<'z, 'y, 'x, 'w> } #[rustc_variance] // Combine - and + to yield o -struct Derived2<'a, 'b:'a, 'c> { //~ ERROR [o, o, *] +struct Derived2<'a, 'b: 'a, 'c> { + //~ ERROR [o, o, {error}] //~^ ERROR: `'c` is never used f: Base<'a, 'a, 'b, 'c> } #[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here) -struct Derived3<'a:'b, 'b, 'c> { //~ ERROR [o, +, *] +struct Derived3<'a: 'b, 'b, 'c> { + //~ ERROR [o, +, {error}] //~^ ERROR: `'c` is never used f: Base<'a, 'b, 'a, 'c> } diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr index 901ec0c6a762b..26e8fedcca42a 100644 --- a/tests/ui/variance/variance-regions-indirect.stderr +++ b/tests/ui/variance/variance-regions-indirect.stderr @@ -30,25 +30,25 @@ LL | struct Derived3<'a:'b, 'b, 'c> { | = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` -error: [-, +, o, *] +error: [-, +, o, 💥] --> $DIR/variance-regions-indirect.rs:8:1 | LL | enum Base<'a, 'b, 'c:'b, 'd> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, o, +, -] +error: [💥, o, +, -] --> $DIR/variance-regions-indirect.rs:16:1 | LL | struct Derived1<'w, 'x:'y, 'y, 'z> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, o, *] +error: [o, o, 💥] --> $DIR/variance-regions-indirect.rs:22:1 | LL | struct Derived2<'a, 'b:'a, 'c> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [o, +, *] +error: [o, +, 💥] --> $DIR/variance-regions-indirect.rs:28:1 | LL | struct Derived3<'a:'b, 'b, 'c> { diff --git a/tests/ui/variance/variance-trait-bounds.rs b/tests/ui/variance/variance-trait-bounds.rs index 25a01b160ddd1..a3c920e53449d 100644 --- a/tests/ui/variance/variance-trait-bounds.rs +++ b/tests/ui/variance/variance-trait-bounds.rs @@ -18,19 +18,22 @@ struct TestStruct> { //~ ERROR [+, +] } #[rustc_variance] -enum TestEnum> { //~ ERROR [*, +] +enum TestEnum> { + //~ ERROR [{error}, +] //~^ ERROR: `U` is never used Foo(T) } #[rustc_variance] -struct TestContraStruct> { //~ ERROR [*, +] +struct TestContraStruct> { + //~ ERROR [{error}, +] //~^ ERROR: `U` is never used t: T } #[rustc_variance] -struct TestBox+Setter> { //~ ERROR [*, +] +struct TestBox + Setter> { + //~ ERROR [{error}, +] //~^ ERROR: `U` is never used t: T } diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr index 95ed18c1ad2bf..dc9dd109635aa 100644 --- a/tests/ui/variance/variance-trait-bounds.stderr +++ b/tests/ui/variance/variance-trait-bounds.stderr @@ -31,19 +31,19 @@ error: [+, +] LL | struct TestStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [💥, +] --> $DIR/variance-trait-bounds.rs:21:1 | LL | enum TestEnum> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [💥, +] --> $DIR/variance-trait-bounds.rs:27:1 | LL | struct TestContraStruct> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: [*, +] +error: [💥, +] --> $DIR/variance-trait-bounds.rs:33:1 | LL | struct TestBox+Setter> {