Get spans for a couple more region types, add some optimizations, and extend test
This commit is contained in:
parent
00e314d5ed
commit
cececca7c7
4 changed files with 126 additions and 37 deletions
|
@ -15,9 +15,11 @@ use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
|
||||||
use rustc_infer::infer::RegionVariableOrigin;
|
use rustc_infer::infer::RegionVariableOrigin;
|
||||||
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
use rustc_middle::middle::region::{self, Scope, ScopeData, YieldData};
|
||||||
|
use rustc_middle::ty::fold::FnMutDelegate;
|
||||||
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
use rustc_middle::ty::{self, BoundVariableKind, RvalueScopes, Ty, TyCtxt, TypeVisitable};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use smallvec::{smallvec, SmallVec};
|
||||||
|
|
||||||
mod drop_ranges;
|
mod drop_ranges;
|
||||||
|
|
||||||
|
@ -226,6 +228,12 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||||
// typeck had previously found constraints that would cause them to be related.
|
// typeck had previously found constraints that would cause them to be related.
|
||||||
|
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
|
let mut mk_bound_region = |span| {
|
||||||
|
let kind = ty::BrAnon(counter, span);
|
||||||
|
let var = ty::BoundVar::from_u32(counter);
|
||||||
|
counter += 1;
|
||||||
|
ty::BoundRegion { var, kind }
|
||||||
|
};
|
||||||
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
|
||||||
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
|
let ty = fcx.tcx.fold_regions(ty, |region, current_depth| {
|
||||||
let br = match region.kind() {
|
let br = match region.kind() {
|
||||||
|
@ -233,25 +241,24 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||||
let origin = fcx.region_var_origin(vid);
|
let origin = fcx.region_var_origin(vid);
|
||||||
match origin {
|
match origin {
|
||||||
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
|
RegionVariableOrigin::EarlyBoundRegion(span, _) => {
|
||||||
let kind = ty::BrAnon(counter, Some(span));
|
mk_bound_region(Some(span))
|
||||||
let var = ty::BoundVar::from_u32(counter);
|
|
||||||
counter += 1;
|
|
||||||
ty::BoundRegion { var, kind }
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let kind = ty::BrAnon(counter, None);
|
|
||||||
let var = ty::BoundVar::from_u32(counter);
|
|
||||||
counter += 1;
|
|
||||||
ty::BoundRegion { var, kind }
|
|
||||||
}
|
}
|
||||||
|
_ => mk_bound_region(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
// FIXME: these should use `BrNamed`
|
||||||
let kind = ty::BrAnon(counter, None);
|
ty::ReEarlyBound(region) => {
|
||||||
let var = ty::BoundVar::from_u32(counter);
|
mk_bound_region(Some(fcx.tcx.def_span(region.def_id)))
|
||||||
counter += 1;
|
|
||||||
ty::BoundRegion { var, kind }
|
|
||||||
}
|
}
|
||||||
|
ty::ReLateBound(_, ty::BoundRegion { kind, .. })
|
||||||
|
| ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
|
||||||
|
ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
|
||||||
|
ty::BoundRegionKind::BrNamed(def_id, _) => {
|
||||||
|
mk_bound_region(Some(fcx.tcx.def_span(def_id)))
|
||||||
|
}
|
||||||
|
ty::BoundRegionKind::BrEnv => mk_bound_region(None),
|
||||||
|
},
|
||||||
|
_ => mk_bound_region(None),
|
||||||
};
|
};
|
||||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
||||||
r
|
r
|
||||||
|
@ -265,25 +272,34 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut bound_vars: Vec<BoundVariableKind> = vec![];
|
let mut bound_vars: SmallVec<[BoundVariableKind; 4]> = smallvec![];
|
||||||
let mut counter = 0;
|
let mut counter = 0;
|
||||||
let type_causes = fcx.tcx.fold_regions(type_causes, |region, current_depth| {
|
// Optimization: If there is only one captured type, then we don't actually
|
||||||
let br = match region.kind() {
|
// need to fold and reindex (since the first type doesn't change).
|
||||||
ty::ReLateBound(_, br) => {
|
let type_causes = if captured_tys.len() > 0 {
|
||||||
let kind = match br.kind {
|
// Optimization: Use `replace_escaping_bound_vars_uncached` instead of
|
||||||
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
|
// `fold_regions`, since we only have late bound regions, and it skips
|
||||||
_ => br.kind,
|
// types without bound regions.
|
||||||
};
|
fcx.tcx.replace_escaping_bound_vars_uncached(
|
||||||
let var = ty::BoundVar::from_usize(bound_vars.len());
|
type_causes,
|
||||||
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
FnMutDelegate {
|
||||||
counter += 1;
|
regions: &mut |br| {
|
||||||
ty::BoundRegion { var, kind }
|
let kind = match br.kind {
|
||||||
}
|
ty::BrAnon(_, span) => ty::BrAnon(counter, span),
|
||||||
_ => bug!("All regions should have been replaced by ReLateBound"),
|
_ => br.kind,
|
||||||
};
|
};
|
||||||
let r = fcx.tcx.mk_region(ty::ReLateBound(current_depth, br));
|
let var = ty::BoundVar::from_usize(bound_vars.len());
|
||||||
r
|
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
||||||
});
|
counter += 1;
|
||||||
|
fcx.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var, kind }))
|
||||||
|
},
|
||||||
|
types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"),
|
||||||
|
consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
type_causes
|
||||||
|
};
|
||||||
|
|
||||||
// Extract type components to build the witness type.
|
// Extract type components to build the witness type.
|
||||||
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
let type_list = fcx.tcx.mk_type_list(type_causes.iter().map(|cause| cause.ty));
|
||||||
|
|
|
@ -61,7 +61,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(Some(sub_span), Some(sup_span), _, _) => {
|
(Some(sub_span), Some(sup_span), _, _) => {
|
||||||
err.span_note(sub_span, format!("the lifetime defined here, ..."));
|
err.span_note(sub_span, format!("the lifetime defined here..."));
|
||||||
err.span_note(
|
err.span_note(
|
||||||
sup_span,
|
sup_span,
|
||||||
format!("...must outlive the lifetime defined here"),
|
format!("...must outlive the lifetime defined here"),
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub trait FutureIterator {
|
||||||
's: 'cx;
|
's: 'cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_2<I: FutureIterator>() -> impl Send {
|
fn call<I: FutureIterator>() -> impl Send {
|
||||||
async { // a generator checked for autotrait impl `Send`
|
async { // a generator checked for autotrait impl `Send`
|
||||||
//~^ lifetime bound not satisfied
|
//~^ lifetime bound not satisfied
|
||||||
let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||||
|
@ -19,4 +19,21 @@ fn call_2<I: FutureIterator>() -> impl Send {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
async { // a generator checked for autotrait impl `Send`
|
||||||
|
//~^ lifetime bound not satisfied
|
||||||
|
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
//~^ lifetime may not live long enough
|
||||||
|
async {}.await; // a yield point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
async { // a generator checked for autotrait impl `Send`
|
||||||
|
//~^ lifetime bound not satisfied
|
||||||
|
let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
async {}.await; // a yield point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -8,7 +8,7 @@ LL | | async {}.await; // a yield point
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
note: the lifetime defined here, ...
|
note: the lifetime defined here...
|
||||||
--> $DIR/issue-100013.rs:17:38
|
--> $DIR/issue-100013.rs:17:38
|
||||||
|
|
|
|
||||||
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||||
|
@ -19,5 +19,61 @@ note: ...must outlive the lifetime defined here
|
||||||
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
LL | let x = None::<I::Future<'_, '_>>; // a type referencing GAT
|
||||||
| ^^
|
| ^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: lifetime bound not satisfied
|
||||||
|
--> $DIR/issue-100013.rs:23:5
|
||||||
|
|
|
||||||
|
LL | / async { // a generator checked for autotrait impl `Send`
|
||||||
|
LL | |
|
||||||
|
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
LL | |
|
||||||
|
LL | | async {}.await; // a yield point
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
note: the lifetime defined here...
|
||||||
|
--> $DIR/issue-100013.rs:22:14
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
note: ...must outlive the lifetime defined here
|
||||||
|
--> $DIR/issue-100013.rs:22:10
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: lifetime may not live long enough
|
||||||
|
--> $DIR/issue-100013.rs:25:17
|
||||||
|
|
|
||||||
|
LL | fn call2<'a, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| -- -- lifetime `'b` defined here
|
||||||
|
| |
|
||||||
|
| lifetime `'a` defined here
|
||||||
|
...
|
||||||
|
LL | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'b`
|
||||||
|
|
|
||||||
|
= help: consider adding the following bound: `'a: 'b`
|
||||||
|
|
||||||
|
error: lifetime bound not satisfied
|
||||||
|
--> $DIR/issue-100013.rs:32:5
|
||||||
|
|
|
||||||
|
LL | / async { // a generator checked for autotrait impl `Send`
|
||||||
|
LL | |
|
||||||
|
LL | | let x = None::<I::Future<'a, 'b>>; // a type referencing GAT
|
||||||
|
LL | | async {}.await; // a yield point
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
|
|
||||||
|
note: the lifetime defined here...
|
||||||
|
--> $DIR/issue-100013.rs:31:18
|
||||||
|
|
|
||||||
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
note: ...must outlive the lifetime defined here
|
||||||
|
--> $DIR/issue-100013.rs:31:10
|
||||||
|
|
|
||||||
|
LL | fn call3<'a: 'b, 'b, I: FutureIterator>() -> impl Send {
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue