Skip to content

Commit 6383540

Browse files
author
Yuki Okushi
authored
Rollup merge of #103382 - compiler-errors:anon-apit-lt-region-ice, r=cjgillot
Don't ICE when reporting borrowck errors involving regions from `anonymous_lifetime_in_impl_trait` The issue here is that when we have: ``` trait Trait<'a> { .. } fn foo(arg: impl Trait) { .. } ``` The anonymous lifetime `'_` that we generate for `arg: impl Trait` doesn't end up in the argument type (which is a param) but in a where-clause of the function, in a predicate whose self type is that param ty. Fixes #101660 r? ``@cjgillot``
2 parents e47d222 + e025306 commit 6383540

File tree

3 files changed

+120
-8
lines changed

3 files changed

+120
-8
lines changed

compiler/rustc_borrowck/src/diagnostics/region_name.rs

+92-8
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
251251
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
252252
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
253253
.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));
254+
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
255+
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
255256

256257
if let Some(ref value) = value {
257258
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@@ -869,13 +870,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
869870
return None;
870871
}
871872

872-
let mut found = false;
873-
tcx.fold_regions(tcx.type_of(region_parent), |r: ty::Region<'tcx>, _| {
874-
if *r == ty::ReEarlyBound(region) {
875-
found = true;
876-
}
877-
r
878-
});
873+
let found = tcx
874+
.any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
879875

880876
Some(RegionName {
881877
name: self.synthesize_region_name(),
@@ -888,4 +884,92 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
888884
),
889885
})
890886
}
887+
888+
fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
889+
&self,
890+
fr: RegionVid,
891+
) -> Option<RegionName> {
892+
let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
893+
return None;
894+
};
895+
if region.has_name() {
896+
return None;
897+
};
898+
899+
let predicates = self
900+
.infcx
901+
.tcx
902+
.predicates_of(self.body.source.def_id())
903+
.instantiate_identity(self.infcx.tcx)
904+
.predicates;
905+
906+
if let Some(upvar_index) = self
907+
.regioncx
908+
.universal_regions()
909+
.defining_ty
910+
.upvar_tys()
911+
.position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
912+
{
913+
let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
914+
self.infcx.tcx,
915+
&self.upvars,
916+
upvar_index,
917+
);
918+
let region_name = self.synthesize_region_name();
919+
920+
Some(RegionName {
921+
name: region_name,
922+
source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
923+
})
924+
} else if let Some(arg_index) = self
925+
.regioncx
926+
.universal_regions()
927+
.unnormalized_input_tys
928+
.iter()
929+
.position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
930+
{
931+
let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
932+
self.body,
933+
&self.local_names,
934+
arg_index,
935+
);
936+
let region_name = self.synthesize_region_name();
937+
938+
Some(RegionName {
939+
name: region_name,
940+
source: RegionNameSource::AnonRegionFromArgument(
941+
RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
942+
),
943+
})
944+
} else {
945+
None
946+
}
947+
}
948+
949+
fn any_param_predicate_mentions(
950+
&self,
951+
predicates: &[ty::Predicate<'tcx>],
952+
ty: Ty<'tcx>,
953+
region: ty::EarlyBoundRegion,
954+
) -> bool {
955+
let tcx = self.infcx.tcx;
956+
ty.walk().any(|arg| {
957+
if let ty::GenericArgKind::Type(ty) = arg.unpack()
958+
&& let ty::Param(_) = ty.kind()
959+
{
960+
predicates.iter().any(|pred| {
961+
match pred.kind().skip_binder() {
962+
ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
963+
ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
964+
_ => return false,
965+
}
966+
tcx.any_free_region_meets(pred, |r| {
967+
*r == ty::ReEarlyBound(region)
968+
})
969+
})
970+
} else {
971+
false
972+
}
973+
})
974+
}
891975
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(anonymous_lifetime_in_impl_trait)]
2+
3+
trait Foo<T> {
4+
fn bar(self, baz: T);
5+
}
6+
7+
fn qux(foo: impl Foo<&str>) {
8+
|baz: &str| foo.bar(baz);
9+
//~^ ERROR borrowed data escapes outside of closure
10+
}
11+
12+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0521]: borrowed data escapes outside of closure
2+
--> $DIR/anonymous-region-in-apit.rs:8:17
3+
|
4+
LL | fn qux(foo: impl Foo<&str>) {
5+
| --- lifetime `'2` appears in the type of `foo`
6+
LL | |baz: &str| foo.bar(baz);
7+
| --- - ^^^^^^^^^^^^
8+
| | | |
9+
| | | `baz` escapes the closure body here
10+
| | | argument requires that `'1` must outlive `'2`
11+
| | let's call the lifetime of this reference `'1`
12+
| `baz` is a reference that is only valid in the closure body
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0521`.

0 commit comments

Comments
 (0)