diff options
| author | bors <bors@rust-lang.org> | 2022-08-09 16:39:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-08-09 16:39:43 +0000 |
| commit | 63e4312e6bd50ec9859c363402209809fb8155d5 (patch) | |
| tree | 4953dbef9f6b944e18af8388d48adf94a4ce92b2 /src | |
| parent | 6d3f1beae1720055e5a30f4dbe7a9e7fb810c65e (diff) | |
| parent | 8691b96eee9635756b957ac8d9e5bd963cb73f12 (diff) | |
Auto merge of #99217 - lcnr:implied-bounds-pre-norm, r=lcnr
consider unnormalized types for implied bounds extracted, and slightly modified, from #98900 The idea here is that generally, rustc is split into things which can assume its inputs are well formed[^1], and things which have verify that themselves. Generally most predicates should only deal with well formed inputs, e.g. a `&'a &'b (): Trait` predicate should be able to assume that `'b: 'a` holds. Normalization can loosen wf requirements (see #91068) and must therefore not be used in places which still have to check well formedness. The only such place should hopefully be `WellFormed` predicates fixes #87748 and #98543 r? `@jackh726` cc `@rust-lang/types` [^1]: These places may still encounter non-wf inputs and have to deal with them without causing an ICE as we may check for well formedness out of order.
Diffstat (limited to 'src')
20 files changed, 178 insertions, 76 deletions
diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs index 162f9e00edd..9e68e9e7751 100644 --- a/src/test/ui/associated-types/issue-59324.rs +++ b/src/test/ui/associated-types/issue-59324.rs @@ -15,9 +15,9 @@ pub trait ThriftService<Bug: NotFoo>: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied + //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; - //~^ the trait bound `Bug: Foo` is not satisfied } fn with_factory<H>(factory: dyn ThriftService<()>) {} diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index a84b599b52b..dd5ec7175b5 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -20,7 +20,7 @@ LL | | LL | | LL | | Service<AssocType = <Bug as Foo>::OnlyFoo> ... | -LL | | +LL | | ) -> Self::AssocType; LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -34,6 +34,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | +LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` @@ -50,10 +51,10 @@ LL | fn with_factory<H>(factory: dyn ThriftService<()>) {} | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:19:10 + --> $DIR/issue-59324.rs:16:8 | -LL | ) -> Self::AssocType; - | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` +LL | fn get_service( + | ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs index 5a92bcd37b6..5d924555625 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.rs @@ -1,4 +1,4 @@ -// check-pass +// check-fail trait Trait { type Type; @@ -17,6 +17,7 @@ where fn g<'a, 'b>() { f::<'a, 'b>(()); + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.stderr new file mode 100644 index 00000000000..0c3df04eabc --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-2.stderr @@ -0,0 +1,17 @@ +error: lifetime may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-2.rs:19:5 + | +LL | fn g<'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | f::<'a, 'b>(()); + | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `f` + = note: the function `f` is invariant over the parameter `'a` + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to previous error + diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.rs index dc25ac08613..888f74cf6b3 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.rs +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.rs @@ -1,6 +1,4 @@ -// check-fail -// See issue #91899. If we treat unnormalized args as WF, `Self` can also be a -// source of unsoundness. +// check-pass pub trait Yokeable<'a>: 'static { type Output: 'a; @@ -17,7 +15,6 @@ pub trait ZeroCopyFrom<C: ?Sized>: for<'a> Yokeable<'a> { impl<T> ZeroCopyFrom<[T]> for &'static [T] { fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] { - //~^ the parameter cart } } diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr deleted file mode 100644 index 95cf4fb168f..00000000000 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/implied-bounds-unnorm-associated-type-3.rs:19:5 - | -LL | fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `[T]` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... - | -LL | impl<T: 'static> ZeroCopyFrom<[T]> for &'static [T] { - | +++++++++ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.rs new file mode 100644 index 00000000000..12859252c87 --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.rs @@ -0,0 +1,24 @@ +// A regression test for #98543 + +trait Trait { + type Type; +} + +impl<T> Trait for T { + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str +where + &'a &'b (): Trait, // <- adding this bound is the change from #91068 +{ + s +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + //~^ ERROR cannot move out of `x` because it is borrowed + println!("{}", y); +} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.stderr new file mode 100644 index 00000000000..fcbaa91d19f --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-4.stderr @@ -0,0 +1,14 @@ +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/implied-bounds-unnorm-associated-type-4.rs:21:10 + | +LL | let y = f(&x, ()); + | -- borrow of `x` occurs here +LL | drop(x); + | ^ move out of `x` occurs here +LL | +LL | println!("{}", y); + | - borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.rs new file mode 100644 index 00000000000..2a9a6a8cc6c --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.rs @@ -0,0 +1,23 @@ +trait Trait<'a>: 'a { + type Type; +} + +// if the `T: 'a` bound gets implied we would probably get ub here again +impl<'a, T> Trait<'a> for T { + //~^ ERROR the parameter type `T` may not live long enough + type Type = (); +} + +fn f<'a, 'b>(s: &'b str, _: <&'b () as Trait<'a>>::Type) -> &'a str +where + &'b (): Trait<'a>, +{ + s +} + +fn main() { + let x = String::from("Hello World!"); + let y = f(&x, ()); + drop(x); + println!("{}", y); +} diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.stderr new file mode 100644 index 00000000000..458756a3dcd --- /dev/null +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type-5.stderr @@ -0,0 +1,19 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:6:13 + | +LL | impl<'a, T> Trait<'a> for T { + | ^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds... + | +note: ...that is required by this bound + --> $DIR/implied-bounds-unnorm-associated-type-5.rs:1:18 + | +LL | trait Trait<'a>: 'a { + | ^^ +help: consider adding an explicit lifetime bound... + | +LL | impl<'a, T: 'a> Trait<'a> for T { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs index 04b6f4dd84e..d58d25036c5 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.rs @@ -1,6 +1,6 @@ // check-fail -// See issue #91068. Types in the substs of an associated type can't be implied -// to be WF, since they don't actually have to be constructed. +// See issue #91068. We check that the unnormalized associated types in +// function signatures are implied trait Trait { type Type; @@ -12,12 +12,12 @@ impl<T> Trait for T { fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { s - //~^ ERROR lifetime may not live long enough } fn main() { let x = String::from("Hello World!"); let y = f(&x, ()); drop(x); + //~^ ERROR cannot move out of `x` because it is borrowed println!("{}", y); } diff --git a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr index 8096f08385c..e35f46e4439 100644 --- a/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr +++ b/src/test/ui/fn/implied-bounds-unnorm-associated-type.stderr @@ -1,14 +1,14 @@ -error: lifetime may not live long enough - --> $DIR/implied-bounds-unnorm-associated-type.rs:14:5 +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/implied-bounds-unnorm-associated-type.rs:20:10 | -LL | fn f<'a, 'b>(s: &'b str, _: <&'a &'b () as Trait>::Type) -> &'a str { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | s - | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` +LL | let y = f(&x, ()); + | -- borrow of `x` occurs here +LL | drop(x); + | ^ move out of `x` occurs here +LL | +LL | println!("{}", y); + | - borrow later used here error: aborting due to previous error +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr deleted file mode 100644 index ac197dfe6ff..00000000000 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0478]: lifetime bound not satisfied - --> $DIR/issue-87748.rs:18:5 - | -LL | fn do_sth(_: u32) {} - | ^^^^^^^^^^^^^^^^^ - | -note: lifetime parameter instantiated with the anonymous lifetime as defined here - --> $DIR/issue-87748.rs:18:5 - | -LL | fn do_sth(_: u32) {} - | ^^^^^^^^^^^^^^^^^ -note: but lifetime parameter must outlive the anonymous lifetime as defined here - --> $DIR/issue-87748.rs:18:5 - | -LL | fn do_sth(_: u32) {} - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0478`. diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs index a3d00ee03b1..1a1ab9bf8a4 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs +++ b/src/test/ui/generic-associated-types/issue-87748.rs @@ -1,13 +1,14 @@ -// check-fail -// known-bug: #87748 +// Checks that we properly add implied bounds from unnormalized projections in +// inputs when typechecking functions. -// This should pass, but unnormalized input args aren't treated as implied. +// check-pass #![feature(generic_associated_types)] trait MyTrait { type Assoc<'a, 'b> where 'b: 'a; fn do_sth(arg: Self::Assoc<'_, '_>); + fn do_sth2(arg: Self::Assoc<'_, '_>) {} } struct Foo; @@ -16,8 +17,7 @@ impl MyTrait for Foo { type Assoc<'a, 'b> = u32 where 'b: 'a; fn do_sth(_: u32) {} - // fn do_sth(_: Self::Assoc<'static, 'static>) {} - // fn do_sth(_: Self::Assoc<'_, '_>) {} + fn do_sth2(_: Self::Assoc<'static, 'static>) {} } fn main() {} diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs index 172bf218c0d..de9348f5397 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs @@ -7,7 +7,6 @@ trait SomeTrait<'a> { fn give_me_ice<T>() { callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); //~^ ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277] - //~| ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277] } fn callee<T: Fn<(&'static (),)>>() { diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr index ecca4b999e7..6a948a116e0 100644 --- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr +++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr @@ -9,17 +9,6 @@ help: consider restricting type parameter `T` LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() { | +++++++++++++++++++++++ -error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied - --> $DIR/issue-85455.rs:8:14 - | -LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() { - | +++++++++++++++++++++++ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs b/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs new file mode 100644 index 00000000000..33b746c5edf --- /dev/null +++ b/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.rs @@ -0,0 +1,27 @@ +// Test for a less than ideal interaction of implied bounds and normalization. +trait Tr { + type Ty; +} + +impl<T: 'static> Tr for T { + type Ty = &'static T; +} + +// `<&'a u8 as Tr>::Ty` should cause an error because `&'a u8: Tr` doesn't hold for +// all possible 'a. However, we consider normalized types for implied bounds. +// +// We normalize this projection to `&'static &'a u8` and add a nested `&'a u8: 'static` +// bound. This bound is then proven using the implied bounds for `&'static &'a u8` which +// we only get by normalizing in the first place. +fn test<'a>(x: &'a u8, _wf: <&'a u8 as Tr>::Ty) -> &'static u8 { x } + +fn main() { + // This works as we have 'static references due to promotion. + let _: &'static u8 = test(&3, &&3); + // This causes an error because the projection requires 'a to be 'static. + // It would be unsound if this compiled. + let x: u8 = 3; + let _: &'static u8 = test(&x, &&3); + //~^ ERROR `x` does not live long enough + +} diff --git a/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr b/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr new file mode 100644 index 00000000000..d0249e74f39 --- /dev/null +++ b/src/test/ui/implied-bounds/assoc-ty-wf-used-to-get-assoc-ty.stderr @@ -0,0 +1,15 @@ +error[E0597]: `x` does not live long enough + --> $DIR/assoc-ty-wf-used-to-get-assoc-ty.rs:24:31 + | +LL | let _: &'static u8 = test(&x, &&3); + | -----^^------ + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'static` +... +LL | } + | - `x` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs index c4db6fc97dc..05e2ea047f6 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs @@ -30,4 +30,5 @@ fn main() { let _x = <fn(&())>::make_f(); //~^ ERROR implementation of `Y` is not general enough //~| ERROR implementation of `Y` is not general enough + //~| ERROR implementation of `Y` is not general enough } diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 51adfca3e79..8c47379886d 100644 --- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -16,5 +16,14 @@ LL | let _x = <fn(&())>::make_f(); = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` -error: aborting due to 2 previous errors +error: implementation of `Y` is not general enough + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 + | +LL | let _x = <fn(&())>::make_f(); + | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | + = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` + +error: aborting due to 3 previous errors |
