mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Rollup merge of #98184 - compiler-errors:elided-lifetime-in-impl-nll, r=cjgillot
Give name if anonymous region appears in impl signature Fixes #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.
This commit is contained in:
commit
49bcc70574
@ -62,7 +62,8 @@ impl OutlivesSuggestionBuilder {
|
|||||||
| RegionNameSource::AnonRegionFromUpvar(..)
|
| RegionNameSource::AnonRegionFromUpvar(..)
|
||||||
| RegionNameSource::AnonRegionFromOutput(..)
|
| RegionNameSource::AnonRegionFromOutput(..)
|
||||||
| RegionNameSource::AnonRegionFromYieldTy(..)
|
| RegionNameSource::AnonRegionFromYieldTy(..)
|
||||||
| RegionNameSource::AnonRegionFromAsyncFn(..) => {
|
| RegionNameSource::AnonRegionFromAsyncFn(..)
|
||||||
|
| RegionNameSource::AnonRegionFromImplSignature(..) => {
|
||||||
debug!("Region {:?} is NOT suggestable", name);
|
debug!("Region {:?} is NOT suggestable", name);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_middle::ty::print::RegionHighlightMode;
|
use rustc_middle::ty::print::RegionHighlightMode;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||||
use rustc_middle::ty::{self, RegionVid, Ty};
|
use rustc_middle::ty::{self, DefIdTree, RegionVid, Ty};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
@ -45,6 +45,8 @@ pub(crate) enum RegionNameSource {
|
|||||||
AnonRegionFromYieldTy(Span, String),
|
AnonRegionFromYieldTy(Span, String),
|
||||||
/// An anonymous region from an async fn.
|
/// An anonymous region from an async fn.
|
||||||
AnonRegionFromAsyncFn(Span),
|
AnonRegionFromAsyncFn(Span),
|
||||||
|
/// An anonymous region from an impl self type or trait
|
||||||
|
AnonRegionFromImplSignature(Span, &'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes what to highlight to explain to the user that we're giving an anonymous region a
|
/// Describes what to highlight to explain to the user that we're giving an anonymous region a
|
||||||
@ -75,7 +77,8 @@ impl RegionName {
|
|||||||
| RegionNameSource::AnonRegionFromUpvar(..)
|
| RegionNameSource::AnonRegionFromUpvar(..)
|
||||||
| RegionNameSource::AnonRegionFromOutput(..)
|
| RegionNameSource::AnonRegionFromOutput(..)
|
||||||
| RegionNameSource::AnonRegionFromYieldTy(..)
|
| RegionNameSource::AnonRegionFromYieldTy(..)
|
||||||
| RegionNameSource::AnonRegionFromAsyncFn(..) => false,
|
| RegionNameSource::AnonRegionFromAsyncFn(..)
|
||||||
|
| RegionNameSource::AnonRegionFromImplSignature(..) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +90,8 @@ impl RegionName {
|
|||||||
| RegionNameSource::SynthesizedFreeEnvRegion(span, _)
|
| RegionNameSource::SynthesizedFreeEnvRegion(span, _)
|
||||||
| RegionNameSource::AnonRegionFromUpvar(span, _)
|
| RegionNameSource::AnonRegionFromUpvar(span, _)
|
||||||
| RegionNameSource::AnonRegionFromYieldTy(span, _)
|
| RegionNameSource::AnonRegionFromYieldTy(span, _)
|
||||||
| RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span),
|
| RegionNameSource::AnonRegionFromAsyncFn(span)
|
||||||
|
| RegionNameSource::AnonRegionFromImplSignature(span, _) => Some(span),
|
||||||
RegionNameSource::AnonRegionFromArgument(ref highlight)
|
RegionNameSource::AnonRegionFromArgument(ref highlight)
|
||||||
| RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight {
|
| RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight {
|
||||||
RegionNameHighlight::MatchedHirTy(span)
|
RegionNameHighlight::MatchedHirTy(span)
|
||||||
@ -166,6 +170,12 @@ impl RegionName {
|
|||||||
RegionNameSource::AnonRegionFromYieldTy(span, type_name) => {
|
RegionNameSource::AnonRegionFromYieldTy(span, type_name) => {
|
||||||
diag.span_label(*span, format!("yield type is {type_name}"));
|
diag.span_label(*span, format!("yield type is {type_name}"));
|
||||||
}
|
}
|
||||||
|
RegionNameSource::AnonRegionFromImplSignature(span, location) => {
|
||||||
|
diag.span_label(
|
||||||
|
*span,
|
||||||
|
format!("lifetime `{self}` appears in the `impl`'s {location}"),
|
||||||
|
);
|
||||||
|
}
|
||||||
RegionNameSource::Static => {}
|
RegionNameSource::Static => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +250,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
|
.or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
|
||||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
|
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
|
||||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
|
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
|
||||||
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr));
|
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
|
||||||
|
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
|
||||||
|
|
||||||
if let Some(ref value) = value {
|
if let Some(ref value) = value {
|
||||||
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
|
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
|
||||||
@ -847,4 +858,43 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
|
source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn give_name_if_anonymous_region_appears_in_impl_signature(
|
||||||
|
&self,
|
||||||
|
fr: RegionVid,
|
||||||
|
) -> Option<RegionName> {
|
||||||
|
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
if region.has_name() {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let tcx = self.infcx.tcx;
|
||||||
|
let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?;
|
||||||
|
if tcx.parent(region.def_id) != body_parent_did
|
||||||
|
|| tcx.def_kind(body_parent_did) != DefKind::Impl
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut found = false;
|
||||||
|
tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| {
|
||||||
|
if *r == ty::ReEarlyBound(region) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
r
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(RegionName {
|
||||||
|
name: self.synthesize_region_name(),
|
||||||
|
source: RegionNameSource::AnonRegionFromImplSignature(
|
||||||
|
tcx.def_span(region.def_id),
|
||||||
|
// FIXME(compiler-errors): Does this ever actually show up
|
||||||
|
// anywhere other than the self type? I couldn't create an
|
||||||
|
// example of a `'_` in the impl's trait being referenceable.
|
||||||
|
if found { "self type" } else { "header" },
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
src/test/ui/nll/issue-98170.rs
Normal file
25
src/test/ui/nll/issue-98170.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
pub struct MyStruct<'a> {
|
||||||
|
field: &'a [u32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MyStruct<'_> {
|
||||||
|
pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
Self { field }
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
//~| ERROR lifetime may not live long enough
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Trait<'a> {
|
||||||
|
fn new(field: &'a [u32]) -> MyStruct<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Trait<'a> for MyStruct<'_> {
|
||||||
|
fn new(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
Self { field }
|
||||||
|
//~^ ERROR lifetime may not live long enough
|
||||||
|
//~| ERROR lifetime may not live long enough
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
44
src/test/ui/nll/issue-98170.stderr
Normal file
44
src/test/ui/nll/issue-98170.stderr
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98170.rs:7:9
|
||||||
|
|
|
||||||
|
LL | impl MyStruct<'_> {
|
||||||
|
| -- lifetime `'1` appears in the `impl`'s self type
|
||||||
|
LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
| -- lifetime `'a` defined here
|
||||||
|
LL | Self { field }
|
||||||
|
| ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98170.rs:7:16
|
||||||
|
|
|
||||||
|
LL | impl MyStruct<'_> {
|
||||||
|
| -- lifetime `'1` appears in the `impl`'s self type
|
||||||
|
LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
| -- lifetime `'a` defined here
|
||||||
|
LL | Self { field }
|
||||||
|
| ^^^^^ this usage requires that `'a` must outlive `'1`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98170.rs:19:9
|
||||||
|
|
|
||||||
|
LL | impl<'a> Trait<'a> for MyStruct<'_> {
|
||||||
|
| -- -- lifetime `'1` appears in the `impl`'s self type
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | fn new(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
LL | Self { field }
|
||||||
|
| ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-98170.rs:19:16
|
||||||
|
|
|
||||||
|
LL | impl<'a> Trait<'a> for MyStruct<'_> {
|
||||||
|
| -- -- lifetime `'1` appears in the `impl`'s self type
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
LL | fn new(field: &'a [u32]) -> MyStruct<'a> {
|
||||||
|
LL | Self { field }
|
||||||
|
| ^^^^^ this usage requires that `'a` must outlive `'1`
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user