From ef7bda3b62b7d6821acb4603e2c72b7120b02059 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 25 Aug 2022 11:12:04 +0200 Subject: [PATCH] no unnormalized types for implied bounds --- .../src/traits/engine.rs | 13 ++++++++- .../impl-header-unnormalized-types.rs | 28 +++++++++++++++++++ .../impl-header-unnormalized-types.stderr | 20 +++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/implied-bounds/impl-header-unnormalized-types.rs create mode 100644 src/test/ui/implied-bounds/impl-header-unnormalized-types.stderr diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 136b94321459e..72533a42d8078 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -124,7 +124,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let cause = ObligationCause::misc(span, hir_id); for ty in assumed_wf_types { - implied_bounds.insert(ty); + // FIXME(@lcnr): rustc currently does not check wf for types + // pre-normalization, meaning that implied bounds are sometimes + // incorrect. See #100910 for more details. + // + // Not adding the unnormalized types here mostly fixes that, except + // that there are projections which are still ambiguous in the item definition + // but do normalize successfully when using the item, see #98543. + // + // Anyways, I will hopefully soon change implied bounds to make all of this + // sound and then uncomment this line again. + + // implied_bounds.insert(ty); let normalized = self.normalize(cause.clone(), param_env, ty); implied_bounds.insert(normalized); } diff --git a/src/test/ui/implied-bounds/impl-header-unnormalized-types.rs b/src/test/ui/implied-bounds/impl-header-unnormalized-types.rs new file mode 100644 index 0000000000000..d84539f8ab525 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-header-unnormalized-types.rs @@ -0,0 +1,28 @@ +struct Foo(T); + +trait GoodBye { + type Forget; +} +impl GoodBye for T { + type Forget = (); +} + +trait NeedsWf<'a, 'b> { + type Assoc; +} + +impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + type Assoc = &'a &'b (); + //~^ ERROR in type `&'a &'b ()`, reference has a longer lifetime than the data it references +} + +fn needs_wf<'a, 'b, T: NeedsWf<'a, 'b>>() {} + +fn foo<'a: 'a, 'b: 'b>(_: &'b String) { + needs_wf::<'a, 'b, Foo<()>>(); +} + +fn main() { + let x = String::from("hello"); + foo::<'static, '_>(&x); +} diff --git a/src/test/ui/implied-bounds/impl-header-unnormalized-types.stderr b/src/test/ui/implied-bounds/impl-header-unnormalized-types.stderr new file mode 100644 index 0000000000000..88abd5f54c2a6 --- /dev/null +++ b/src/test/ui/implied-bounds/impl-header-unnormalized-types.stderr @@ -0,0 +1,20 @@ +error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references + --> $DIR/impl-header-unnormalized-types.rs:15:18 + | +LL | type Assoc = &'a &'b (); + | ^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/impl-header-unnormalized-types.rs:14:6 + | +LL | impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/impl-header-unnormalized-types.rs:14:10 + | +LL | impl<'a, 'b> NeedsWf<'a, 'b> for Foo<<&'a &'b () as GoodBye>::Forget> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0491`.