Don't ICE on regions from anonymous_lifetime_in_impl_trait

This commit is contained in:
Michael Goulet 2022-10-22 02:48:36 +00:00
parent 0940040c04
commit e025306fa0
3 changed files with 120 additions and 8 deletions

View File

@ -251,7 +251,8 @@ pub(crate) fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
.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_yield_ty(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
if let Some(ref value) = value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@ -869,13 +870,8 @@ fn give_name_if_anonymous_region_appears_in_impl_signature(
return None;
}
let mut found = false;
tcx.fold_regions(tcx.type_of(region_parent), |r: ty::Region<'tcx>, _| {
if *r == ty::ReEarlyBound(region) {
found = true;
}
r
});
let found = tcx
.any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
Some(RegionName {
name: self.synthesize_region_name(),
@ -888,4 +884,92 @@ fn give_name_if_anonymous_region_appears_in_impl_signature(
),
})
}
fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
&self,
fr: RegionVid,
) -> Option<RegionName> {
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
return None;
};
if region.has_name() {
return None;
};
let predicates = self
.infcx
.tcx
.predicates_of(self.body.source.def_id())
.instantiate_identity(self.infcx.tcx)
.predicates;
if let Some(upvar_index) = self
.regioncx
.universal_regions()
.defining_ty
.upvar_tys()
.position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
{
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
self.infcx.tcx,
&self.upvars,
upvar_index,
);
let region_name = self.synthesize_region_name();
Some(RegionName {
name: region_name,
source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
})
} else if let Some(arg_index) = self
.regioncx
.universal_regions()
.unnormalized_input_tys
.iter()
.position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
{
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
self.body,
&self.local_names,
arg_index,
);
let region_name = self.synthesize_region_name();
Some(RegionName {
name: region_name,
source: RegionNameSource::AnonRegionFromArgument(
RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
),
})
} else {
None
}
}
fn any_param_predicate_mentions(
&self,
predicates: &[ty::Predicate<'tcx>],
ty: Ty<'tcx>,
region: ty::EarlyBoundRegion,
) -> bool {
let tcx = self.infcx.tcx;
ty.walk().any(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
&& let ty::Param(_) = ty.kind()
{
predicates.iter().any(|pred| {
match pred.kind().skip_binder() {
ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
tcx.any_free_region_meets(pred, |r| {
*r == ty::ReEarlyBound(region)
})
})
} else {
false
}
})
}
}

View File

@ -0,0 +1,12 @@
#![feature(anonymous_lifetime_in_impl_trait)]
trait Foo<T> {
fn bar(self, baz: T);
}
fn qux(foo: impl Foo<&str>) {
|baz: &str| foo.bar(baz);
//~^ ERROR borrowed data escapes outside of closure
}
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0521]: borrowed data escapes outside of closure
--> $DIR/anonymous-region-in-apit.rs:8:17
|
LL | fn qux(foo: impl Foo<&str>) {
| --- lifetime `'2` appears in the type of `foo`
LL | |baz: &str| foo.bar(baz);
| --- - ^^^^^^^^^^^^
| | | |
| | | `baz` escapes the closure body here
| | | argument requires that `'1` must outlive `'2`
| | let's call the lifetime of this reference `'1`
| `baz` is a reference that is only valid in the closure body
error: aborting due to previous error
For more information about this error, try `rustc --explain E0521`.