From 558cfd2b5ed758d804b53f9cf183f51309019336 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 20:59:26 +0000 Subject: [PATCH 1/2] Enforce opaque WF during add_item_bounds_for_hidden_type --- compiler/rustc_infer/src/infer/opaque_types/mod.rs | 9 +++++++++ .../bivariant-duplicated-lifetime.rs | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/ui/type-alias-impl-trait/bivariant-duplicated-lifetime.rs diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 3d6829ba6579f..2b8c71bd1195d 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -610,6 +610,15 @@ impl<'tcx> InferCtxt<'tcx> { ty::ClauseKind::WellFormed(hidden_ty.into()), )); + // This enforces the region obligations that link the bivariant + // lifetimes of an opaque to their invariant copies. + obligations.push(traits::Obligation::new( + tcx, + cause.clone(), + param_env, + ty::ClauseKind::WellFormed(Ty::new_opaque(self.tcx, def_id, args).into()), + )); + let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { let predicate = predicate.fold_with(&mut BottomUpFolder { diff --git a/tests/ui/type-alias-impl-trait/bivariant-duplicated-lifetime.rs b/tests/ui/type-alias-impl-trait/bivariant-duplicated-lifetime.rs new file mode 100644 index 0000000000000..7978bd8bf5bff --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bivariant-duplicated-lifetime.rs @@ -0,0 +1,12 @@ +//@ check-pass + +#![feature(type_alias_impl_trait)] +#![allow(unconditional_recursion)] + +type Opaque<'a> = impl Sized + 'a; + +fn test<'a>() -> Opaque<'a> { + let _: () = test::<'a>(); +} + +fn main() {} From f72f5d8f3f04798751e6d2334c8efface8a6b799 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 10 Mar 2024 21:05:55 +0000 Subject: [PATCH 2/2] Enforce nominal obligations for RPIT too --- .../rustc_trait_selection/src/traits/wf.rs | 9 +---- .../bivariant-duplicated-lifetime.rs | 9 +++++ .../in-trait/return-dont-satisfy-bounds.rs | 1 + .../return-dont-satisfy-bounds.stderr | 18 ++++++++- .../ui/lifetimes/issue-76168-hr-outlives-3.rs | 1 + .../issue-76168-hr-outlives-3.stderr | 23 ++++++++++-- .../type-match-with-late-bound.stderr | 37 ++++++++++++++++++- 7 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 tests/ui/impl-trait/bivariant-duplicated-lifetime.rs diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f89daf033f6cd..f144ce4115e72 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -792,13 +792,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - // All of the requirements on type parameters - // have already been checked for `impl Trait` in - // return position. We do need to check type-alias-impl-trait though. - if self.tcx().is_type_alias_impl_trait(def_id) { - let obligations = self.nominal_obligations(def_id, args); - self.out.extend(obligations); - } + let obligations = self.nominal_obligations(def_id, args); + self.out.extend(obligations); } ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => { diff --git a/tests/ui/impl-trait/bivariant-duplicated-lifetime.rs b/tests/ui/impl-trait/bivariant-duplicated-lifetime.rs new file mode 100644 index 0000000000000..436c30016f506 --- /dev/null +++ b/tests/ui/impl-trait/bivariant-duplicated-lifetime.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#![allow(unconditional_recursion)] + +fn test<'a>() -> impl Sized + 'a { + let _: () = test::<'a>(); +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs index ff265e576b90f..84bc39d926307 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs @@ -9,6 +9,7 @@ impl Foo for Bar { //~^ ERROR: the trait bound `impl Foo: Foo` is not satisfied [E0277] //~| ERROR: the trait bound `Bar: Foo` is not satisfied [E0277] //~| ERROR: impl has stricter requirements than trait + //~| ERROR: the trait bound `F2: Foo` is not satisfied self } } diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 12725c3456fd5..fbf82a24b5015 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -11,6 +11,22 @@ note: required by a bound in `Foo::{synthetic#0}` LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::{synthetic#0}` +error[E0277]: the trait bound `F2: Foo` is not satisfied + --> $DIR/return-dont-satisfy-bounds.rs:8:34 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^^^^^^ the trait `Foo` is not implemented for `F2` + | +note: required by a bound in `>::foo` + --> $DIR/return-dont-satisfy-bounds.rs:8:16 + | +LL | fn foo>(self) -> impl Foo { + | ^^^^^^^ required by this bound in `>::foo` +help: consider further restricting this bound + | +LL | fn foo + Foo>(self) -> impl Foo { + | +++++++++ + error[E0276]: impl has stricter requirements than trait --> $DIR/return-dont-satisfy-bounds.rs:8:16 | @@ -32,7 +48,7 @@ LL | self = help: the trait `Foo` is implemented for `Bar` = help: for that trait implementation, expected `char`, found `u8` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0276, E0277. For more information about an error, try `rustc --explain E0276`. diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs index 85eeb5d4c901e..eab436fa3419d 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs @@ -7,6 +7,7 @@ async fn wrapper(f: F) //~^ ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` //~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` +//~| ERROR: expected a `FnOnce(&'a mut i32)` closure, found `i32` where F:, for<'a> >::Output: Future + 'a, diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index 578ba149baf3f..e9f97d1d93bde 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -5,7 +5,7 @@ LL | / async fn wrapper(f: F) LL | | LL | | LL | | -LL | | where +... | LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` @@ -27,7 +27,7 @@ LL | / async fn wrapper(f: F) LL | | LL | | LL | | -LL | | where +... | LL | | F:, LL | | for<'a> >::Output: Future + 'a, | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` @@ -35,7 +35,22 @@ LL | | for<'a> >::Output: Future + 'a = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` - --> $DIR/issue-76168-hr-outlives-3.rs:13:1 + --> $DIR/issue-76168-hr-outlives-3.rs:6:1 + | +LL | / async fn wrapper(f: F) +LL | | +LL | | +LL | | +... | +LL | | F:, +LL | | for<'a> >::Output: Future + 'a, + | |__________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` + | + = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: expected a `FnOnce(&'a mut i32)` closure, found `i32` + --> $DIR/issue-76168-hr-outlives-3.rs:14:1 | LL | / { LL | | @@ -46,6 +61,6 @@ LL | | } | = help: the trait `for<'a> FnOnce<(&'a mut i32,)>` is not implemented for `i32` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr index 6c259621466d3..69a935261bb97 100644 --- a/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr +++ b/tests/ui/traits/non_lifetime_binders/type-match-with-late-bound.stderr @@ -7,6 +7,27 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 for more information = note: `#[warn(incomplete_features)]` on by default +error[E0309]: the placeholder type `!1_"F"` may not live long enough + --> $DIR/type-match-with-late-bound.rs:8:1 + | +LL | async fn walk2<'a, T: 'a>(_: T) + | ^ -- the placeholder type `!1_"F"` must be valid for the lifetime `'a` as defined here... + | _| + | | +LL | | where +LL | | for F: 'a, + | |_________________^ ...so that the type `F` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/type-match-with-late-bound.rs:10:15 + | +LL | for F: 'a, + | ^^ +help: consider adding an explicit lifetime bound + | +LL | for F: 'a, !1_"F": 'a + | ~~~~~~~~~~~~ + error[E0309]: the placeholder type `!1_"F"` may not live long enough --> $DIR/type-match-with-late-bound.rs:11:1 | @@ -35,6 +56,20 @@ help: consider adding an explicit lifetime bound LL | for F: 'a, !2_"F": 'a | ~~~~~~~~~~~~ -error: aborting due to 2 previous errors; 1 warning emitted +error[E0309]: the placeholder type `!3_"F"` may not live long enough + --> $DIR/type-match-with-late-bound.rs:11:1 + | +LL | async fn walk2<'a, T: 'a>(_: T) + | -- the placeholder type `!3_"F"` must be valid for the lifetime `'a` as defined here... +... +LL | {} + | ^^ ...so that the type `F` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | for F: 'a, !3_"F": 'a + | ~~~~~~~~~~~~ + +error: aborting due to 4 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0309`.