Make things actually work

This commit is contained in:
Michael Goulet 2022-12-14 23:53:05 +00:00
parent eff2cb7760
commit 52f82354dc
5 changed files with 151 additions and 93 deletions

View file

@ -2598,6 +2598,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path<'_>,
hir_id: hir::HirId,
permit_variants: bool,
) -> Ty<'tcx> {
let tcx = self.tcx();
@ -2661,11 +2662,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
});
let def_id = def_id.expect_local();
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
match tcx.named_bound_var(hir_id) {
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
let name =
tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
let br = ty::BoundTy {
var: ty::BoundVar::from_u32(index),
kind: ty::BoundTyKind::Param(def_id, name),
};
tcx.mk_ty(ty::Bound(debruijn, br))
}
Some(rbv::ResolvedArg::EarlyBound(_)) => {
let def_id = def_id.expect_local();
let item_def_id = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id))
}
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
}
}
Res::SelfTyParam { .. } => {
// `Self` in trait or type alias.
@ -2888,7 +2903,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
self.res_to_ty(opt_self_ty, path, false)
self.res_to_ty(opt_self_ty, path, ast_ty.hir_id, false)
}
&hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);

View file

@ -35,14 +35,14 @@ trait RegionExt {
impl RegionExt for ResolvedArg {
fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
debug!("Region::early: def_id={:?}", param.def_id);
debug!("ResolvedArg::early: def_id={:?}", param.def_id);
(param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id()))
}
fn late(idx: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) {
let depth = ty::INNERMOST;
debug!(
"Region::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
"ResolvedArg::late: idx={:?}, param={:?} depth={:?} def_id={:?}",
idx, param, depth, param.def_id,
);
(param.def_id, ResolvedArg::LateBound(depth, idx, param.def_id.to_def_id()))
@ -278,13 +278,25 @@ fn resolve_bound_vars(tcx: TyCtxt<'_>, local_def_id: hir::OwnerId) -> ResolveBou
rl
}
fn late_region_as_bound_region(tcx: TyCtxt<'_>, region: &ResolvedArg) -> ty::BoundVariableKind {
match region {
fn late_arg_as_bound_arg<'tcx>(
tcx: TyCtxt<'tcx>,
arg: &ResolvedArg,
param: &GenericParam<'tcx>,
) -> ty::BoundVariableKind {
match arg {
ResolvedArg::LateBound(_, _, def_id) => {
let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
match param.kind {
GenericParamKind::Lifetime { .. } => {
ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name))
}
GenericParamKind::Type { .. } => {
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(*def_id, name))
}
GenericParamKind::Const { .. } => ty::BoundVariableKind::Const,
}
}
_ => bug!("{:?} is not a late argument", region),
_ => bug!("{:?} is not a late argument", arg),
}
}
@ -391,11 +403,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_region_as_bound_region(self.tcx, &pair.1);
let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
@ -481,7 +492,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
}
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_),
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics,
..
}) => {
@ -490,26 +501,24 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let mut bound_vars = FxIndexMap::default();
debug!(?generics.params);
for param in generics.params {
match param.kind {
GenericParamKind::Lifetime { .. } => {
let (def_id, reg) = ResolvedArg::early(&param);
bound_vars.insert(def_id, reg);
}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
}
let (def_id, reg) = ResolvedArg::early(&param);
bound_vars.insert(def_id, reg);
}
let scope = Scope::Binder {
hir_id: item.hir_id(),
bound_vars,
s: self.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
let scope = Scope::Root { opt_parent_item: Some(parent) };
self.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| intravisit::walk_item(this, item))
});
let scope = Scope::Binder {
hir_id: item.hir_id(),
bound_vars,
s: this.scope,
scope_type: BinderScopeType::Normal,
where_bound_origin: None,
};
this.with(scope, |this| {
let scope = Scope::TraitRefBoundary { s: this.scope };
this.with(scope, |this| intravisit::walk_item(this, item))
});
})
}
hir::ItemKind::TyAlias(_, generics)
| hir::ItemKind::Enum(_, generics)
@ -519,14 +528,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
| hir::ItemKind::TraitAlias(generics, ..)
| hir::ItemKind::Impl(&hir::Impl { generics, .. }) => {
// These kinds of items have only early-bound lifetime parameters.
let bound_vars = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(ResolvedArg::early(param)),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
@ -568,11 +570,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c
.generic_params
.iter()
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_region_as_bound_region(self.tcx, &pair.1);
let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
(pair, r)
})
.unzip();
@ -725,14 +726,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
Type(bounds, ty) => {
let generics = &trait_item.generics;
let bound_vars = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(ResolvedArg::early(param)),
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
let bound_vars = generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
@ -771,14 +765,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}),
Type(ty) => {
let generics = &impl_item.generics;
let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => Some(ResolvedArg::early(param)),
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
})
.collect();
let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
generics.params.iter().map(ResolvedArg::early).collect();
self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: impl_item.hir_id(),
@ -819,13 +807,16 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
}
}
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
fn visit_path(&mut self, path: &hir::Path<'tcx>, hir_id: hir::HirId) {
for (i, segment) in path.segments.iter().enumerate() {
let depth = path.segments.len() - i - 1;
if let Some(args) = segment.args {
self.visit_segment_args(path.res, depth, args);
}
}
if let Res::Def(DefKind::TyParam | DefKind::ConstParam, param_def_id) = path.res {
self.resolve_type_ref(param_def_id.expect_local(), hir_id);
}
}
fn visit_fn(
@ -874,24 +865,17 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
origin,
..
}) => {
let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> =
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
bound_generic_params
.iter()
.filter(|param| {
matches!(param.kind, GenericParamKind::Lifetime { .. })
})
.enumerate()
.map(|(late_bound_idx, param)| {
ResolvedArg::late(late_bound_idx as u32, param)
})
.collect();
let binders: Vec<_> =
bound_vars
.iter()
.map(|(_, region)| {
late_region_as_bound_region(this.tcx, region)
})
.collect();
.iter()
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
(pair, r)
})
.unzip();
this.record_late_bound_vars(hir_id, binders.clone());
// Even if there are no lifetimes defined here, we still wrap it in a binder
// scope. If there happens to be a nested poly trait ref (an error), that
@ -989,14 +973,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
let initial_bound_vars = binders.len() as u32;
let mut bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = FxIndexMap::default();
let binders_iter = trait_ref
.bound_generic_params
.iter()
.filter(|param| matches!(param.kind, GenericParamKind::Lifetime { .. }))
.enumerate()
.map(|(late_bound_idx, param)| {
let binders_iter =
trait_ref.bound_generic_params.iter().enumerate().map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(initial_bound_vars + late_bound_idx as u32, param);
let r = late_region_as_bound_region(self.tcx, &pair.1);
let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
bound_vars.insert(pair.0, pair.1);
r
});
@ -1121,17 +1101,19 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let bound_vars: FxIndexMap<LocalDefId, ResolvedArg> = generics
.params
.iter()
.filter_map(|param| match param.kind {
.map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
if self.tcx.is_late_bound(param.hir_id) {
let late_bound_idx = named_late_bound_vars;
named_late_bound_vars += 1;
Some(ResolvedArg::late(late_bound_idx, param))
ResolvedArg::late(late_bound_idx, param)
} else {
Some(ResolvedArg::early(param))
ResolvedArg::early(param)
}
}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
ResolvedArg::early(param)
}
})
.collect();
@ -1145,7 +1127,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
.enumerate()
.map(|(late_bound_idx, param)| {
let pair = ResolvedArg::late(late_bound_idx as u32, param);
late_region_as_bound_region(self.tcx, &pair.1)
late_arg_as_bound_arg(self.tcx, &pair.1, param)
})
.collect();
self.record_late_bound_vars(hir_id, binders);
@ -1182,7 +1164,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Root { opt_parent_item } => {
if let Some(parent_item) = opt_parent_item
&& let parent_generics = self.tcx.generics_of(parent_item)
&& parent_generics.param_def_id_to_index.contains_key(&region_def_id.to_def_id())
&& parent_generics.param_def_id_to_index(self.tcx, region_def_id.to_def_id()).is_some()
{
break Some(ResolvedArg::EarlyBound(region_def_id.to_def_id()));
}
@ -1334,6 +1316,61 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
);
}
fn resolve_type_ref(&mut self, param_def_id: LocalDefId, hir_id: hir::HirId) {
// Walk up the scope chain, tracking the number of fn scopes
// that we pass through, until we find a lifetime with the
// given name or we run out of scopes.
// search.
let mut late_depth = 0;
let mut scope = self.scope;
let result = loop {
match *scope {
Scope::Body { s, .. } => {
scope = s;
}
Scope::Root { opt_parent_item } => {
if let Some(parent_item) = opt_parent_item
&& let parent_generics = self.tcx.generics_of(parent_item)
&& parent_generics.param_def_id_to_index(self.tcx, param_def_id.to_def_id()).is_some()
{
break Some(ResolvedArg::EarlyBound(param_def_id.to_def_id()));
}
break None;
}
Scope::Binder { ref bound_vars, scope_type, s, .. } => {
if let Some(&def) = bound_vars.get(&param_def_id) {
break Some(def.shifted(late_depth));
}
match scope_type {
BinderScopeType::Normal => late_depth += 1,
BinderScopeType::Concatenating => {}
}
scope = s;
}
Scope::Elision { s, .. }
| Scope::ObjectLifetimeDefault { s, .. }
| Scope::Supertrait { s, .. }
| Scope::TraitRefBoundary { s, .. } => {
scope = s;
}
}
};
if let Some(def) = result {
self.map.defs.insert(hir_id, def);
return;
}
span_bug!(
self.tcx.hir().span(hir_id),
"could not resolve {param_def_id:?}, scopes: {:#?}",
self.scope
);
}
#[instrument(level = "debug", skip(self))]
fn visit_segment_args(
&mut self,