Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/generics.rs25
-rw-r--r--crates/hir-def/src/resolver.rs25
-rw-r--r--crates/hir-ty/src/lower.rs50
-rw-r--r--crates/hir-ty/src/mapping.rs8
-rw-r--r--crates/hir-ty/src/utils.rs34
5 files changed, 126 insertions, 16 deletions
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index 1d2c7c3a55..8bdd9c6587 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -22,8 +22,8 @@ use crate::{
lower::LowerCtx,
nameres::{DefMap, MacroSubNs},
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
- AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
- TypeOrConstParamId, TypeParamId,
+ AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
+ LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
};
/// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -365,6 +365,13 @@ impl GenericParams {
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(
db: &dyn DefDatabase,
def: GenericDefId,
@@ -507,4 +514,18 @@ impl GenericParams {
.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
+ }
+ })
+ }
}
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 226d6f513f..bfad75c50b 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -24,6 +24,7 @@ use crate::{
nameres::{DefMap, MacroSubNs},
path::{ModPath, Path, PathKind},
per_ns::PerNs,
+ type_ref::LifetimeRef,
visibility::{RawVisibility, Visibility},
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
@@ -120,6 +121,12 @@ pub enum ValueNs {
GenericParam(ConstParamId),
}
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum LifetimeNs {
+ Static,
+ LifetimeParam(LifetimeParamId),
+}
+
impl Resolver {
/// Resolve known trait from std, like `std::futures::Future`
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
@@ -418,6 +425,24 @@ impl Resolver {
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.
///
/// Note that this is a somewhat fuzzy concept -- internally, the compiler
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 0bc739e696..af1a91a06a 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -29,8 +29,10 @@ use hir_def::{
lang_item::LangItem,
nameres::MacroSubNs,
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
- resolver::{HasResolver, Resolver, TypeNs},
- type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
+ resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
+ type_ref::{
+ ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
+ },
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
@@ -53,17 +55,17 @@ use crate::{
},
db::HirDatabase,
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,
- utils::Generics,
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,
},
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
- FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
- PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
- TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
+ FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
+ LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
+ QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
+ TyKind, WhereClause,
};
#[derive(Debug)]
@@ -275,9 +277,10 @@ impl<'a> TyLoweringContext<'a> {
let inner_ty = self.lower_ty(inner);
TyKind::Slice(inner_ty).intern(Interner)
}
- TypeRef::Reference(inner, _, mutability) => {
+ TypeRef::Reference(inner, lifetime, mutability) => {
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)
.intern(Interner)
}
@@ -1309,6 +1312,33 @@ impl<'a> TyLoweringContext<'a> {
});
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 {
diff --git a/crates/hir-ty/src/mapping.rs b/crates/hir-ty/src/mapping.rs
index fba760974f..1474626039 100644
--- a/crates/hir-ty/src/mapping.rs
+++ b/crates/hir-ty/src/mapping.rs
@@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
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 {
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
}
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 8bd57820d2..84fcc31dd4 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -13,14 +13,15 @@ use either::Either;
use hir_def::{
db::DefDatabase,
generics::{
- GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
- WherePredicateTypeTarget,
+ GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
+ WherePredicate, WherePredicateTypeTarget,
},
lang_item::LangItem,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
- ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
- OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
+ ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
+ LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
+ TypeParamId,
};
use hir_expand::name::Name;
use intern::Interned;
@@ -322,6 +323,11 @@ impl Generics {
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)
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
let mut self_params = 0;
@@ -358,6 +364,26 @@ impl Generics {
}
}
+ 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> {
self.parent_generics.as_deref()
}