diff options
| author | bors <bors@rust-lang.org> | 2024-03-28 09:51:39 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-28 09:51:39 +0000 |
| commit | 551abd65bee759c1fd1cc0acd5ba7e5723823c54 (patch) | |
| tree | a7f0f76f260e7ed98cac5068bf8ed7341f1b210f /tests | |
| parent | d0e8cbbd99ccc1be12b1aa743521ed89268e59a2 (diff) | |
| parent | 59c217fed2bc74f3685bf3461674f6b3c7e113c3 (diff) | |
| download | rust-551abd65bee759c1fd1cc0acd5ba7e5723823c54.tar.gz rust-551abd65bee759c1fd1cc0acd5ba7e5723823c54.zip | |
Auto merge of #116891 - aliemjay:opaque-region-infer-rework-2, r=compiler-errors,oli-obk
rework opaque type region inference User-facing changes are documented in [this comment](https://github.com/rust-lang/rust/pull/116891#issuecomment-1973774412). The design document is in [this comment](https://github.com/rust-lang/rust/pull/116891#issuecomment-1836900102). --- \- Fix Ice in check_unique; ICE -> Error; fixes #122782. \- Ignore uncaptured lifetime args; ICE -> Pass; fixes #111906, fixes #110623, fixes #109059, fixes #122307 \- Except equal parameters from the uniqueness check; Pass -> Error; fixes #113916. \- Check RPITs for invalid args; Pass -> Error; fixes #111935; ICE -> Error; fixes #110726. \- Rework opaque types region inference; Pass -> Error; fixes #113971, fixes #112841. \- Reject external lifetimes as invalid args; Pass -> Error; fixes #105498. r? `@ghost`
Diffstat (limited to 'tests')
35 files changed, 594 insertions, 164 deletions
diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr new file mode 100644 index 00000000000..ded9a92d8e8 --- /dev/null +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/defining-use-captured-non-universal-region.rs:13:18 + | +LL | fn foo<'a>() -> impl Sized + 'a { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | let i: i32 = foo::<'_>(); + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs new file mode 100644 index 00000000000..e18302dc061 --- /dev/null +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs @@ -0,0 +1,22 @@ +// This was an ICE. See #110726. + +//@ revisions: statik infer fixed +//@ [fixed] check-pass +#![allow(unconditional_recursion)] + +fn foo<'a>() -> impl Sized + 'a { + #[cfg(statik)] + let i: i32 = foo::<'static>(); + //[statik]~^ ERROR expected generic lifetime parameter, found `'static` + + #[cfg(infer)] + let i: i32 = foo::<'_>(); + //[infer]~^ ERROR expected generic lifetime parameter, found `'_` + + #[cfg(fixed)] + let i: i32 = foo::<'a>(); + + i +} + +fn main() {} diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr new file mode 100644 index 00000000000..43beb29f9ec --- /dev/null +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'static` + --> $DIR/defining-use-captured-non-universal-region.rs:9:18 + | +LL | fn foo<'a>() -> impl Sized + 'a { + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +LL | #[cfg(statik)] +LL | let i: i32 = foo::<'static>(); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs new file mode 100644 index 00000000000..56e099c28d2 --- /dev/null +++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-2.rs @@ -0,0 +1,74 @@ +// issue: #110623 +//@ check-pass + +use std::{collections::BTreeMap, num::ParseIntError, str::FromStr}; + +enum FileSystem { + File(usize), + Directory(BTreeMap<String, FileSystem>), +} + +impl FromStr for FileSystem { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s.starts_with("dir") { + Ok(Self::new_dir()) + } else { + Ok(Self::File(s.split_whitespace().next().unwrap().parse()?)) + } + } +} + +impl FileSystem { + fn new_dir() -> FileSystem { + FileSystem::Directory(BTreeMap::new()) + } + + fn insert(&mut self, name: String, other: FileSystem) -> Option<FileSystem> { + match self { + FileSystem::File(_) => panic!("can only insert into directory!"), + FileSystem::Directory(tree) => tree.insert(name, other), + } + } + + // Recursively build a tree from commands. This uses (abuses?) + // the fact that `cd /` only appears at the start and that + // subsequent `cd`s can only move ONE level to use the recursion + // stack as the filesystem stack + fn build<'a>( + &mut self, + mut commands: impl Iterator<Item = &'a str> + 'a, + ) -> Option<impl Iterator<Item = &'a str> + 'a> { + let cmd = commands.next()?; + let mut elements = cmd.lines(); + match elements.next().map(str::trim) { + Some("cd /") | None => self.build(commands), + Some("cd ..") => { + // return to higher scope + Some(commands) + } + Some("ls") => { + for item in elements { + let name = item.split_whitespace().last().unwrap(); + let prior = self.insert(name.to_string(), item.parse().unwrap()); + debug_assert!(prior.is_none()); + } + // continue on + self.build(commands) + } + Some(other_cd) => { + let name = other_cd + .trim() + .strip_prefix("cd ") + .expect("expected a cd command"); + let mut directory = FileSystem::new_dir(); + let further_commands = directory.build(commands); + self.insert(name.to_string(), directory); + self.build(further_commands?) // THIS LINE FAILS TO COMPILE + } + } + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs new file mode 100644 index 00000000000..a6dcad3face --- /dev/null +++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region-3.rs @@ -0,0 +1,13 @@ +//@ check-pass + +#![feature(adt_const_params)] +#![allow(incomplete_features)] + +trait Bar<const FOO: &'static str> {} +impl Bar<"asdf"> for () {} + +fn foo<const FOO: &'static str>() -> impl Bar<"asdf"> { + () +} + +fn main() {} diff --git a/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs new file mode 100644 index 00000000000..f90ff51c651 --- /dev/null +++ b/tests/ui/impl-trait/defining-use-uncaptured-non-universal-region.rs @@ -0,0 +1,16 @@ +// issue: #111906 +//@ check-pass + +#![allow(unconditional_recursion)] + +fn foo<'a: 'a>() -> impl Sized { + let _: () = foo::<'a>(); + loop {} +} + +fn bar<'a: 'a>() -> impl Sized + 'a { + let _: *mut &'a () = bar::<'a>(); + loop {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr index 1d648162113..78ef8ec404c 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr @@ -1,4 +1,4 @@ -error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} +error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} --> $DIR/erased-regions-in-hidden-ty.rs:12:36 | LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static { diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr index 1d648162113..78ef8ec404c 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr @@ -1,4 +1,4 @@ -error: {foo<DefId(..)_'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} +error: {foo<'{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} --> $DIR/erased-regions-in-hidden-ty.rs:12:36 | LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static { diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs index 9d71685f179..e60f1badcae 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs @@ -10,7 +10,7 @@ // Make sure that the compiler can handle `ReErased` in the hidden type of an opaque. fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static { - //~^ ERROR 'a/#0>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} + //~^ ERROR '{erased}>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} // Can't write whole type because of lack of path sanitization || () } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 15778662375..199cbbf4fcc 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -2,10 +2,8 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR cannot resolve opaque type - |x| x - //~^ ERROR concrete type differs from previous defining opaque type use + //~^ ERROR expected generic lifetime parameter, found `'_` } fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index c19420bbb0c..6064b09ef09 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -1,21 +1,11 @@ -error: concrete type differs from previous defining opaque type use - --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 - | -LL | |x| x - | ^ expected `impl Debug + '_`, got `&u8` - | -note: previous use here - --> $DIR/impl-fn-predefined-lifetimes.rs:7:5 - | -LL | |x| x - | ^^^^^ - -error[E0720]: cannot resolve opaque type - --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/impl-fn-predefined-lifetimes.rs:5:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ cannot resolve opaque type + | -- this generic parameter must be used with a generic lifetime parameter +LL | |x| x + | ^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0720`. +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs index 41d5f0f6449..5b3a4eb53ff 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.rs @@ -5,6 +5,7 @@ trait Foo { fn bar<'other: 'a>() -> impl Sized + 'a {} //~^ ERROR use of undeclared lifetime name `'a` //~| ERROR use of undeclared lifetime name `'a` + //~| ERROR expected generic lifetime parameter, found `'static` } fn main() {} diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr index b0832eb33ca..8975578dabd 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit-2.stderr @@ -28,6 +28,15 @@ help: consider introducing lifetime `'a` here LL | trait Foo<'a> { | ++++ -error: aborting due to 2 previous errors +error[E0792]: expected generic lifetime parameter, found `'static` + --> $DIR/bad-item-bound-within-rpitit-2.rs:5:45 + | +LL | fn bar<'other: 'a>() -> impl Sized + 'a {} + | ------ ^^ + | | + | cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0261`. +Some errors have detailed explanations: E0261, E0792. +For more information about an error, try `rustc --explain E0261`. diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs index 6dda687929c..005bcea59f2 100644 --- a/tests/ui/impl-trait/rpit/early_bound.rs +++ b/tests/ui/impl-trait/rpit/early_bound.rs @@ -5,6 +5,7 @@ fn test<'a: 'a>(n: bool) -> impl Sized + 'a { let true = n else { loop {} }; let _ = || { let _ = identity::<&'a ()>(test(false)); + //~^ ERROR expected generic lifetime parameter, found `'_` }; loop {} } diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.stderr index 780dea4e284..b0c7bd4199c 100644 --- a/tests/ui/impl-trait/rpit/early_bound.stderr +++ b/tests/ui/impl-trait/rpit/early_bound.stderr @@ -1,3 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/early_bound.rs:7:17 + | +LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a { + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | let _ = identity::<&'a ()>(test(false)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: concrete type differs from previous defining opaque type use --> $DIR/early_bound.rs:3:29 | @@ -10,5 +19,6 @@ note: previous use here LL | let _ = identity::<&'a ()>(test(false)); | ^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs new file mode 100644 index 00000000000..5e04e6b091a --- /dev/null +++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs @@ -0,0 +1,37 @@ +// issue: #111935 + +#![allow(unconditional_recursion)] + +// Lt indirection is necessary to make the lifetime of the function late-bound, +// in order to bypass some other bugs. +type Lt<'lt> = Option<*mut &'lt ()>; + +mod statik { + use super::*; + // invalid defining use: Opaque<'static> := () + fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { + let _: () = foo(Lt::<'static>::None); + //~^ ERROR expected generic lifetime parameter, found `'static` + } +} + +mod infer { + use super::*; + // invalid defining use: Opaque<'_> := () + fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { + let _: () = foo(Lt::<'_>::None); + //~^ ERROR expected generic lifetime parameter, found `'_` + } +} + +mod equal { + use super::*; + // invalid defining use: Opaque<'a, 'a> := () + // because of the use of equal lifetimes in args + fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b { + let _: () = foo(Lt::<'a>::None, Lt::<'a>::None); + //~^ ERROR non-defining opaque type use in defining scope + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr new file mode 100644 index 00000000000..d2a224601fb --- /dev/null +++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr @@ -0,0 +1,31 @@ +error[E0792]: expected generic lifetime parameter, found `'static` + --> $DIR/non-defining-use-lifetimes.rs:13:16 + | +LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +LL | let _: () = foo(Lt::<'static>::None); + | ^^ + +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/non-defining-use-lifetimes.rs:22:16 + | +LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { + | -- this generic parameter must be used with a generic lifetime parameter +LL | let _: () = foo(Lt::<'_>::None); + | ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/non-defining-use-lifetimes.rs:32:16 + | +LL | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None); + | ^^ + | +note: lifetime used multiple times + --> $DIR/non-defining-use-lifetimes.rs:31:58 + | +LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b { + | ^^ ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs new file mode 100644 index 00000000000..3b83b2e544b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs @@ -0,0 +1,18 @@ +// The defining use below has an unconstrained lifetime argument. +// Opaque<'{empty}, 'a> := (); +// Make sure we accept it because the lifetime parameter in such position is +// irrelevant - it is an artifact of how we internally represent opaque +// generics. +// See issue #122307 for details. + +//@ 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() {} diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs index d97a3010a17..0e1d44e7bb3 100644 --- a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs +++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs @@ -8,12 +8,24 @@ impl<T> Equate for T { type Proj = T; } trait Indirect { type Ty; } impl<A, B: Equate<Proj = A>> Indirect for (A, B) { type Ty = (); } -type Opq = impl Sized; -fn define_1(_: Opq) { - let _ = None::<<(Opq, u8) as Indirect>::Ty>; +mod basic { + use super::*; + type Opq = impl Sized; + fn define_1(_: Opq) { + let _ = None::<<(Opq, u8) as Indirect>::Ty>; + } + fn define_2() -> Opq { + 0u8 + } } -fn define_2() -> Opq { - 0u8 + +// `Opq<'a> == &'b u8` shouldn't be an error because `'a == 'b`. +mod lifetime { + use super::*; + type Opq<'a> = impl Sized + 'a; + fn define<'a: 'b, 'b: 'a>(_: Opq<'a>) { + let _ = None::<<(Opq<'a>, &'b u8) as Indirect>::Ty>; + } } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs new file mode 100644 index 00000000000..9101e4385b3 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs @@ -0,0 +1,19 @@ +#![feature(type_alias_impl_trait)] + +mod case1 { + type Opaque<'x> = impl Sized + 'x; + fn foo<'s>() -> Opaque<'s> { + let _ = || { let _: Opaque<'s> = (); }; + //~^ ERROR expected generic lifetime parameter, found `'_` + } +} + +mod case2 { + type Opaque<'x> = impl Sized + 'x; + fn foo<'s>() -> Opaque<'s> { + let _ = || -> Opaque<'s> {}; + //~^ ERROR expected generic lifetime parameter, found `'_` + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr new file mode 100644 index 00000000000..a8fd1f691dd --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr @@ -0,0 +1,21 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/defined-in-closure-external-lifetime.rs:6:29 + | +LL | type Opaque<'x> = impl Sized + 'x; + | -- this generic parameter must be used with a generic lifetime parameter +LL | fn foo<'s>() -> Opaque<'s> { +LL | let _ = || { let _: Opaque<'s> = (); }; + | ^^^^^^^^^^ + +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/defined-in-closure-external-lifetime.rs:14:34 + | +LL | type Opaque<'x> = impl Sized + 'x; + | -- this generic parameter must be used with a generic lifetime parameter +LL | fn foo<'s>() -> Opaque<'s> { +LL | let _ = || -> Opaque<'s> {}; + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs new file mode 100644 index 00000000000..59ba2694a76 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs @@ -0,0 +1,37 @@ +// issue: #112841 + +#![feature(type_alias_impl_trait)] + +trait Trait<'a, 'b> {} +impl<T> Trait<'_, '_> for T {} + +mod mod1 { + type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + fn test<'a>() -> Opaque<'a, 'a> {} + //~^ ERROR non-defining opaque type use in defining scope + //~| ERROR non-defining opaque type use in defining scope +} + +mod mod2 { + type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {} + //~^ ERROR non-defining opaque type use in defining scope +} + +mod mod3 { + type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a } + //~^ ERROR non-defining opaque type use in defining scope +} + +// This is similar to the previous cases in that 'a is equal to 'static, +// which is is some sense an implicit parameter to `Opaque`. +// For example, given a defining use `Opaque<'a> := &'a ()`, +// it is ambiguous whether `Opaque<'a> := &'a ()` or `Opaque<'a> := &'static ()` +mod mod4 { + type Opaque<'a> = impl super::Trait<'a, 'a>; + fn test<'a: 'static>() -> Opaque<'a> {} + //~^ ERROR expected generic lifetime parameter, found `'static` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr new file mode 100644 index 00000000000..b08bc8b8268 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr @@ -0,0 +1,59 @@ +error: non-defining opaque type use in defining scope + --> $DIR/equal-lifetime-params-not-ok.rs:10:22 + | +LL | fn test<'a>() -> Opaque<'a, 'a> {} + | ^^^^^^^^^^^^^^ generic argument `'a` used twice + | +note: for this opaque type + --> $DIR/equal-lifetime-params-not-ok.rs:9:27 + | +LL | type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: non-defining opaque type use in defining scope + --> $DIR/equal-lifetime-params-not-ok.rs:10:37 + | +LL | fn test<'a>() -> Opaque<'a, 'a> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/equal-lifetime-params-not-ok.rs:9:17 + | +LL | type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/equal-lifetime-params-not-ok.rs:17:49 + | +LL | fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {} + | ^^ + | +note: lifetime used multiple times + --> $DIR/equal-lifetime-params-not-ok.rs:16:17 + | +LL | type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + | ^^ ^^ + +error: non-defining opaque type use in defining scope + --> $DIR/equal-lifetime-params-not-ok.rs:23:61 + | +LL | fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a } + | ^ + | +note: lifetime used multiple times + --> $DIR/equal-lifetime-params-not-ok.rs:22:17 + | +LL | type Opaque<'a, 'b> = impl super::Trait<'a, 'b>; + | ^^ ^^ + +error[E0792]: expected generic lifetime parameter, found `'static` + --> $DIR/equal-lifetime-params-not-ok.rs:33:42 + | +LL | type Opaque<'a> = impl super::Trait<'a, 'a>; + | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type +LL | fn test<'a: 'static>() -> Opaque<'a> {} + | ^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs new file mode 100644 index 00000000000..0ce85a4d6cb --- /dev/null +++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs @@ -0,0 +1,52 @@ +// Normally we do not allow equal lifetimes in opaque type generic args at +// their defining sites. An exception to this rule, however, is when the bounds +// of the opaque type *require* the lifetimes to be equal. +// issue: #113916 +//@ check-pass + +#![feature(type_alias_impl_trait)] +#![feature(impl_trait_in_assoc_type)] + +trait Trait<'a, 'b> {} +impl<T> Trait<'_, '_> for T {} + +mod equal_params { + type Opaque<'a: 'b, 'b: 'a> = impl super::Trait<'a, 'b>; + fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> { + let _ = None::<&'a &'b &'a ()>; + 0u8 + } +} + +mod equal_static { + type Opaque<'a: 'static> = impl Sized + 'a; + fn test<'a: 'static>() -> Opaque<'a> { + let _ = None::<&'static &'a ()>; + 0u8 + } +} + +mod implied_bounds { + trait Traitor { + type Assoc; + fn define(self) -> Self::Assoc; + } + + impl<'a> Traitor for &'static &'a () { + type Assoc = impl Sized + 'a; + fn define(self) -> Self::Assoc { + let _ = None::<&'static &'a ()>; + 0u8 + } + } + + impl<'a, 'b> Traitor for (&'a &'b (), &'b &'a ()) { + type Assoc = impl Sized + 'a + 'b; + fn define(self) -> Self::Assoc { + let _ = None::<(&'a &'b (), &'b &'a ())>; + 0u8 + } + } +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr new file mode 100644 index 00000000000..e5f86c8c193 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/generic-not-strictly-equal.rs:33:5 + | +LL | type Opaque<'a> = impl Copy + Captures<'a>; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | relate(opaque, hidden); // defining use: Opaque<'?1> := u8 + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr new file mode 100644 index 00000000000..693af69d6fa --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr @@ -0,0 +1,15 @@ +error[E0700]: hidden type for `Opaque<'x>` captures lifetime that does not appear in bounds + --> $DIR/generic-not-strictly-equal.rs:33:5 + | +LL | type Opaque<'a> = impl Copy + Captures<'a>; + | ------------------------ opaque type defined here +LL | +LL | fn test<'x>(_: Opaque<'x>) { + | -- hidden type `&'x u8` captures the lifetime `'x` as defined here +... +LL | relate(opaque, hidden); // defining use: Opaque<'?1> := u8 + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs new file mode 100644 index 00000000000..a059fd3b822 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs @@ -0,0 +1,38 @@ +// `Opaque<'?1> := u8` is not a valid defining use here. +// +// Due to fundamental limitations of the member constraints algorithm, +// we require '?1 to be *equal* to some universal region. +// +// While '?1 is eventually inferred to be equal to 'x because of the constraint '?1: 'x, +// we don't consider them equal in the strict sense because they lack the bidirectional outlives +// constraints ['?1: 'x, 'x: '?1]. In NLL terms, they are not part of the same SCC. +// +// See #113971 for details. + +//@ revisions: basic member_constraints +#![feature(type_alias_impl_trait)] + +trait Captures<'a> {} +impl<T> Captures<'_> for T {} + +fn ensure_outlives<'a, X: 'a>(_: X) {} +fn relate<X>(_: X, _: X) {} + +type Opaque<'a> = impl Copy + Captures<'a>; + +fn test<'x>(_: Opaque<'x>) { + let opaque = None::<Opaque<'_>>; // let's call this lifetime '?1 + + #[cfg(basic)] + let hidden = None::<u8>; + + #[cfg(member_constraints)] + let hidden = None::<&'x u8>; + + ensure_outlives::<'x>(opaque); // outlives constraint: '?1: 'x + relate(opaque, hidden); // defining use: Opaque<'?1> := u8 + //[basic]~^ ERROR expected generic lifetime parameter, found `'_` + //[member_constraints]~^^ ERROR captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs index ef9fe604ea7..3b54fb7ea99 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs @@ -13,6 +13,7 @@ type FutNothing<'a> = impl 'a + Future<Output = ()>; async fn operation(_: &mut ()) -> () { //~^ ERROR: concrete type differs from previous call(operation).await + //~^ ERROR: expected generic lifetime parameter, found `'any` } async fn call<F>(_f: F) diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index cd4982b2480..c41ed0642a4 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -6,20 +6,17 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; | = note: `FutNothing` must be used in combination with a concrete type within the same module -error: concrete type differs from previous defining opaque type use - --> $DIR/hkl_forbidden4.rs:13:1 - | -LL | async fn operation(_: &mut ()) -> () { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}` - | -note: previous use here +error[E0792]: expected generic lifetime parameter, found `'any` --> $DIR/hkl_forbidden4.rs:15:5 | +LL | async fn operation(_: &mut ()) -> () { + | - this generic parameter must be used with a generic lifetime parameter +LL | LL | call(operation).await | ^^^^^^^^^^^^^^^ error[E0792]: expected generic lifetime parameter, found `'any` - --> $DIR/hkl_forbidden4.rs:21:1 + --> $DIR/hkl_forbidden4.rs:22:1 | LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; | -- this generic parameter must be used with a generic lifetime parameter @@ -29,6 +26,18 @@ LL | | LL | | } | |_^ -error: aborting due to 3 previous errors +error: concrete type differs from previous defining opaque type use + --> $DIR/hkl_forbidden4.rs:13:1 + | +LL | async fn operation(_: &mut ()) -> () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}` + | +note: previous use here + --> $DIR/hkl_forbidden4.rs:15:5 + | +LL | call(operation).await + | ^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs index 9ec585d93f5..45a55050c44 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs @@ -5,7 +5,6 @@ type Foo<'a> = impl Sized; fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) { (x, y) //~^ ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes } type Bar<'a, 'b> = impl std::fmt::Debug; @@ -13,9 +12,6 @@ type Bar<'a, 'b> = impl std::fmt::Debug; fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) { (i, j) //~^ ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes } fn main() { diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr index 7f54f47d27d..4f7b0f17407 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr @@ -14,53 +14,7 @@ LL | (x, y) | ^^^^^^ error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:6:5 - | -LL | (x, y) - | ^^^^^^ - | | - | lifetime `'a` used here - | lifetime `'b` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:6:5 - | -LL | (x, y) - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - | | - | lifetime `'x` used here - | lifetime `'y` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - -error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - | | - | lifetime `'y` used here - | lifetime `'x` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - -error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:14:5 + --> $DIR/lifetime_mismatch.rs:13:5 | LL | (i, j) | ^^^^^^ @@ -69,27 +23,10 @@ LL | (i, j) | lifetime `'y` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:14:5 - | -LL | (i, j) - | ^^^^^^ - | | - | lifetime `'y` used here - | lifetime `'x` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:14:5 + --> $DIR/lifetime_mismatch.rs:13:5 | LL | (i, j) | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 6 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs index 5bec38c5e5b..580fb58ef83 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -3,11 +3,8 @@ type Foo<'a, 'b> = impl std::fmt::Debug; fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { - (i, i) + (i, j) //~^ ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes - //~| ERROR opaque type used twice with different lifetimes } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr index 0ccb3e2221d..b2b9e604a6b 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr @@ -1,7 +1,7 @@ error: opaque type used twice with different lifetimes --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 | -LL | (i, i) +LL | (i, j) | ^^^^^^ | | | lifetime `'x` used here @@ -10,55 +10,8 @@ LL | (i, i) note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 | -LL | (i, i) +LL | (i, j) | ^^^^^^ -error: opaque type used twice with different lifetimes - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - | | - | lifetime `'y` used here - | lifetime `'x` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - -error: opaque type used twice with different lifetimes - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - | | - | lifetime `'x` used here - | lifetime `'y` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: opaque type used twice with different lifetimes - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - | | - | lifetime `'y` used here - | lifetime `'x` previously used here - | -note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5 - | -LL | (i, i) - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.rs b/tests/ui/type-alias-impl-trait/param_mismatch4.rs new file mode 100644 index 00000000000..e072f3ab8e0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/param_mismatch4.rs @@ -0,0 +1,16 @@ +//! This test checks that when checking for opaque types that +//! only differ in lifetimes, we handle the case of non-generic +//! regions correctly. +#![feature(type_alias_impl_trait)] + +type Opq<'a> = impl Sized; + +// Two defining uses: Opq<'{empty}> and Opq<'a>. +// This used to ICE. +// issue: #122782 +fn build<'a>() -> Opq<'a> { + let _: Opq<'_> = (); + //~^ ERROR expected generic lifetime parameter, found `'_` +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr new file mode 100644 index 00000000000..d3fdea25a3d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr @@ -0,0 +1,12 @@ +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/param_mismatch4.rs:12:12 + | +LL | type Opq<'a> = impl Sized; + | -- this generic parameter must be used with a generic lifetime parameter +... +LL | let _: Opq<'_> = (); + | ^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0792`. |
