diff options
Diffstat (limited to 'src/test/ui/implied-bounds')
7 files changed, 207 insertions, 0 deletions
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 000000000..33b746c5e --- /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 000000000..d0249e74f --- /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/implied-bounds/impl-header-unnormalized-types.rs b/src/test/ui/implied-bounds/impl-header-unnormalized-types.rs new file mode 100644 index 000000000..d84539f8a --- /dev/null +++ b/src/test/ui/implied-bounds/impl-header-unnormalized-types.rs @@ -0,0 +1,28 @@ +struct Foo<T>(T); + +trait GoodBye { + type Forget; +} +impl<T> 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 000000000..88abd5f54 --- /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`. diff --git a/src/test/ui/implied-bounds/issue-100690.rs b/src/test/ui/implied-bounds/issue-100690.rs new file mode 100644 index 000000000..5599cd410 --- /dev/null +++ b/src/test/ui/implied-bounds/issue-100690.rs @@ -0,0 +1,45 @@ +// This code (probably) _should_ compile, but it currently does not because we +// are not smart enough about implied bounds. + +use std::io; + +fn real_dispatch<T, F>(f: F) -> Result<(), io::Error> +//~^ NOTE required by a bound in this +where + F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static, + //~^ NOTE required by this bound in `real_dispatch` + //~| NOTE required by a bound in `real_dispatch` +{ + todo!() +} + +#[derive(Debug)] +struct UIView<'a, T: 'a> { + _phantom: std::marker::PhantomData<&'a mut T>, +} + +trait Handle<'a, T: 'a, V, R> { + fn dispatch<F>(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut V) -> R + Send + 'static; +} + +#[derive(Debug, Clone)] +struct TUIHandle<T> { + _phantom: std::marker::PhantomData<T>, +} + +impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle<T> { + fn dispatch<F>(&self, f: F) -> Result<(), io::Error> + where + F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static, + { + real_dispatch(f) + //~^ ERROR expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + //~| NOTE expected a closure with arguments + //~| NOTE required by a bound introduced by this call + } +} + +fn main() {} diff --git a/src/test/ui/implied-bounds/issue-100690.stderr b/src/test/ui/implied-bounds/issue-100690.stderr new file mode 100644 index 000000000..3f6af70d8 --- /dev/null +++ b/src/test/ui/implied-bounds/issue-100690.stderr @@ -0,0 +1,22 @@ +error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + --> $DIR/issue-100690.rs:37:23 + | +LL | real_dispatch(f) + | ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F` + | | + | required by a bound introduced by this call + | + = note: expected a closure with arguments `(&mut UIView<'a, T>,)` + found a closure with arguments `(&mut UIView<'_, T>,)` +note: required by a bound in `real_dispatch` + --> $DIR/issue-100690.rs:9:8 + | +LL | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error> + | ------------- required by a bound in this +... +LL | F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/implied-bounds/issue-101951.rs b/src/test/ui/implied-bounds/issue-101951.rs new file mode 100644 index 000000000..108fef8a1 --- /dev/null +++ b/src/test/ui/implied-bounds/issue-101951.rs @@ -0,0 +1,50 @@ +// Taken directly from that issue. +// +// This test detected that we didn't correctly resolve +// inference variables when computing implied bounds. +// +// check-pass +pub trait BuilderFn<'a> { + type Output; +} + +impl<'a, F, Out> BuilderFn<'a> for F +where + F: FnOnce(&'a mut ()) -> Out, +{ + type Output = Out; +} + +pub trait ConstructionFirm { + type Builder: for<'a> BuilderFn<'a>; +} + +pub trait Campus<T> +where + T: ConstructionFirm, +{ + fn add_building( + &mut self, + building: &mut <<T as ConstructionFirm>::Builder as BuilderFn<'_>>::Output, + ); +} + +struct ArchitectsInc {} + +impl ConstructionFirm for ArchitectsInc { + type Builder = fn(&mut ()) -> PrettyCondo<'_>; +} + +struct PrettyCondo<'a> { + _marker: &'a mut (), +} + +struct CondoEstate {} + +impl Campus<ArchitectsInc> for CondoEstate { + fn add_building(&mut self, _building: &mut PrettyCondo<'_>) { + todo!() + } +} + +fn main() {} |