Skip to content

Commit 65a6164

Browse files
authored
Rollup merge of rust-lang#98184 - compiler-errors:elided-lifetime-in-impl-nll, r=cjgillot
Give name if anonymous region appears in impl signature Fixes rust-lang#98170 We probably should remove the two unwraps in [`report_general_error`](https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_borrowck/diagnostics/region_errors.rs.html#683-685), but I have no idea what to provide if those regions are missing, so I've kept those in. Let me know if I should try harder to remove those.
2 parents 27887f0 + e900a35 commit 65a6164

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ impl OutlivesSuggestionBuilder {
6262
| RegionNameSource::AnonRegionFromUpvar(..)
6363
| RegionNameSource::AnonRegionFromOutput(..)
6464
| RegionNameSource::AnonRegionFromYieldTy(..)
65-
| RegionNameSource::AnonRegionFromAsyncFn(..) => {
65+
| RegionNameSource::AnonRegionFromAsyncFn(..)
66+
| RegionNameSource::AnonRegionFromImplSignature(..) => {
6667
debug!("Region {:?} is NOT suggestable", name);
6768
false
6869
}

compiler/rustc_borrowck/src/diagnostics/region_name.rs

+54-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc_hir as hir;
66
use rustc_hir::def::{DefKind, Res};
77
use rustc_middle::ty::print::RegionHighlightMode;
88
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
9-
use rustc_middle::ty::{self, RegionVid, Ty};
9+
use rustc_middle::ty::{self, DefIdTree, RegionVid, Ty};
1010
use rustc_span::symbol::{kw, sym, Ident, Symbol};
1111
use rustc_span::{Span, DUMMY_SP};
1212

@@ -45,6 +45,8 @@ pub(crate) enum RegionNameSource {
4545
AnonRegionFromYieldTy(Span, String),
4646
/// An anonymous region from an async fn.
4747
AnonRegionFromAsyncFn(Span),
48+
/// An anonymous region from an impl self type or trait
49+
AnonRegionFromImplSignature(Span, &'static str),
4850
}
4951

5052
/// Describes what to highlight to explain to the user that we're giving an anonymous region a
@@ -75,7 +77,8 @@ impl RegionName {
7577
| RegionNameSource::AnonRegionFromUpvar(..)
7678
| RegionNameSource::AnonRegionFromOutput(..)
7779
| RegionNameSource::AnonRegionFromYieldTy(..)
78-
| RegionNameSource::AnonRegionFromAsyncFn(..) => false,
80+
| RegionNameSource::AnonRegionFromAsyncFn(..)
81+
| RegionNameSource::AnonRegionFromImplSignature(..) => false,
7982
}
8083
}
8184

@@ -87,7 +90,8 @@ impl RegionName {
8790
| RegionNameSource::SynthesizedFreeEnvRegion(span, _)
8891
| RegionNameSource::AnonRegionFromUpvar(span, _)
8992
| RegionNameSource::AnonRegionFromYieldTy(span, _)
90-
| RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span),
93+
| RegionNameSource::AnonRegionFromAsyncFn(span)
94+
| RegionNameSource::AnonRegionFromImplSignature(span, _) => Some(span),
9195
RegionNameSource::AnonRegionFromArgument(ref highlight)
9296
| RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight {
9397
RegionNameHighlight::MatchedHirTy(span)
@@ -166,6 +170,12 @@ impl RegionName {
166170
RegionNameSource::AnonRegionFromYieldTy(span, type_name) => {
167171
diag.span_label(*span, format!("yield type is {type_name}"));
168172
}
173+
RegionNameSource::AnonRegionFromImplSignature(span, location) => {
174+
diag.span_label(
175+
*span,
176+
format!("lifetime `{self}` appears in the `impl`'s {location}"),
177+
);
178+
}
169179
RegionNameSource::Static => {}
170180
}
171181
}
@@ -240,7 +250,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
240250
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
241251
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
242252
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
243-
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr));
253+
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
254+
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
244255

245256
if let Some(ref value) = value {
246257
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@@ -840,4 +851,43 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
840851
source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
841852
})
842853
}
854+
855+
fn give_name_if_anonymous_region_appears_in_impl_signature(
856+
&self,
857+
fr: RegionVid,
858+
) -> Option<RegionName> {
859+
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
860+
return None;
861+
};
862+
if region.has_name() {
863+
return None;
864+
};
865+
866+
let tcx = self.infcx.tcx;
867+
let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?;
868+
if tcx.parent(region.def_id) != body_parent_did
869+
|| tcx.def_kind(body_parent_did) != DefKind::Impl
870+
{
871+
return None;
872+
}
873+
874+
let mut found = false;
875+
tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| {
876+
if *r == ty::ReEarlyBound(region) {
877+
found = true;
878+
}
879+
r
880+
});
881+
882+
Some(RegionName {
883+
name: self.synthesize_region_name(),
884+
source: RegionNameSource::AnonRegionFromImplSignature(
885+
tcx.def_span(region.def_id),
886+
// FIXME(compiler-errors): Does this ever actually show up
887+
// anywhere other than the self type? I couldn't create an
888+
// example of a `'_` in the impl's trait being referenceable.
889+
if found { "self type" } else { "header" },
890+
),
891+
})
892+
}
843893
}

src/test/ui/nll/issue-98170.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
pub struct MyStruct<'a> {
2+
field: &'a [u32],
3+
}
4+
5+
impl MyStruct<'_> {
6+
pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
7+
Self { field }
8+
//~^ ERROR lifetime may not live long enough
9+
//~| ERROR lifetime may not live long enough
10+
}
11+
}
12+
13+
trait Trait<'a> {
14+
fn new(field: &'a [u32]) -> MyStruct<'a>;
15+
}
16+
17+
impl<'a> Trait<'a> for MyStruct<'_> {
18+
fn new(field: &'a [u32]) -> MyStruct<'a> {
19+
Self { field }
20+
//~^ ERROR lifetime may not live long enough
21+
//~| ERROR lifetime may not live long enough
22+
}
23+
}
24+
25+
fn main() {}

src/test/ui/nll/issue-98170.stderr

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/issue-98170.rs:7:9
3+
|
4+
LL | impl MyStruct<'_> {
5+
| -- lifetime `'1` appears in the `impl`'s self type
6+
LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
7+
| -- lifetime `'a` defined here
8+
LL | Self { field }
9+
| ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
10+
11+
error: lifetime may not live long enough
12+
--> $DIR/issue-98170.rs:7:16
13+
|
14+
LL | impl MyStruct<'_> {
15+
| -- lifetime `'1` appears in the `impl`'s self type
16+
LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
17+
| -- lifetime `'a` defined here
18+
LL | Self { field }
19+
| ^^^^^ this usage requires that `'a` must outlive `'1`
20+
21+
error: lifetime may not live long enough
22+
--> $DIR/issue-98170.rs:19:9
23+
|
24+
LL | impl<'a> Trait<'a> for MyStruct<'_> {
25+
| -- -- lifetime `'1` appears in the `impl`'s self type
26+
| |
27+
| lifetime `'a` defined here
28+
LL | fn new(field: &'a [u32]) -> MyStruct<'a> {
29+
LL | Self { field }
30+
| ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
31+
32+
error: lifetime may not live long enough
33+
--> $DIR/issue-98170.rs:19:16
34+
|
35+
LL | impl<'a> Trait<'a> for MyStruct<'_> {
36+
| -- -- lifetime `'1` appears in the `impl`'s self type
37+
| |
38+
| lifetime `'a` defined here
39+
LL | fn new(field: &'a [u32]) -> MyStruct<'a> {
40+
LL | Self { field }
41+
| ^^^^^ this usage requires that `'a` must outlive `'1`
42+
43+
error: aborting due to 4 previous errors
44+

0 commit comments

Comments
 (0)