diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 8c9de5210cd38..1073ea4069483 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -225,21 +225,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Find something that we can name let upper_bound = self.approx_universal_upper_bound(vid); - let upper_bound = &self.definitions[upper_bound]; - match upper_bound.external_name { - Some(reg) => reg, - None => { - // Nothing exact found, so we pick the first one that we find. - let scc = self.constraint_sccs.scc(vid); - for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) { - match self.definitions[vid].external_name { - None => {} - Some(region) if region.is_static() => {} - Some(region) => return region, - } - } - region - } + if let Some(universal_region) = self.definitions[upper_bound].external_name { + return universal_region; + } + + // Nothing exact found, so we pick a named upper bound, if there's only one. + // If there's >1 universal region, then we probably are dealing w/ an intersection + // region which cannot be mapped back to a universal. + // FIXME: We could probably compute the LUB if there is one. + let scc = self.constraint_sccs.scc(vid); + let upper_bounds: Vec<_> = self + .rev_scc_graph + .as_ref() + .unwrap() + .upper_bounds(scc) + .filter_map(|vid| self.definitions[vid].external_name) + .filter(|r| !r.is_static()) + .collect(); + match &upper_bounds[..] { + [universal_region] => *universal_region, + _ => region, } } _ => region, diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs new file mode 100644 index 0000000000000..d7b62436d2d34 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.rs @@ -0,0 +1,29 @@ +#![feature(precise_capturing)] + +use std::future::Future; +use std::pin::Pin; + +trait MyTrait { + fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future; +} + +trait ErasedMyTrait { + fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32) + -> Pin + 'dynosaur>> + where + 'life0: 'dynosaur, + 'life1: 'dynosaur; +} + +struct DynMyTrait { + ptr: T, +} + +impl MyTrait for DynMyTrait { + fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future { + self.ptr.foo(x) + //~^ ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds + } +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr new file mode 100644 index 0000000000000..92ef66c55043c --- /dev/null +++ b/tests/ui/impl-trait/in-trait/cannot-capture-intersection.stderr @@ -0,0 +1,13 @@ +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/cannot-capture-intersection.rs:24:9 + | +LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future { + | ------------------------- opaque type defined here +LL | self.ptr.foo(x) + | ^^^^^^^^^^^^^^^ + | + = note: hidden type `Pin>>` captures lifetime `'_` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr index 4d4ba58c97440..b7cee7d0b1f7a 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr @@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n --> $DIR/ordinary-bounds-unrelated.rs:28:33 | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> - | -- ------------------ opaque type defined here - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | ------------------ opaque type defined here ... LL | if condition() { a } else { b } | ^ | -help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b - | ++++ + = note: hidden type `Ordinary<'_>` captures lifetime `'_` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr index 060eaa7e64a13..d1190da6c9f89 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr @@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n --> $DIR/ordinary-bounds-unsuited.rs:31:33 | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> - | -- ------------------ opaque type defined here - | | - | hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here + | ------------------ opaque type defined here ... LL | if condition() { a } else { b } | ^ | -help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound - | -LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b - | ++++ + = note: hidden type `Ordinary<'_>` captures lifetime `'_` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr b/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr index aeeec3aca3409..3a1f685f16b79 100644 --- a/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr +++ b/tests/ui/suggestions/lifetimes/explicit-lifetime-suggestion-in-proper-span-issue-121267.stderr @@ -2,18 +2,13 @@ error[E0700]: hidden type for `impl Iterator` captures lifetime that --> $DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:7:5 | LL | fn bar(src: &crate::Foo) -> impl Iterator { - | ---------- ------------------------- opaque type defined here - | | - | hidden type `FilterMap, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures the anonymous lifetime defined here + | ------------------------- opaque type defined here LL | / [0].into_iter() LL | | LL | | .filter_map(|_| foo(src)) | |_________________________________^ | -help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` - | -LL | fn bar<'a>(src: &'a crate::Foo<'a>) -> impl Iterator + 'a { - | ++++ ++ ++++ ++++ + = note: hidden type `FilterMap, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures lifetime `'_` error: aborting due to 1 previous error