Skip to content

Commit cececca

Browse files
committed
Get spans for a couple more region types, add some optimizations, and extend test
1 parent 00e314d commit cececca

File tree

4 files changed

+126
-37
lines changed

4 files changed

+126
-37
lines changed

compiler/rustc_hir_typeck/src/generator_interior/mod.rs

+49-33
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ use rustc_hir::intravisit::{self, Visitor};
1515
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
1616
use rustc_infer::infer::RegionVariableOrigin;
1717
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
18+
use rustc_middle::ty::fold::FnMutDelegate;
1819
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
1920
use rustc_span::symbol::sym;
2021
use rustc_span::Span;
22+
use smallvec::{smallvec, SmallVec};
2123

2224
mod drop_ranges;
2325

@@ -226,32 +228,37 @@ pub fn resolve_interior<'a, 'tcx>(
226228
// typeck had previously found constraints that would cause them to be related.
227229

228230
let mut counter = 0;
231+
let mut mk_bound_region = |span| {
232+
let kind = ty::BrAnon(counter, span);
233+
let var = ty::BoundVar::from_u32(counter);
234+
counter += 1;
235+
ty::BoundRegion { var, kind }
236+
};
229237
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
230238
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
231239
let br = match region.kind() {
232240
ty::ReVar(vid) => {
233241
let origin = fcx.region_var_origin(vid);
234242
match origin {
235243
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
236-
let kind = ty::BrAnon(counter, Some(span));
237-
let var = ty::BoundVar::from_u32(counter);
238-
counter += 1;
239-
ty::BoundRegion { var, kind }
240-
}
241-
_ => {
242-
let kind = ty::BrAnon(counter, None);
243-
let var = ty::BoundVar::from_u32(counter);
244-
counter += 1;
245-
ty::BoundRegion { var, kind }
244+
mk_bound_region(Some(span))
246245
}
246+
_ => mk_bound_region(None),
247247
}
248248
}
249-
_ => {
250-
let kind = ty::BrAnon(counter, None);
251-
let var = ty::BoundVar::from_u32(counter);
252-
counter += 1;
253-
ty::BoundRegion { var, kind }
249+
// FIXME: these should use `BrNamed`
250+
ty::ReEarlyBound(region) => {
251+
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
254252
}
253+
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
254+
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
255+
ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
256+
ty::BoundRegionKind::BrNamed(def_id, _) => {
257+
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
258+
}
259+
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
260+
},
261+
_ => mk_bound_region(None),
255262
};
256263
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
257264
r
@@ -265,25 +272,34 @@ pub fn resolve_interior<'a, 'tcx>(
265272
})
266273
.collect();
267274

268-
let mut bound_vars: Vec<BoundVariableKind> = vec![];
275+
let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
269276
let mut counter = 0;
270-
let type_causes = fcx.tcx.fold_regions(type_causes, |region, current_depth| {
271-
let br = match region.kind() {
272-
ty::ReLateBound(_, br) => {
273-
let kind = match br.kind {
274-
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
275-
_ => br.kind,
276-
};
277-
let var = ty::BoundVar::from_usize(bound_vars.len());
278-
bound_vars.push(ty::BoundVariableKind::Region(kind));
279-
counter += 1;
280-
ty::BoundRegion { var, kind }
281-
}
282-
_ => bug!("All regions should have been replaced by ReLateBound"),
283-
};
284-
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
285-
r
286-
});
277+
// Optimization: If there is only one captured type, then we don't actually
278+
// need to fold and reindex (since the first type doesn't change).
279+
let type_causes = if captured_tys.len() > 0 {
280+
// Optimization: Use `replace_escaping_bound_vars_uncached` instead of
281+
// `fold_regions`, since we only have late bound regions, and it skips
282+
// types without bound regions.
283+
fcx.tcx.replace_escaping_bound_vars_uncached(
284+
type_causes,
285+
FnMutDelegate {
286+
regions: &mut |br| {
287+
let kind = match br.kind {
288+
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
289+
_ => br.kind,
290+
};
291+
let var = ty::BoundVar::from_usize(bound_vars.len());
292+
bound_vars.push(ty::BoundVariableKind::Region(kind));
293+
counter += 1;
294+
fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
295+
},
296+
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
297+
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
298+
},
299+
)
300+
} else {
301+
type_causes
302+
};
287303

288304
// Extract type components to build the witness type.
289305
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
6161
);
6262
}
6363
(Some(sub_span), Some(sup_span), _, _) => {
64-
err.span_note(sub_span, format!("the lifetime defined here, ..."));
64+
err.span_note(sub_span, format!("the lifetime defined here..."));
6565
err.span_note(
6666
sup_span,
6767
format!("...must outlive the lifetime defined here"),

src/test/ui/generic-associated-types/bugs/issue-100013.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,29 @@ pub trait FutureIterator {
1111
's: 'cx;
1212
}
1313

14-
fn call_2<I: FutureIterator>() -> impl Send {
14+
fn call<I: FutureIterator>() -> impl Send {
1515
async { // a generator checked for autotrait impl `Send`
1616
//~^ lifetime bound not satisfied
1717
let x = None::<I::Future<'_, '_>>; // a type referencing GAT
1818
async {}.await; // a yield point
1919
}
2020
}
2121

22+
fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
23+
async { // a generator checked for autotrait impl `Send`
24+
//~^ lifetime bound not satisfied
25+
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
26+
//~^ lifetime may not live long enough
27+
async {}.await; // a yield point
28+
}
29+
}
30+
31+
fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
32+
async { // a generator checked for autotrait impl `Send`
33+
//~^ lifetime bound not satisfied
34+
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
35+
async {}.await; // a yield point
36+
}
37+
}
38+
2239
fn main() {}

src/test/ui/generic-associated-types/bugs/issue-100013.stderr

+58-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | | async {}.await; // a yield point
88
LL | | }
99
| |_____^
1010
|
11-
note: the lifetime defined here, ...
11+
note: the lifetime defined here...
1212
--> $DIR/issue-100013.rs:17:38
1313
|
1414
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
@@ -19,5 +19,61 @@ note: ...must outlive the lifetime defined here
1919
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
2020
| ^^
2121

22-
error: aborting due to previous error
22+
error: lifetime bound not satisfied
23+
--> $DIR/issue-100013.rs:23:5
24+
|
25+
LL | / async { // a generator checked for autotrait impl `Send`
26+
LL | |
27+
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
28+
LL | |
29+
LL | | async {}.await; // a yield point
30+
LL | | }
31+
| |_____^
32+
|
33+
note: the lifetime defined here...
34+
--> $DIR/issue-100013.rs:22:14
35+
|
36+
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
37+
| ^^
38+
note: ...must outlive the lifetime defined here
39+
--> $DIR/issue-100013.rs:22:10
40+
|
41+
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
42+
| ^^
43+
44+
error: lifetime may not live long enough
45+
--> $DIR/issue-100013.rs:25:17
46+
|
47+
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
48+
| -- -- lifetime `'b` defined here
49+
| |
50+
| lifetime `'a` defined here
51+
...
52+
LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
53+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
54+
|
55+
= help: consider adding the following bound: `'a: 'b`
56+
57+
error: lifetime bound not satisfied
58+
--> $DIR/issue-100013.rs:32:5
59+
|
60+
LL | / async { // a generator checked for autotrait impl `Send`
61+
LL | |
62+
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
63+
LL | | async {}.await; // a yield point
64+
LL | | }
65+
| |_____^
66+
|
67+
note: the lifetime defined here...
68+
--> $DIR/issue-100013.rs:31:18
69+
|
70+
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
71+
| ^^
72+
note: ...must outlive the lifetime defined here
73+
--> $DIR/issue-100013.rs:31:10
74+
|
75+
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
76+
| ^^
77+
78+
error: aborting due to 4 previous errors
2379

0 commit comments

Comments
 (0)