summaryrefslogtreecommitdiffstats
path: root/src/test/ui/object-lifetime
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/object-lifetime')
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs48
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr21
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-default-to-static.rs35
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs27
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr9
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs30
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr9
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs23
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr9
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs28
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-elision.rs76
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-elision.stderr15
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs37
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr33
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs58
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs20
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr10
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs33
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs36
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs25
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr10
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs37
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-rptr.rs42
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-inferred.rs35
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-mybox.rs37
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr29
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default.rs24
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default.stderr44
28 files changed, 840 insertions, 0 deletions
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.rs
new file mode 100644
index 000000000..5dae92fee
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr
new file mode 100644
index 000000000..bd50a27fd
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-default-to-static.rs b/src/test/ui/object-lifetime/object-lifetime-default-default-to-static.rs
new file mode 100644
index 000000000..467767ae5
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.rs
new file mode 100644
index 000000000..7337383e2
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr
new file mode 100644
index 000000000..f06a9da1d
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.rs
new file mode 100644
index 000000000..2a7415174
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr
new file mode 100644
index 000000000..51d8450af
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.rs
new file mode 100644
index 000000000..51be999a6
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr
new file mode 100644
index 000000000..f721bf394
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-static.rs
new file mode 100644
index 000000000..339f3356b
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-elision.rs b/src/test/ui/object-lifetime/object-lifetime-default-elision.rs
new file mode 100644
index 000000000..f7c0261cf
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
new file mode 100644
index 000000000..61e96f59f
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
new file mode 100644
index 000000000..f9b3e2238
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
new file mode 100644
index 000000000..15b36925c
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-ref-struct.rs
new file mode 100644
index 000000000..e1a865fa5
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.rs
new file mode 100644
index 000000000..de79eee6a
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr
new file mode 100644
index 000000000..7d6f9f39d
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box.rs
new file mode 100644
index 000000000..b61083078
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-mut.rs
new file mode 100644
index 000000000..a09fc03ab
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.rs
new file mode 100644
index 000000000..877486e15
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr
new file mode 100644
index 000000000..2bc8e0978
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct.rs
new file mode 100644
index 000000000..d3e92e162
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-from-rptr.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr.rs
new file mode 100644
index 000000000..5093b1c27
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-inferred.rs b/src/test/ui/object-lifetime/object-lifetime-default-inferred.rs
new file mode 100644
index 000000000..8a1156b8f
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-mybox.rs b/src/test/ui/object-lifetime/object-lifetime-default-mybox.rs
new file mode 100644
index 000000000..5e6e5e2c0
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr
new file mode 100644
index 000000000..a1ef0243e
--- /dev/null
+++ b/src/test/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/src/test/ui/object-lifetime/object-lifetime-default.rs b/src/test/ui/object-lifetime/object-lifetime-default.rs
new file mode 100644
index 000000000..60b6629e6
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default.rs
@@ -0,0 +1,24 @@
+#![feature(rustc_attrs)]
+
+#[rustc_object_lifetime_default]
+struct A<T>(T); //~ ERROR BaseDefault
+
+#[rustc_object_lifetime_default]
+struct B<'a,T>(&'a (), T); //~ ERROR BaseDefault
+
+#[rustc_object_lifetime_default]
+struct C<'a,T:'a>(&'a T); //~ ERROR 'a
+
+#[rustc_object_lifetime_default]
+struct D<'a,'b,T:'a+'b>(&'a T, &'b T); //~ ERROR Ambiguous
+
+#[rustc_object_lifetime_default]
+struct E<'a,'b:'a,T:'b>(&'a T, &'b T); //~ ERROR 'b
+
+#[rustc_object_lifetime_default]
+struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U); //~ ERROR 'a,'b
+
+#[rustc_object_lifetime_default]
+struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U); //~ ERROR 'a,Ambiguous
+
+fn main() { }
diff --git a/src/test/ui/object-lifetime/object-lifetime-default.stderr b/src/test/ui/object-lifetime/object-lifetime-default.stderr
new file mode 100644
index 000000000..60cb98c8f
--- /dev/null
+++ b/src/test/ui/object-lifetime/object-lifetime-default.stderr
@@ -0,0 +1,44 @@
+error: BaseDefault
+ --> $DIR/object-lifetime-default.rs:4:1
+ |
+LL | struct A<T>(T);
+ | ^^^^^^^^^^^^^^^
+
+error: BaseDefault
+ --> $DIR/object-lifetime-default.rs:7:1
+ |
+LL | struct B<'a,T>(&'a (), T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'a
+ --> $DIR/object-lifetime-default.rs:10:1
+ |
+LL | struct C<'a,T:'a>(&'a T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Ambiguous
+ --> $DIR/object-lifetime-default.rs:13:1
+ |
+LL | struct D<'a,'b,T:'a+'b>(&'a T, &'b T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'b
+ --> $DIR/object-lifetime-default.rs:16:1
+ |
+LL | struct E<'a,'b:'a,T:'b>(&'a T, &'b T);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'a,'b
+ --> $DIR/object-lifetime-default.rs:19:1
+ |
+LL | struct F<'a,'b,T:'a,U:'b>(&'a T, &'b U);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: 'a,Ambiguous
+ --> $DIR/object-lifetime-default.rs:22:1
+ |
+LL | struct G<'a,'b,T:'a,U:'a+'b>(&'a T, &'b U);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+