From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- .../multiple-lifetimes/error-handling-2.rs | 26 +++++++++++ .../multiple-lifetimes/error-handling-2.stderr | 12 ++++++ .../error-handling.polonius.stderr | 15 +++++++ .../multiple-lifetimes/error-handling.rs | 26 +++++++++++ .../multiple-lifetimes/error-handling.stderr | 15 +++++++ .../multiple-lifetimes/inverse-bounds.rs | 50 ++++++++++++++++++++++ .../ordinary-bounds-pick-original-elided.rs | 25 +++++++++++ ...y-bounds-pick-original-type-alias-impl-trait.rs | 28 ++++++++++++ .../ordinary-bounds-pick-original.rs | 25 +++++++++++ .../ordinary-bounds-pick-other.rs | 42 ++++++++++++++++++ .../ordinary-bounds-unrelated.rs | 36 ++++++++++++++++ .../ordinary-bounds-unrelated.stderr | 17 ++++++++ .../multiple-lifetimes/ordinary-bounds-unsuited.rs | 39 +++++++++++++++++ .../ordinary-bounds-unsuited.stderr | 17 ++++++++ 14 files changed, 373 insertions(+) create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr (limited to 'src/test/ui/impl-trait/multiple-lifetimes') diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs new file mode 100644 index 000000000..2a2be6b74 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +#[derive(Clone)] +struct CopyIfEq(T, U); + +impl Copy for CopyIfEq {} + +type E<'a, 'b> = impl Sized; + +fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. + let u = v; + let _: *mut &'a i32 = u.1; + unsafe { + let _: &'b i32 = *u.0; + } + u.0 + //~^ ERROR hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr new file mode 100644 index 000000000..908757080 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -0,0 +1,12 @@ +error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds + --> $DIR/error-handling-2.rs:22:5 + | +LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here +... +LL | u.0 + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr new file mode 100644 index 000000000..ccd004003 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/error-handling.rs:22:16 + | +LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'b i32 = *u.0; + | ^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs new file mode 100644 index 000000000..367e7f4e6 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] + +#[derive(Clone)] +struct CopyIfEq(T, U); + +impl Copy for CopyIfEq {} + +type E<'a, 'b> = impl Sized; + +fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. + let u = v; + let _: *mut &'a i32 = u.1; + unsafe { + let _: &'b i32 = *u.0; + //~^ ERROR lifetime may not live long enough + } + u.0 +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr new file mode 100644 index 000000000..01d9f506a --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/error-handling.rs:20:16 + | +LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'b i32 = *u.0; + | ^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs new file mode 100644 index 000000000..5251eeee8 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/inverse-bounds.rs @@ -0,0 +1,50 @@ +// edition:2018 +// check-pass + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Invert<'a> <: Invert<'b>` if `'b: 'a`, unlike most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Invert<'a>(fn(&'a u8)); + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Invert<'a>, b: Invert<'b>) -> impl Trait<'d, 'e> +where + 'c: 'a, + 'c: 'b, + 'd: 'c, +{ + // Representing the where clauses as a graph, where `A: B` is an + // edge `B -> A`: + // + // ``` + // 'a -> 'c -> 'd + // ^ + // | + // 'b + // ``` + // + // Meanwhile we return a value &'0 u8 where we have the constraints: + // + // ``` + // '0: 'a + // '0: 'b + // '0 in ['d, 'e] + // ``` + // + // Here, ignoring the "in" constraint, the minimal choice for `'0` + // is `'c`, but that is not in the "in set". Still, that reduces + // the range of options in the "in set" to just `'d` (`'e: 'c` + // does not hold). + let p = if condition() { a } else { b }; + p +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs new file mode 100644 index 000000000..0bddce49b --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-elided.rs @@ -0,0 +1,25 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass? + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Test case where we have elision in the impl trait and we have to +// pick the right region. + +// Ultimately `Trait<'x, 'static>`. +fn upper_bounds1(a: &u8) -> impl Trait<'_, 'static> { + (a, a) +} + +// Ultimately `Trait<'x, 'x>`, so not really multiple bounds. +fn upper_bounds2(a: &u8) -> impl Trait<'_, '_> { + (a, a) +} + +// Kind of a weird annoying case. +fn upper_bounds3<'b>(a: &u8) -> impl Trait<'_, 'b> { + (a, a) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs new file mode 100644 index 000000000..e363fdb36 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs @@ -0,0 +1,28 @@ +// edition:2018 +// check-pass + +#![feature(type_alias_impl_trait)] +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Here we wind up selecting `'a` and `'b` in the hidden type because +// those are the types that appear in the original values. + +type Foo<'a, 'b> = impl Trait<'a, 'b>; + +fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> { + // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // '1 in ['a, 'b] + // ``` + // + // We use the fact that `'a: 0'` must hold (combined with the in + // constraint) to determine that `'0 = 'a` must be the answer. + (a, b) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs new file mode 100644 index 000000000..0f21dd5ff --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original.rs @@ -0,0 +1,25 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass?) + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// Here we wind up selecting `'a` and `'b` in the hidden type because +// those are the types that appear in the original values. + +fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a, 'b> { + // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // '1 in ['a, 'b] + // ``` + // + // We use the fact that `'a: 0'` must hold (combined with the in + // constraint) to determine that `'0 = 'a` must be the answer. + (a, b) +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs new file mode 100644 index 000000000..13ad1f721 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-other.rs @@ -0,0 +1,42 @@ +// edition:2018 +// build-pass (FIXME(62277): could be check-pass?) + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we wind up selecting `'e` in the hidden type because +// we need something outlived by both `'a` and `'b` and only `'e` applies. + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> +where + 'a: 'e, + 'b: 'e, + 'a: 'd, +{ + // We return a value: + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['d, 'e] + // ``` + // + // but we don't have it. + // + // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. + let p = if condition() { a } else { b }; + p +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs new file mode 100644 index 000000000..c6eea5323 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.rs @@ -0,0 +1,36 @@ +// edition:2018 + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we get an error because none of our choices (either `'d` nor `'e`) are outlived +// by both `'a` and `'b`. + +fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> +where + 'a: 'e, + 'b: 'd, +{ + // Hidden type `Ordinary<'0>` with constraints: + // + // ``` + // 'a: '0 + // 'b: '0 + // 'a in ['d, 'e] + // ``` + if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr new file mode 100644 index 000000000..cb1dc0b7d --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -0,0 +1,17 @@ +error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unrelated.rs:28:33 + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs new file mode 100644 index 000000000..adcbca2a4 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.rs @@ -0,0 +1,39 @@ +// edition:2018 + +trait Trait<'a, 'b> {} +impl Trait<'_, '_> for T {} + +// `Ordinary<'a> <: Ordinary<'b>` if `'a: 'b`, as with most types. +// +// I am purposefully avoiding the terms co- and contra-variant because +// their application to regions depends on how you interpreted Rust +// regions. -nikomatsakis +struct Ordinary<'a>(&'a u8); + +// Here we need something outlived by `'a` *and* outlived by `'b`, but +// we can only name `'a` and `'b` (and neither suits). So we get an +// error. Somewhat unfortunate, though, since the caller would have to +// consider the loans for both `'a` and `'b` alive. + +fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> +{ + // We return a value: + // + // ``` + // 'a: '0 + // 'b: '1 + // '0 in ['a, 'b] + // ``` + // + // but we don't have it. + // + // We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b. + if condition() { a } else { b } + //~^ ERROR hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds +} + +fn condition() -> bool { + true +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr new file mode 100644 index 000000000..4388e6601 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -0,0 +1,17 @@ +error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds + --> $DIR/ordinary-bounds-unsuited.rs:31:33 + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + | -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here +... +LL | if condition() { a } else { b } + | ^ + | +help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. -- cgit v1.2.3