implement resolving and lowering of Lifetimes
This commit is contained in:
parent
d3eeadc242
commit
f95b3d4cd2
@ -22,8 +22,8 @@
|
|||||||
lower::LowerCtx,
|
lower::LowerCtx,
|
||||||
nameres::{DefMap, MacroSubNs},
|
nameres::{DefMap, MacroSubNs},
|
||||||
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
|
||||||
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
|
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
|
||||||
TypeOrConstParamId, TypeParamId,
|
LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||||
@ -365,6 +365,13 @@ pub fn iter(
|
|||||||
self.type_or_consts.iter()
|
self.type_or_consts.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterator of lifetimes field
|
||||||
|
pub fn iter_lt(
|
||||||
|
&self,
|
||||||
|
) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
|
||||||
|
self.lifetimes.iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn generic_params_query(
|
pub(crate) fn generic_params_query(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def: GenericDefId,
|
def: GenericDefId,
|
||||||
@ -507,4 +514,18 @@ pub fn find_trait_self_param(&self) -> Option<LocalTypeOrConstParamId> {
|
|||||||
.then(|| id)
|
.then(|| id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find_lifetime_by_name(
|
||||||
|
&self,
|
||||||
|
name: &Name,
|
||||||
|
parent: GenericDefId,
|
||||||
|
) -> Option<LifetimeParamId> {
|
||||||
|
self.lifetimes.iter().find_map(|(id, p)| {
|
||||||
|
if &p.name == name {
|
||||||
|
Some(LifetimeParamId { local_id: id, parent })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
nameres::{DefMap, MacroSubNs},
|
nameres::{DefMap, MacroSubNs},
|
||||||
path::{ModPath, Path, PathKind},
|
path::{ModPath, Path, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
|
type_ref::LifetimeRef,
|
||||||
visibility::{RawVisibility, Visibility},
|
visibility::{RawVisibility, Visibility},
|
||||||
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
|
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
|
||||||
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
|
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
|
||||||
@ -120,6 +121,12 @@ pub enum ValueNs {
|
|||||||
GenericParam(ConstParamId),
|
GenericParam(ConstParamId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum LifetimeNs {
|
||||||
|
Static,
|
||||||
|
LifetimeParam(LifetimeParamId),
|
||||||
|
}
|
||||||
|
|
||||||
impl Resolver {
|
impl Resolver {
|
||||||
/// Resolve known trait from std, like `std::futures::Future`
|
/// Resolve known trait from std, like `std::futures::Future`
|
||||||
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
|
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
|
||||||
@ -418,6 +425,24 @@ pub fn resolve_path_as_macro_def(
|
|||||||
self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
|
self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
|
||||||
|
if lifetime.name == name::known::STATIC_LIFETIME {
|
||||||
|
return Some(LifetimeNs::Static);
|
||||||
|
}
|
||||||
|
|
||||||
|
for scope in self.scopes() {
|
||||||
|
match scope {
|
||||||
|
Scope::GenericParams { def, params } => {
|
||||||
|
if let Some(id) = params.find_lifetime_by_name(&lifetime.name, *def) {
|
||||||
|
return Some(LifetimeNs::LifetimeParam(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a set of names available in the current scope.
|
/// Returns a set of names available in the current scope.
|
||||||
///
|
///
|
||||||
/// Note that this is a somewhat fuzzy concept -- internally, the compiler
|
/// Note that this is a somewhat fuzzy concept -- internally, the compiler
|
||||||
|
@ -29,8 +29,10 @@
|
|||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
nameres::MacroSubNs,
|
nameres::MacroSubNs,
|
||||||
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
|
||||||
resolver::{HasResolver, Resolver, TypeNs},
|
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
|
||||||
type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
|
type_ref::{
|
||||||
|
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
|
||||||
|
},
|
||||||
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
|
||||||
GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
|
GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
|
||||||
ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
|
ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
|
||||||
@ -53,17 +55,17 @@
|
|||||||
},
|
},
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
make_binders,
|
make_binders,
|
||||||
mapping::{from_chalk_trait_id, ToChalk},
|
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
|
||||||
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
|
||||||
utils::Generics,
|
|
||||||
utils::{
|
utils::{
|
||||||
all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
|
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
|
||||||
InTypeConstIdMetadata,
|
InTypeConstIdMetadata,
|
||||||
},
|
},
|
||||||
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
|
||||||
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
|
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
|
||||||
PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
|
LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
|
||||||
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
|
QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
|
||||||
|
TyKind, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -275,9 +277,10 @@ pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
|
|||||||
let inner_ty = self.lower_ty(inner);
|
let inner_ty = self.lower_ty(inner);
|
||||||
TyKind::Slice(inner_ty).intern(Interner)
|
TyKind::Slice(inner_ty).intern(Interner)
|
||||||
}
|
}
|
||||||
TypeRef::Reference(inner, _, mutability) => {
|
TypeRef::Reference(inner, lifetime, mutability) => {
|
||||||
let inner_ty = self.lower_ty(inner);
|
let inner_ty = self.lower_ty(inner);
|
||||||
let lifetime = static_lifetime();
|
let lifetime =
|
||||||
|
lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
|
||||||
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
|
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
|
||||||
.intern(Interner)
|
.intern(Interner)
|
||||||
}
|
}
|
||||||
@ -1309,6 +1312,33 @@ fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>], krate: CrateId) -> Im
|
|||||||
});
|
});
|
||||||
ImplTrait { bounds: crate::make_single_type_binders(predicates) }
|
ImplTrait { bounds: crate::make_single_type_binders(predicates) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
|
||||||
|
match self.resolver.resolve_lifetime(lifetime) {
|
||||||
|
Some(resolution) => match resolution {
|
||||||
|
LifetimeNs::Static => static_lifetime(),
|
||||||
|
LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
|
||||||
|
ParamLoweringMode::Placeholder => {
|
||||||
|
LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
|
||||||
|
}
|
||||||
|
ParamLoweringMode::Variable => {
|
||||||
|
let generics = generics(
|
||||||
|
self.db.upcast(),
|
||||||
|
self.resolver.generic_def().expect("generics in scope"),
|
||||||
|
);
|
||||||
|
let idx = match generics.lifetime_idx(id) {
|
||||||
|
None => return static_lifetime(),
|
||||||
|
Some(idx) => idx,
|
||||||
|
};
|
||||||
|
|
||||||
|
LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.intern(Interner),
|
||||||
|
},
|
||||||
|
None => static_lifetime(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
fn count_impl_traits(type_ref: &TypeRef) -> usize {
|
||||||
|
@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
|
|||||||
db.lookup_intern_lifetime_param_id(interned_id)
|
db.lookup_intern_lifetime_param_id(interned_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
|
||||||
|
let interned_id = db.intern_lifetime_param_id(id);
|
||||||
|
PlaceholderIndex {
|
||||||
|
ui: chalk_ir::UniverseIndex::ROOT,
|
||||||
|
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
|
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
|
||||||
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,15 @@
|
|||||||
use hir_def::{
|
use hir_def::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
generics::{
|
generics::{
|
||||||
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
|
GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
|
||||||
WherePredicateTypeTarget,
|
WherePredicate, WherePredicateTypeTarget,
|
||||||
},
|
},
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
resolver::{HasResolver, TypeNs},
|
resolver::{HasResolver, TypeNs},
|
||||||
type_ref::{TraitBoundModifier, TypeRef},
|
type_ref::{TraitBoundModifier, TypeRef},
|
||||||
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
|
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
|
||||||
OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
|
LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
|
||||||
|
TypeParamId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::Interned;
|
use intern::Interned;
|
||||||
@ -322,6 +323,11 @@ pub(crate) fn len_self(&self) -> usize {
|
|||||||
self.params.type_or_consts.len()
|
self.params.type_or_consts.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns number of generic lifetime excluding those from parent.
|
||||||
|
pub(crate) fn len_lt_self(&self) -> usize {
|
||||||
|
self.params.lifetimes.len()
|
||||||
|
}
|
||||||
|
|
||||||
/// (parent total, self param, type param list, const param list, impl trait)
|
/// (parent total, self param, type param list, const param list, impl trait)
|
||||||
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
|
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
|
||||||
let mut self_params = 0;
|
let mut self_params = 0;
|
||||||
@ -358,6 +364,26 @@ fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
|
||||||
|
Some(self.find_lifetime(lifetime)?.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
|
||||||
|
if lifetime.parent == self.def {
|
||||||
|
let (idx, (_local_id, data)) = self
|
||||||
|
.params
|
||||||
|
.iter_lt()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, (idx, _))| *idx == lifetime.local_id)?;
|
||||||
|
|
||||||
|
Some((idx, data))
|
||||||
|
} else {
|
||||||
|
self.parent_generics()
|
||||||
|
.and_then(|g| g.find_lifetime(lifetime))
|
||||||
|
.map(|(idx, data)| (self.len_lt_self() + idx, data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
|
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
|
||||||
self.parent_generics.as_deref()
|
self.parent_generics.as_deref()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user