From 04524c8f6aef8a8a1b3b80edb93815e86caeddfa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 11 Mar 2024 16:57:18 +0000 Subject: [PATCH] Consolidate WF for aliases --- .../rustc_trait_selection/src/traits/wf.rs | 28 ++++++------------- .../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 | 23 ++++++++++++++- 6 files changed, 68 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index f89daf033f6cd..64f02bfd32116 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -164,7 +164,7 @@ pub fn clause_obligations<'tcx>( wf.compute(ty.into()); } ty::ClauseKind::Projection(t) => { - wf.compute_projection(t.projection_ty); + wf.compute_alias(t.projection_ty); wf.compute(match t.term.unpack() { ty::TermKind::Ty(ty) => ty.into(), ty::TermKind::Const(c) => c.into(), @@ -436,9 +436,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } - /// Pushes the obligations required for `trait_ref::Item` to be WF + /// Pushes the obligations required for an alias (except inherent) to be WF /// into `self.out`. - fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) { + fn compute_alias(&mut self, data: ty::AliasTy<'tcx>) { // A projection is well-formed if // // (a) its predicates hold (*) @@ -466,6 +466,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.compute_projection_args(data.args); } + /// Pushes the obligations required for an inherent alias to be WF + /// into `self.out`. + // FIXME(inherent_associated_types): Merge this function with `fn compute_alias`. fn compute_inherent_projection(&mut self, data: ty::AliasTy<'tcx>) { // An inherent projection is well-formed if // @@ -688,8 +691,8 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // Simple cases that are WF if their type args are WF. } - ty::Alias(ty::Projection, data) => { - self.compute_projection(data); + ty::Alias(ty::Projection | ty::Opaque | ty::Weak, data) => { + self.compute_alias(data); return; // Subtree handled by compute_projection. } ty::Alias(ty::Inherent, data) => { @@ -791,21 +794,6 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // types appearing in the fn signature. } - 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); - } - } - - ty::Alias(ty::Weak, ty::AliasTy { def_id, args, .. }) => { - let obligations = self.nominal_obligations(def_id, args); - self.out.extend(obligations); - } - ty::Dynamic(data, r, _) => { // WfObject // 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..40e16dde6e4a4 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,6 @@ 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: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0309`.