Skip to content

Commit f95b3d4

Browse files
committed
implement resolving and lowering of Lifetimes
1 parent d3eeadc commit f95b3d4

File tree

5 files changed

+126
-16
lines changed

5 files changed

+126
-16
lines changed

crates/hir-def/src/generics.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ use crate::{
2222
lower::LowerCtx,
2323
nameres::{DefMap, MacroSubNs},
2424
type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
25-
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
26-
TypeOrConstParamId, TypeParamId,
25+
AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
26+
LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
2727
};
2828

2929
/// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -365,6 +365,13 @@ impl GenericParams {
365365
self.type_or_consts.iter()
366366
}
367367

368+
/// Iterator of lifetimes field
369+
pub fn iter_lt(
370+
&self,
371+
) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
372+
self.lifetimes.iter()
373+
}
374+
368375
pub(crate) fn generic_params_query(
369376
db: &dyn DefDatabase,
370377
def: GenericDefId,
@@ -507,4 +514,18 @@ impl GenericParams {
507514
.then(|| id)
508515
})
509516
}
517+
518+
pub fn find_lifetime_by_name(
519+
&self,
520+
name: &Name,
521+
parent: GenericDefId,
522+
) -> Option<LifetimeParamId> {
523+
self.lifetimes.iter().find_map(|(id, p)| {
524+
if &p.name == name {
525+
Some(LifetimeParamId { local_id: id, parent })
526+
} else {
527+
None
528+
}
529+
})
530+
}
510531
}

crates/hir-def/src/resolver.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::{
2424
nameres::{DefMap, MacroSubNs},
2525
path::{ModPath, Path, PathKind},
2626
per_ns::PerNs,
27+
type_ref::LifetimeRef,
2728
visibility::{RawVisibility, Visibility},
2829
AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
2930
ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
@@ -120,6 +121,12 @@ pub enum ValueNs {
120121
GenericParam(ConstParamId),
121122
}
122123

124+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
125+
pub enum LifetimeNs {
126+
Static,
127+
LifetimeParam(LifetimeParamId),
128+
}
129+
123130
impl Resolver {
124131
/// Resolve known trait from std, like `std::futures::Future`
125132
pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
@@ -418,6 +425,24 @@ impl Resolver {
418425
self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
419426
}
420427

428+
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
429+
if lifetime.name == name::known::STATIC_LIFETIME {
430+
return Some(LifetimeNs::Static);
431+
}
432+
433+
for scope in self.scopes() {
434+
match scope {
435+
Scope::GenericParams { def, params } => {
436+
if let Some(id) = params.find_lifetime_by_name(&lifetime.name, *def) {
437+
return Some(LifetimeNs::LifetimeParam(id));
438+
}
439+
}
440+
_ => continue,
441+
}
442+
}
443+
None
444+
}
445+
421446
/// Returns a set of names available in the current scope.
422447
///
423448
/// Note that this is a somewhat fuzzy concept -- internally, the compiler

crates/hir-ty/src/lower.rs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ use hir_def::{
2929
lang_item::LangItem,
3030
nameres::MacroSubNs,
3131
path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
32-
resolver::{HasResolver, Resolver, TypeNs},
33-
type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
32+
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
33+
type_ref::{
34+
ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
35+
},
3436
AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
3537
GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
3638
ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
@@ -53,17 +55,17 @@ use crate::{
5355
},
5456
db::HirDatabase,
5557
make_binders,
56-
mapping::{from_chalk_trait_id, ToChalk},
58+
mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
5759
static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
58-
utils::Generics,
5960
utils::{
60-
all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
61+
all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
6162
InTypeConstIdMetadata,
6263
},
6364
AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
64-
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, ParamKind,
65-
PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, Substitution,
66-
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
65+
FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
66+
LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
67+
QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
68+
TyKind, WhereClause,
6769
};
6870

6971
#[derive(Debug)]
@@ -275,9 +277,10 @@ impl<'a> TyLoweringContext<'a> {
275277
let inner_ty = self.lower_ty(inner);
276278
TyKind::Slice(inner_ty).intern(Interner)
277279
}
278-
TypeRef::Reference(inner, _, mutability) => {
280+
TypeRef::Reference(inner, lifetime, mutability) => {
279281
let inner_ty = self.lower_ty(inner);
280-
let lifetime = static_lifetime();
282+
let lifetime =
283+
lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
281284
TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
282285
.intern(Interner)
283286
}
@@ -1309,6 +1312,33 @@ impl<'a> TyLoweringContext<'a> {
13091312
});
13101313
ImplTrait { bounds: crate::make_single_type_binders(predicates) }
13111314
}
1315+
1316+
fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
1317+
match self.resolver.resolve_lifetime(lifetime) {
1318+
Some(resolution) => match resolution {
1319+
LifetimeNs::Static => static_lifetime(),
1320+
LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
1321+
ParamLoweringMode::Placeholder => {
1322+
LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
1323+
}
1324+
ParamLoweringMode::Variable => {
1325+
let generics = generics(
1326+
self.db.upcast(),
1327+
self.resolver.generic_def().expect("generics in scope"),
1328+
);
1329+
let idx = match generics.lifetime_idx(id) {
1330+
None => return static_lifetime(),
1331+
Some(idx) => idx,
1332+
};
1333+
1334+
LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
1335+
}
1336+
}
1337+
.intern(Interner),
1338+
},
1339+
None => static_lifetime(),
1340+
}
1341+
}
13121342
}
13131343

13141344
fn count_impl_traits(type_ref: &TypeRef) -> usize {

crates/hir-ty/src/mapping.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
151151
db.lookup_intern_lifetime_param_id(interned_id)
152152
}
153153

154+
pub(crate) fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
155+
let interned_id = db.intern_lifetime_param_id(id);
156+
PlaceholderIndex {
157+
ui: chalk_ir::UniverseIndex::ROOT,
158+
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
159+
}
160+
}
161+
154162
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
155163
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
156164
}

crates/hir-ty/src/utils.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ use either::Either;
1313
use hir_def::{
1414
db::DefDatabase,
1515
generics::{
16-
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
17-
WherePredicateTypeTarget,
16+
GenericParams, LifetimeParamData, TypeOrConstParamData, TypeParamProvenance,
17+
WherePredicate, WherePredicateTypeTarget,
1818
},
1919
lang_item::LangItem,
2020
resolver::{HasResolver, TypeNs},
2121
type_ref::{TraitBoundModifier, TypeRef},
22-
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
23-
OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
22+
ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId,
23+
LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
24+
TypeParamId,
2425
};
2526
use hir_expand::name::Name;
2627
use intern::Interned;
@@ -322,6 +323,11 @@ impl Generics {
322323
self.params.type_or_consts.len()
323324
}
324325

326+
/// Returns number of generic lifetime excluding those from parent.
327+
pub(crate) fn len_lt_self(&self) -> usize {
328+
self.params.lifetimes.len()
329+
}
330+
325331
/// (parent total, self param, type param list, const param list, impl trait)
326332
pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
327333
let mut self_params = 0;
@@ -358,6 +364,26 @@ impl Generics {
358364
}
359365
}
360366

367+
pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
368+
Some(self.find_lifetime(lifetime)?.0)
369+
}
370+
371+
fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
372+
if lifetime.parent == self.def {
373+
let (idx, (_local_id, data)) = self
374+
.params
375+
.iter_lt()
376+
.enumerate()
377+
.find(|(_, (idx, _))| *idx == lifetime.local_id)?;
378+
379+
Some((idx, data))
380+
} else {
381+
self.parent_generics()
382+
.and_then(|g| g.find_lifetime(lifetime))
383+
.map(|(idx, data)| (self.len_lt_self() + idx, data))
384+
}
385+
}
386+
361387
pub(crate) fn parent_generics(&self) -> Option<&Generics> {
362388
self.parent_generics.as_deref()
363389
}

0 commit comments

Comments
 (0)