1
Fork 0

Create a specific ObjectLifetimeDefault enum.

This commit is contained in:
Camille GILLOT 2022-05-24 12:51:59 +02:00
parent 39bc74e8b8
commit 236ccce79e
6 changed files with 58 additions and 83 deletions

View file

@ -499,7 +499,9 @@ impl<'hir> Map<'hir> {
let def_kind = self.tcx.def_kind(def_id); let def_kind = self.tcx.def_kind(def_id);
match def_kind { match def_kind {
DefKind::Trait | DefKind::TraitAlias => def_id, DefKind::Trait | DefKind::TraitAlias => def_id,
DefKind::TyParam | DefKind::ConstParam => self.tcx.local_parent(def_id), DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
self.tcx.local_parent(def_id)
}
_ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind), _ => bug!("ty_param_owner: {:?} is a {:?} not a type parameter", def_id, def_kind),
} }
} }
@ -508,7 +510,9 @@ impl<'hir> Map<'hir> {
let def_kind = self.tcx.def_kind(def_id); let def_kind = self.tcx.def_kind(def_id);
match def_kind { match def_kind {
DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper, DefKind::Trait | DefKind::TraitAlias => kw::SelfUpper,
DefKind::TyParam | DefKind::ConstParam => self.tcx.item_name(def_id.to_def_id()), DefKind::LifetimeParam | DefKind::TyParam | DefKind::ConstParam => {
self.tcx.item_name(def_id.to_def_id())
}
_ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind), _ => bug!("ty_param_name: {:?} is a {:?} not a type parameter", def_id, def_kind),
} }
} }

View file

@ -35,7 +35,13 @@ impl<T: PartialEq> Set1<T> {
} }
} }
pub type ObjectLifetimeDefault = Set1<Region>; #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)]
pub enum ObjectLifetimeDefault {
Empty,
Static,
Ambiguous,
Param(DefId),
}
/// Maps the id of each lifetime reference to the lifetime decl /// Maps the id of each lifetime reference to the lifetime decl
/// that it corresponds to. /// that it corresponds to.

View file

@ -1579,7 +1579,7 @@ rustc_queries! {
/// for each parameter if a trait object were to be passed for that parameter. /// for each parameter if a trait object were to be passed for that parameter.
/// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`. /// For example, for `struct Foo<'a, T, U>`, this would be `['static, 'static]`.
/// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`. /// For `struct Foo<'a, T: 'a, U>`, this would instead be `['a, 'static]`.
query object_lifetime_defaults(_: DefId) -> Option<&'tcx [ObjectLifetimeDefault]> { query object_lifetime_defaults(_: LocalDefId) -> Option<&'tcx [ObjectLifetimeDefault]> {
desc { "looking up lifetime defaults for a region on an item" } desc { "looking up lifetime defaults for a region on an item" }
} }
query late_bound_vars_map(_: LocalDefId) query late_bound_vars_map(_: LocalDefId)

View file

@ -290,24 +290,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id), named_region_map: |tcx, id| resolve_lifetimes_for(tcx, id).defs.get(&id),
is_late_bound_map, is_late_bound_map,
object_lifetime_defaults: |tcx, def_id| { object_lifetime_defaults,
if let Some(def_id) = def_id.as_local() {
match tcx.hir().get_by_def_id(def_id) {
Node::Item(item) => compute_object_lifetime_defaults(tcx, item),
_ => None,
}
} else {
Some(tcx.arena.alloc_from_iter(tcx.generics_of(def_id).params.iter().filter_map(
|param| match param.kind {
GenericParamDefKind::Type { object_lifetime_default, .. } => {
Some(object_lifetime_default)
}
GenericParamDefKind::Const { .. } => Some(Set1::Empty),
GenericParamDefKind::Lifetime => None,
},
)))
}
},
late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id), late_bound_vars_map: |tcx, id| resolve_lifetimes_for(tcx, id).late_bound_vars.get(&id),
..*providers ..*providers
@ -1281,10 +1264,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
} }
} }
fn compute_object_lifetime_defaults<'tcx>( fn object_lifetime_defaults<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
item: &hir::Item<'_>, def_id: LocalDefId,
) -> Option<&'tcx [ObjectLifetimeDefault]> { ) -> Option<&'tcx [ObjectLifetimeDefault]> {
let hir::Node::Item(item) = tcx.hir().get_by_def_id(def_id) else { return None; };
match item.kind { match item.kind {
hir::ItemKind::Struct(_, ref generics) hir::ItemKind::Struct(_, ref generics)
| hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Union(_, ref generics)
@ -1304,24 +1288,13 @@ fn compute_object_lifetime_defaults<'tcx>(
let object_lifetime_default_reprs: String = result let object_lifetime_default_reprs: String = result
.iter() .iter()
.map(|set| match *set { .map(|set| match *set {
Set1::Empty => "BaseDefault".into(), ObjectLifetimeDefault::Empty => "BaseDefault".into(),
Set1::One(Region::Static) => "'static".into(), ObjectLifetimeDefault::Static => "'static".into(),
Set1::One(Region::EarlyBound(mut i, _)) => generics ObjectLifetimeDefault::Param(def_id) => {
.params let def_id = def_id.expect_local();
.iter() tcx.hir().ty_param_name(def_id).to_string().into()
.find_map(|param| match param.kind { }
GenericParamKind::Lifetime { .. } => { ObjectLifetimeDefault::Ambiguous => "Ambiguous".into(),
if i == 0 {
return Some(param.name.ident().to_string().into());
}
i -= 1;
None
}
_ => None,
})
.unwrap(),
Set1::One(_) => bug!(),
Set1::Many => "Ambiguous".into(),
}) })
.collect::<Vec<Cow<'static, str>>>() .collect::<Vec<Cow<'static, str>>>()
.join(","); .join(",");
@ -1376,32 +1349,12 @@ fn object_lifetime_defaults_for_item<'tcx>(
} }
Some(match set { Some(match set {
Set1::Empty => Set1::Empty, Set1::Empty => ObjectLifetimeDefault::Empty,
Set1::One(name) => { Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
if name == hir::LifetimeName::Static { Set1::One(hir::LifetimeName::Param(param_def_id, _)) => {
Set1::One(Region::Static) ObjectLifetimeDefault::Param(param_def_id.to_def_id())
} else {
generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => {
let param_def_id = tcx.hir().local_def_id(param.hir_id);
Some((
param_def_id,
hir::LifetimeName::Param(param_def_id, param.name),
))
}
_ => None,
})
.enumerate()
.find(|&(_, (_, lt_name))| lt_name == name)
.map_or(Set1::Many, |(i, (def_id, _))| {
Set1::One(Region::EarlyBound(i as u32, def_id.to_def_id()))
})
}
} }
Set1::Many => Set1::Many, _ => ObjectLifetimeDefault::Ambiguous,
}) })
} }
GenericParamKind::Const { .. } => { GenericParamKind::Const { .. } => {
@ -1409,7 +1362,7 @@ fn object_lifetime_defaults_for_item<'tcx>(
// //
// We still store a dummy value here to allow generic parameters // We still store a dummy value here to allow generic parameters
// in an arbitrary order. // in an arbitrary order.
Some(Set1::Empty) Some(ObjectLifetimeDefault::Empty)
} }
}; };
@ -1769,24 +1722,37 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}; };
let map = &self.map; let map = &self.map;
let set_to_region = |set: &ObjectLifetimeDefault| match *set { let generics = self.tcx.generics_of(def_id);
Set1::Empty => { let set_to_region = |set: ObjectLifetimeDefault| match set {
ObjectLifetimeDefault::Empty => {
if in_body { if in_body {
None None
} else { } else {
Some(Region::Static) Some(Region::Static)
} }
} }
Set1::One(r) => { ObjectLifetimeDefault::Static => Some(Region::Static),
let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { ObjectLifetimeDefault::Param(param_def_id) => {
GenericArg::Lifetime(lt) => Some(lt), let index = generics.param_def_id_to_index[&param_def_id];
generic_args.args.get(index as usize).and_then(|arg| match arg {
GenericArg::Lifetime(lt) => map.defs.get(&lt.hir_id).copied(),
_ => None, _ => None,
}); })
r.subst(lifetimes, map)
} }
Set1::Many => None, ObjectLifetimeDefault::Ambiguous => None,
}; };
self.tcx.object_lifetime_defaults(def_id).unwrap().iter().map(set_to_region).collect() generics
.params
.iter()
.filter_map(|param| match param.kind {
GenericParamDefKind::Type { object_lifetime_default, .. } => {
Some(object_lifetime_default)
}
GenericParamDefKind::Const { .. } => Some(ObjectLifetimeDefault::Empty),
GenericParamDefKind::Lifetime => None,
})
.map(set_to_region)
.collect()
}); });
debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults); debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);

View file

@ -252,9 +252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}) })
} }
}; };
debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r); debug!("ast_region_to_region(lifetime={:?}) yields {:?}", lifetime, r);
r r
} }

View file

@ -34,6 +34,7 @@ use rustc_hir::weak_lang_items;
use rustc_hir::{GenericParamKind, HirId, Node}; use rustc_hir::{GenericParamKind, HirId, Node};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc_middle::mir::mono::Linkage; use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::subst::InternalSubsts;
@ -1597,7 +1598,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: false, has_default: false,
object_lifetime_default: rl::Set1::Empty, object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false, synthetic: false,
}, },
}); });
@ -1671,7 +1672,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
has_default: default.is_some(), has_default: default.is_some(),
object_lifetime_default: object_lifetime_defaults object_lifetime_default: object_lifetime_defaults
.as_ref() .as_ref()
.map_or(rl::Set1::Empty, |o| o[i]), .map_or(ObjectLifetimeDefault::Empty, |o| o[i]),
synthetic, synthetic,
}; };
@ -1727,7 +1728,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: false, has_default: false,
object_lifetime_default: rl::Set1::Empty, object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false, synthetic: false,
}, },
})); }));
@ -1744,7 +1745,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
pure_wrt_drop: false, pure_wrt_drop: false,
kind: ty::GenericParamDefKind::Type { kind: ty::GenericParamDefKind::Type {
has_default: false, has_default: false,
object_lifetime_default: rl::Set1::Empty, object_lifetime_default: ObjectLifetimeDefault::Empty,
synthetic: false, synthetic: false,
}, },
}); });