diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index b7862691b05f3..8fba8b493bd6b 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -404,7 +404,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // For soundness, we need to ensure that every region that is captured by the opaque type // but does not explicitly appear in the opaque type outlives the actual (concrete) type. // This allows for invariant lifetimes to be captured by opaque types as long as - // short-lived lifetimes are not permitted to escape and cause UB. + // short-lived lifetimes are not permitted to escape and cause UB. let opaque_substs_regions = opaque_defn.substs.regions().collect(); let captured_regions = concrete_ty_regions.difference(&opaque_substs_regions); for captured_region in captured_regions { diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs index 7ebc348996f5e..68ebaa5b46491 100644 --- a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs +++ b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs @@ -1,9 +1,9 @@ +// run-pass + // This used to ICE because it creates an `impl Trait` that captures a // hidden empty region. -#![feature(conservative_impl_trait)] - -fn server() -> impl FilterBase2 { //~ ERROR [E0700] +fn server() -> impl FilterBase2 { segment2(|| { loop { } }).map2(|| "") } diff --git a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs index e2310a3907f7e..d7f114f823003 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs +++ b/src/test/ui/impl-trait/region-escape-via-bound-contravariant.rs @@ -1,4 +1,4 @@ -// In contrast to `region-escape-via-bound-invariant`, in this case we +// In contrast to `region-escape-via-bound.rs`, in this case we // *can* return a value of type `&'x u32`, even though `'x` does not // appear in the bounds. This is because `&` is contravariant, and so // we are *actually* returning a `&'y u32`. diff --git a/src/test/ui/impl-trait/region-escape-via-bound.rs b/src/test/ui/impl-trait/region-escape-via-bound.rs index d62aec800e8ce..6c3e7c292e67e 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.rs +++ b/src/test/ui/impl-trait/region-escape-via-bound.rs @@ -1,5 +1,7 @@ -// Test that we do not allow the region `'x` to escape in the impl -// trait **even though** `'y` escapes, which outlives `'x`. +// run-pass + +// Test that we allow the region `'x` to escape in the impl +// because 'y` escapes, which outlives `'x`. // // See https://github.com/rust-lang/rust/issues/46541 for more details. @@ -14,10 +16,14 @@ trait Trait<'a> { } impl Trait<'b> for Cell<&'a u32> { } fn foo(x: Cell<&'x u32>) -> impl Trait<'y> - //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700] + // ^ hidden type for `impl Trait` captures lifetime that does not appear in bounds + // because it outlives the lifetime that *does* appear in the bounds, `'y` where 'x: 'y { x } -fn main() { } +fn main() { + let x = 123; + let _ = foo(Cell::new(&x)); +} diff --git a/src/test/ui/impl-trait/region-escape-via-swap.rs b/src/test/ui/impl-trait/region-escape-via-swap.rs new file mode 100644 index 0000000000000..f31440bc99c5e --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-swap.rs @@ -0,0 +1,29 @@ +// compile-fail + +// See https://github.com/rust-lang/rust/pull/57870#issuecomment-457333709 for more details. + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for &mut T { + fn swap(self, other: Self) { + std::mem::swap(self, other); + } +} + +// The hidden relifetimegion `'b` should not be allowed to escape this function, since it may not +// outlive '`a`, in which case we have a dangling reference. +fn hide<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { +//~^ lifetime mismatch [E0623] + x +} + +fn dangle() -> &'static [i32; 3] { + let mut res = &[4, 5, 6]; + let x = [1, 2, 3]; + hide(&mut res).swap(hide(&mut &x)); + res +} + +fn main() {} diff --git a/src/test/ui/impl-trait/region-escape-via-swap.stderr b/src/test/ui/impl-trait/region-escape-via-swap.stderr new file mode 100644 index 0000000000000..ad5418a6e1b2f --- /dev/null +++ b/src/test/ui/impl-trait/region-escape-via-swap.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/region-escape-via-swap.rs:17:50 + | +LL | fn hide<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + | ----- ^^^^^^^^^^^^^^ + | | | + | | ...but data from `x` is returned here + | this parameter and the return type are declared with different lifetimes... + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0623`.