diff options
Diffstat (limited to 'tests/ui/object-lifetime')
28 files changed, 878 insertions, 0 deletions
diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs new file mode 100644 index 000000000..5dae92fee --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.rs @@ -0,0 +1,48 @@ +// Test that if a struct declares multiple region bounds for a given +// type parameter, an explicit lifetime bound is required on object +// lifetimes within. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct Ref0<T:?Sized> { + r: *mut T +} + +struct Ref1<'a,T:'a+?Sized> { + r: &'a T +} + +struct Ref2<'a,'b:'a,T:'a+'b+?Sized> { + r: &'a &'b T +} + +fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn b(t: Ref2<dyn Test>) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn c(t: Ref2<&dyn Test>) { + // In this case, the &'a overrides. +} + +fn d(t: Ref2<Ref1<dyn Test>>) { + // In this case, the lifetime parameter from the Ref1 overrides. +} + +fn e(t: Ref2<Ref0<dyn Test>>) { + // In this case, Ref2 is ambiguous, but Ref0 overrides with 'static. +} + +fn f(t: &Ref2<dyn Test>) { + //~^ ERROR lifetime bound for this object type cannot be deduced from context +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr new file mode 100644 index 000000000..bd50a27fd --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-ambiguous.stderr @@ -0,0 +1,21 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:23:28 + | +LL | fn a<'a,'b>(t: Ref2<'a,'b, dyn Test>) { + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:27:14 + | +LL | fn b(t: Ref2<dyn Test>) { + | ^^^^^^^^ + +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-ambiguous.rs:43:15 + | +LL | fn f(t: &Ref2<dyn Test>) { + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs b/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs new file mode 100644 index 000000000..467767ae5 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-default-to-static.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that `Box<Test>` is equivalent to `Box<Test+'static>`, both in +// fields and fn arguments. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct { + t: Box<dyn Test>, + u: Box<dyn Test+'static>, +} + +fn a(t: Box<dyn Test>, mut ss: SomeStruct) { + ss.t = t; +} + +fn b(t: Box<dyn Test+'static>, mut ss: SomeStruct) { + ss.t = t; +} + +fn c(t: Box<dyn Test>, mut ss: SomeStruct) { + ss.u = t; +} + +fn d(t: Box<dyn Test+'static>, mut ss: SomeStruct) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs new file mode 100644 index 000000000..7337383e2 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs @@ -0,0 +1,27 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr new file mode 100644 index 000000000..f06a9da1d --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs new file mode 100644 index 000000000..2a7415174 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs @@ -0,0 +1,30 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: 'a + ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo<'_> for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'a`. Or, we *should*, but the +// current code forces us into a conservative, hacky path. +fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + + // If it weren't for the conservative path above, we'd expect an + // error here. + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr new file mode 100644 index 000000000..51d8450af --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50 + | +LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs new file mode 100644 index 000000000..51be999a6 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs @@ -0,0 +1,23 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. + +trait Foo<'a> { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we should default to `dyn Bar + 'static`, but the current +// code forces us into a conservative, hacky path. +fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } +//~^ ERROR please supply an explicit bound + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr new file mode 100644 index 000000000..f721bf394 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -0,0 +1,9 @@ +error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound + --> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36 + | +LL | fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } + | ^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0228`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs new file mode 100644 index 000000000..339f3356b --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs @@ -0,0 +1,28 @@ +// Test that `dyn Bar<Item = XX>` uses `'static` as the default object +// lifetime bound for the type `XX`. +// +// check-pass + +trait Foo { + type Item: ?Sized; + + fn item(&self) -> Box<Self::Item> { panic!() } +} + +trait Bar { } + +impl<T> Foo for T { + type Item = dyn Bar; +} + +fn is_static<T>(_: T) where T: 'static { } + +// Here, we default to `dyn Bar + 'static`, and not `&'x dyn Foo<Item +// = dyn Bar + 'x>`. +fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() } + +fn main() { + let s = format!("foo"); + let r = bar(&s); + is_static(r.item()); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.rs b/tests/ui/object-lifetime/object-lifetime-default-elision.rs new file mode 100644 index 000000000..f7c0261cf --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.rs @@ -0,0 +1,76 @@ +// Test various cases where the old rules under lifetime elision +// yield slightly different results than the new rules. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct SomeStruct<'a> { + r: Box<dyn SomeTrait+'a> +} + +fn deref<T>(ss: &T) -> T { + // produces the type of a deref without worrying about whether a + // move out would actually be legal + loop { } +} + +fn load0<'a>(ss: &'a Box<dyn SomeTrait>) -> Box<dyn SomeTrait> { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b> fn(&'a Box<SomeTrait+'b>) -> Box<SomeTrait+'a> + // + // Under new rules the result is: + // + // for<'a> fn(&'a Box<SomeTrait+'static>) -> Box<SomeTrait+'static> + // + // Therefore, no type error. + + deref(ss) +} + +fn load1(ss: &dyn SomeTrait) -> &dyn SomeTrait { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b> fn(&'a (SomeTrait+'b)) -> &'a (SomeTrait+'a) + // + // Under new rules the result is: + // + // for<'a> fn(&'a (SomeTrait+'a)) -> &'a (SomeTrait+'a) + // + // In both cases, returning `ss` is legal. + + ss +} + +fn load2<'a>(ss: &'a dyn SomeTrait) -> &dyn SomeTrait { + // Same as `load1` but with an explicit name thrown in for fun. + + ss +} + +fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { + // Under old rules, the fully elaborated types of input/output were: + // + // for<'a,'b,'c>fn(&'a (SomeTrait+'c)) -> &'b (SomeTrait+'a) + // + // Based on the input/output types, the compiler could infer that + // 'c : 'a + // 'b : 'a + // must hold, and therefore it permitted `&'a (Sometrait+'c)` to be + // coerced to `&'b (SomeTrait+'a)`. + // + // Under the newer defaults, though, we get: + // + // for<'a,'b> fn(&'a (SomeTrait+'a)) -> &'b (SomeTrait+'b) + // + // which fails to type check. + + ss + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-elision.stderr b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr new file mode 100644 index 000000000..61e96f59f --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -0,0 +1,15 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-elision.rs:71:5 + | +LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | ss + | ^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs new file mode 100644 index 000000000..f9b3e2238 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.rs @@ -0,0 +1,37 @@ +// Test various cases where the defaults should lead to errors being +// reported. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct SomeStruct<'a> { + r: Box<dyn SomeTrait+'a> +} + +fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> { + // `Box<SomeTrait>` defaults to a `'static` bound, so this return + // is illegal. + + ss.r + //~^ ERROR lifetime may not live long enough + //~| ERROR cannot move out of +} + +fn store(ss: &mut SomeStruct, b: Box<dyn SomeTrait>) { + // No error: b is bounded by 'static which outlives the + // (anonymous) lifetime on the struct. + + ss.r = b; +} + +fn store1<'b>(ss: &mut SomeStruct, b: Box<dyn SomeTrait+'b>) { + // Here we override the lifetimes explicitly, and so naturally we get an error. + + ss.r = b; //~ ERROR explicit lifetime required in the type of `ss` [E0621] +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr new file mode 100644 index 000000000..15b36925c --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-box-error.stderr @@ -0,0 +1,33 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-box-error.rs:18:5 + | +LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> { + | -- has type `&mut SomeStruct<'1>` +... +LL | ss.r + | ^^^^ returning this value requires that `'1` must outlive `'static` + | +help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound + | +LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> { + | ++++ + +error[E0507]: cannot move out of `ss.r` which is behind a mutable reference + --> $DIR/object-lifetime-default-from-box-error.rs:18:5 + | +LL | ss.r + | ^^^^ move occurs because `ss.r` has type `Box<dyn SomeTrait>`, which does not implement the `Copy` trait + +error[E0621]: explicit lifetime required in the type of `ss` + --> $DIR/object-lifetime-default-from-box-error.rs:33:5 + | +LL | fn store1<'b>(ss: &mut SomeStruct, b: Box<dyn SomeTrait+'b>) { + | --------------- help: add explicit lifetime `'b` to the type of `ss`: `&mut SomeStruct<'b>` +... +LL | ss.r = b; + | ^^^^ lifetime `'b` required + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0507, E0621. +For more information about an error, try `rustc --explain E0507`. diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs b/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs new file mode 100644 index 000000000..e1a865fa5 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs @@ -0,0 +1,58 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::fmt::Display; + +trait Test { + fn foo(&self) { } +} + +struct Ref<'a,T:'a+?Sized> { + r: &'a T +} + +struct Ref2<'a,'b,T:'a+'b+?Sized> { + a: &'a T, + b: &'b T +} + +struct SomeStruct<'a> { + t: Ref<'a, dyn Test>, + u: Ref<'a, dyn Test+'a>, +} + +fn a<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: Ref<'a, dyn Test>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: Ref<'a, dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn e<'a>(_: Ref<'a, dyn Display+'static>) {} +fn g<'a, 'b>(_: Ref2<'a, 'b, dyn Display+'static>) {} + + +fn main() { + // Inside a function body, we can just infer all + // lifetimes, to allow Ref<'tmp, Display+'static> + // and Ref2<'tmp, 'tmp, Display+'static>. + let x = &0 as &(dyn Display+'static); + let r: Ref<dyn Display> = Ref { r: x }; + let r2: Ref2<dyn Display> = Ref2 { a: x, b: x }; + e(r); + g(r2); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs new file mode 100644 index 000000000..de79eee6a --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs @@ -0,0 +1,20 @@ +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `Box` struct. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a Box<dyn Test>, +} + +fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.t = t; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr new file mode 100644 index 000000000..7d6f9f39d --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-rptr-box-error.rs:15:5 + | +LL | fn c<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) { + | -- lifetime `'a` defined here +LL | ss.t = t; + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs new file mode 100644 index 000000000..b61083078 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs @@ -0,0 +1,33 @@ +// run-pass +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `Box` struct. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a Box<dyn Test>, + u: &'a Box<dyn Test+'a>, +} + +fn a<'a>(t: &'a Box<dyn Test>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a Box<dyn Test>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs + +fn d<'a>(t: &'a Box<dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs new file mode 100644 index 000000000..a09fc03ab --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs @@ -0,0 +1,36 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a mut dyn Test, + u: &'a mut (dyn Test+'a), +} + +fn a<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a mut dyn Test, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: &'a mut (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs new file mode 100644 index 000000000..877486e15 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs @@ -0,0 +1,25 @@ +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `MyBox` struct. + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a MyBox<dyn Test>, + u: &'a MyBox<dyn Test + 'a>, +} + +struct MyBox<T:?Sized> { + b: Box<T> +} + +fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.t = t; + //~^ ERROR lifetime may not live long enough +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr new file mode 100644 index 000000000..2bc8e0978 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:5 + | +LL | fn c<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) { + | -- lifetime `'a` defined here +LL | ss.t = t; + | ^^^^^^^^ assignment requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs new file mode 100644 index 000000000..d3e92e162 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs @@ -0,0 +1,37 @@ +// run-pass +// Test that the lifetime from the enclosing `&` is "inherited" +// through the `MyBox` struct. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a MyBox<dyn Test>, + u: &'a MyBox<dyn Test+'a>, +} + +struct MyBox<T:?Sized> { + b: Box<T> +} + +fn a<'a>(t: &'a MyBox<dyn Test>, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a MyBox<dyn Test>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +// see also ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs + +fn d<'a>(t: &'a MyBox<dyn Test+'a>, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs b/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs new file mode 100644 index 000000000..5093b1c27 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-from-rptr.rs @@ -0,0 +1,42 @@ +// run-pass +// Test that the lifetime of the enclosing `&` is used for the object +// lifetime bound. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] + +use std::fmt::Display; + +trait Test { + fn foo(&self) { } +} + +struct SomeStruct<'a> { + t: &'a dyn Test, + u: &'a (dyn Test+'a), +} + +fn a<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a>(t: &'a dyn Test, mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn c<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn d<'a>(t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn e<'a>(_: &'a (dyn Display+'static)) {} + +fn main() { + // Inside a function body, we can just infer both + // lifetimes, to allow &'tmp (Display+'static). + e(&0 as &dyn Display); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-inferred.rs b/tests/ui/object-lifetime/object-lifetime-default-inferred.rs new file mode 100644 index 000000000..8a1156b8f --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-inferred.rs @@ -0,0 +1,35 @@ +// run-pass +// Test that even with prior inferred parameters, object lifetimes of objects after are still +// valid. + +// pretty-expanded FIXME #23616 + +#![allow(dead_code)] +#![feature(generic_arg_infer)] + +trait Test { + fn foo(&self) { } +} + +struct Foo; +impl Test for Foo {} + +struct SomeStruct<'a> { + t: &'a dyn Test, + u: &'a (dyn Test+'a), +} + +fn a<'a, const N: usize>(_: [u8; N], t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.t = t; +} + +fn b<'a, T>(_: T, t: &'a (dyn Test+'a), mut ss: SomeStruct<'a>) { + ss.u = t; +} + +fn main() { + // Inside a function body, we can just infer both + // lifetimes, to allow &'tmp (Display+'static). + a::<_>([], &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo}); + b::<_>(0u8, &Foo as &dyn Test, SomeStruct{t:&Foo,u:&Foo}); +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-mybox.rs b/tests/ui/object-lifetime/object-lifetime-default-mybox.rs new file mode 100644 index 000000000..5e6e5e2c0 --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-mybox.rs @@ -0,0 +1,37 @@ +// Test a "pass-through" object-lifetime-default that produces errors. + +#![allow(dead_code)] + +trait SomeTrait { + fn dummy(&self) { } +} + +struct MyBox<T:?Sized> { + r: Box<T> +} + +fn deref<T>(ss: &T) -> T { + // produces the type of a deref without worrying about whether a + // move out would actually be legal + loop { } +} + +fn load0(ss: &MyBox<dyn SomeTrait>) -> MyBox<dyn SomeTrait> { + deref(ss) +} + +fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>, + b: &'b MyBox<dyn SomeTrait>) + -> &'b MyBox<dyn SomeTrait> +{ + a + //~^ ERROR lifetime may not live long enough +} + +fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> { + load0(ss) + //~^ ERROR borrowed data escapes outside of function +} + +fn main() { +} diff --git a/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr new file mode 100644 index 000000000..a1ef0243e --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -0,0 +1,29 @@ +error: lifetime may not live long enough + --> $DIR/object-lifetime-default-mybox.rs:27:5 + | +LL | fn load1<'a,'b>(a: &'a MyBox<dyn SomeTrait>, + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a + | ^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | + = help: consider adding the following bound: `'a: 'b` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/object-lifetime-default-mybox.rs:32:5 + | +LL | fn load2<'a>(ss: &MyBox<dyn SomeTrait + 'a>) -> MyBox<dyn SomeTrait + 'a> { + | -- -- `ss` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | load0(ss) + | ^^^^^^^^^ + | | + | `ss` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/object-lifetime/object-lifetime-default.rs b/tests/ui/object-lifetime/object-lifetime-default.rs new file mode 100644 index 000000000..74f5bb7dd --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default.rs @@ -0,0 +1,50 @@ +#![feature(rustc_attrs)] + +#[rustc_object_lifetime_default] +struct A< + T, //~ ERROR BaseDefault +>(T); + +#[rustc_object_lifetime_default] +struct B< + 'a, + T, //~ ERROR BaseDefault +>(&'a (), T); + +#[rustc_object_lifetime_default] +struct C< + 'a, + T: 'a, //~ ERROR 'a +>(&'a T); + +#[rustc_object_lifetime_default] +struct D< + 'a, + 'b, + T: 'a + 'b, //~ ERROR Ambiguous +>(&'a T, &'b T); + +#[rustc_object_lifetime_default] +struct E< + 'a, + 'b: 'a, + T: 'b, //~ ERROR 'b +>(&'a T, &'b T); + +#[rustc_object_lifetime_default] +struct F< + 'a, + 'b, + T: 'a, //~ ERROR 'a + U: 'b, //~ ERROR 'b +>(&'a T, &'b U); + +#[rustc_object_lifetime_default] +struct G< + 'a, + 'b, + T: 'a, //~ ERROR 'a + U: 'a + 'b, //~ ERROR Ambiguous +>(&'a T, &'b U); + +fn main() {} diff --git a/tests/ui/object-lifetime/object-lifetime-default.stderr b/tests/ui/object-lifetime/object-lifetime-default.stderr new file mode 100644 index 000000000..a58afad3e --- /dev/null +++ b/tests/ui/object-lifetime/object-lifetime-default.stderr @@ -0,0 +1,56 @@ +error: BaseDefault + --> $DIR/object-lifetime-default.rs:5:5 + | +LL | T, + | ^ + +error: BaseDefault + --> $DIR/object-lifetime-default.rs:11:5 + | +LL | T, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:17:5 + | +LL | T: 'a, + | ^ + +error: Ambiguous + --> $DIR/object-lifetime-default.rs:24:5 + | +LL | T: 'a + 'b, + | ^ + +error: 'b + --> $DIR/object-lifetime-default.rs:31:5 + | +LL | T: 'b, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:38:5 + | +LL | T: 'a, + | ^ + +error: 'b + --> $DIR/object-lifetime-default.rs:39:5 + | +LL | U: 'b, + | ^ + +error: 'a + --> $DIR/object-lifetime-default.rs:46:5 + | +LL | T: 'a, + | ^ + +error: Ambiguous + --> $DIR/object-lifetime-default.rs:47:5 + | +LL | U: 'a + 'b, + | ^ + +error: aborting due to 9 previous errors + |