Skip to content

Commit c6172f3

Browse files
committed
Add LifetimeParam resolving to Semantics
1 parent dbd0cfb commit c6172f3

File tree

8 files changed

+131
-39
lines changed

8 files changed

+131
-39
lines changed

crates/hir/src/code_model.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,14 @@ impl LifetimeParam {
12501250
let params = db.generic_params(self.id.parent);
12511251
params.lifetimes[self.id.local_id].name.clone()
12521252
}
1253+
1254+
pub fn module(self, db: &dyn HirDatabase) -> Module {
1255+
self.id.parent.module(db.upcast()).into()
1256+
}
1257+
1258+
pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
1259+
self.id.parent.into()
1260+
}
12531261
}
12541262

12551263
// FIXME: rename from `ImplDef` to `Impl`

crates/hir/src/from_id.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ from_id![
4141
(hir_def::FunctionId, crate::Function),
4242
(hir_def::ImplId, crate::ImplDef),
4343
(hir_def::TypeParamId, crate::TypeParam),
44+
(hir_def::LifetimeParamId, crate::LifetimeParam),
4445
(hir_expand::MacroDefId, crate::MacroDef)
4546
];
4647

@@ -154,6 +155,22 @@ impl From<GenericDef> for GenericDefId {
154155
}
155156
}
156157

158+
impl From<GenericDefId> for GenericDef {
159+
fn from(def: GenericDefId) -> Self {
160+
match def {
161+
GenericDefId::FunctionId(it) => GenericDef::Function(it.into()),
162+
GenericDefId::AdtId(it) => GenericDef::Adt(it.into()),
163+
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
164+
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
165+
GenericDefId::ImplId(it) => GenericDef::ImplDef(it.into()),
166+
GenericDefId::EnumVariantId(it) => {
167+
GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id })
168+
}
169+
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
170+
}
171+
}
172+
}
173+
157174
impl From<Adt> for GenericDefId {
158175
fn from(id: Adt) -> Self {
159176
match id {

crates/hir/src/has_source.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use hir_expand::InFile;
1010
use syntax::ast;
1111

1212
use crate::{
13-
db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, MacroDef,
14-
Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
13+
db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef,
14+
LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
1515
};
1616

1717
pub trait HasSource {
@@ -129,6 +129,14 @@ impl HasSource for TypeParam {
129129
type Ast = Either<ast::Trait, ast::TypeParam>;
130130
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
131131
let child_source = self.id.parent.child_source(db.upcast());
132-
child_source.map(|it| it[self.id.local_id].clone())
132+
child_source.map(|it| it.type_params[self.id.local_id].clone())
133+
}
134+
}
135+
136+
impl HasSource for LifetimeParam {
137+
type Ast = ast::LifetimeParam;
138+
fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
139+
let child_source = self.id.parent.child_source(db.upcast());
140+
child_source.map(|it| it.lifetime_params[self.id.local_id].clone())
133141
}
134142
}

crates/hir/src/semantics.rs

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@ use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
1313
use hir_ty::associated_type_shorthand_candidates;
1414
use itertools::Itertools;
1515
use rustc_hash::{FxHashMap, FxHashSet};
16-
use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize};
16+
use syntax::{
17+
algo::find_node_at_offset,
18+
ast::{self, GenericParamsOwner},
19+
match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
20+
};
1721

1822
use crate::{
1923
code_model::Access,
2024
db::HirDatabase,
2125
diagnostics::Diagnostic,
2226
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
2327
source_analyzer::{resolve_hir_path, SourceAnalyzer},
24-
AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef,
25-
Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
28+
AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local,
29+
MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
30+
VariantDef,
2631
};
2732

2833
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -173,6 +178,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
173178
self.imp.descend_node_at_offset(node, offset).find_map(N::cast)
174179
}
175180

181+
// FIXME: Replace the SyntaxToken with a typed ast Node/Token
182+
pub fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
183+
self.imp.resolve_lifetime_param(lifetime_token)
184+
}
185+
176186
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
177187
self.imp.type_of_expr(expr)
178188
}
@@ -392,16 +402,44 @@ impl<'db> SemanticsImpl<'db> {
392402
.kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
393403
}
394404

405+
// FIXME: Replace the SyntaxToken with a typed ast Node/Token
406+
fn resolve_lifetime_param(&self, lifetime_token: &SyntaxToken) -> Option<LifetimeParam> {
407+
if lifetime_token.kind() != syntax::SyntaxKind::LIFETIME {
408+
return None;
409+
}
410+
let lifetime_text = lifetime_token.text();
411+
let lifetime_param = lifetime_token.parent().ancestors().find_map(|syn| {
412+
let gpl = match_ast! {
413+
match syn {
414+
ast::Fn(it) => it.generic_param_list()?,
415+
ast::TypeAlias(it) => it.generic_param_list()?,
416+
ast::Struct(it) => it.generic_param_list()?,
417+
ast::Enum(it) => it.generic_param_list()?,
418+
ast::Union(it) => it.generic_param_list()?,
419+
ast::Trait(it) => it.generic_param_list()?,
420+
ast::Impl(it) => it.generic_param_list()?,
421+
ast::WherePred(it) => it.generic_param_list()?,
422+
ast::ForType(it) => it.generic_param_list()?,
423+
_ => return None,
424+
}
425+
};
426+
gpl.lifetime_params()
427+
.find(|tp| tp.lifetime_token().as_ref().map(|lt| lt.text()) == Some(lifetime_text))
428+
})?;
429+
let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param);
430+
ToDef::to_def(self, src)
431+
}
432+
395433
fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
396-
self.analyze(expr.syntax()).type_of_expr(self.db, &expr)
434+
self.analyze(expr.syntax()).type_of_expr(self.db, expr)
397435
}
398436

399437
fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
400-
self.analyze(pat.syntax()).type_of_pat(self.db, &pat)
438+
self.analyze(pat.syntax()).type_of_pat(self.db, pat)
401439
}
402440

403441
fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
404-
self.analyze(param.syntax()).type_of_self(self.db, &param)
442+
self.analyze(param.syntax()).type_of_self(self.db, param)
405443
}
406444

407445
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
@@ -684,6 +722,7 @@ to_def_impls![
684722
(crate::Field, ast::TupleField, tuple_field_to_def),
685723
(crate::EnumVariant, ast::Variant, enum_variant_to_def),
686724
(crate::TypeParam, ast::TypeParam, type_param_to_def),
725+
(crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
687726
(crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros
688727
(crate::Local, ast::IdentPat, bind_pat_to_def),
689728
];

crates/hir/src/semantics/source_to_def.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use hir_def::{
77
expr::PatId,
88
keys::{self, Key},
99
ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId,
10-
ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
10+
LifetimeParamId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
11+
VariantId,
1112
};
1213
use hir_expand::{name::AsName, AstId, MacroDefKind};
1314
use rustc_hash::FxHashMap;
@@ -128,13 +129,25 @@ impl SourceToDefCtx<'_, '_> {
128129

129130
pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
130131
let container: ChildContainer =
131-
self.find_type_param_container(src.as_ref().map(|it| it.syntax()))?.into();
132+
self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
132133
let db = self.db;
133134
let dyn_map =
134135
&*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
135136
dyn_map[keys::TYPE_PARAM].get(&src).copied()
136137
}
137138

139+
pub(super) fn lifetime_param_to_def(
140+
&mut self,
141+
src: InFile<ast::LifetimeParam>,
142+
) -> Option<LifetimeParamId> {
143+
let container: ChildContainer =
144+
self.find_generic_param_container(src.as_ref().map(|it| it.syntax()))?.into();
145+
let db = self.db;
146+
let dyn_map =
147+
&*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
148+
dyn_map[keys::LIFETIME_PARAM].get(&src).copied()
149+
}
150+
138151
// FIXME: use DynMap as well?
139152
pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> {
140153
let kind = MacroDefKind::Declarative;
@@ -203,7 +216,7 @@ impl SourceToDefCtx<'_, '_> {
203216
Some(def.into())
204217
}
205218

206-
fn find_type_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
219+
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
207220
for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
208221
let res: GenericDefId = match_ast! {
209222
match (container.value) {
@@ -247,7 +260,7 @@ pub(crate) enum ChildContainer {
247260
VariantId(VariantId),
248261
TypeAliasId(TypeAliasId),
249262
/// XXX: this might be the same def as, for example an `EnumId`. However,
250-
/// here the children generic parameters, and not, eg enum variants.
263+
/// here the children are generic parameters, and not, eg enum variants.
251264
GenericDefId(GenericDefId),
252265
}
253266
impl_from! {

crates/hir_def/src/generics.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ use crate::{
1919
db::DefDatabase,
2020
dyn_map::DynMap,
2121
keys,
22-
src::HasChildSource,
2322
src::HasSource,
2423
type_ref::{LifetimeRef, TypeBound, TypeRef},
25-
AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId,
24+
AdtId, GenericDefId, LifetimeParamId, LocalLifetimeParamId, LocalTypeParamId, Lookup,
25+
TypeParamId,
2626
};
2727

2828
/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -72,7 +72,11 @@ pub enum WherePredicateTypeTarget {
7272
// FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
7373
}
7474

75-
type SourceMap = ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>;
75+
#[derive(Default)]
76+
pub struct SourceMaps {
77+
pub type_params: ArenaMap<LocalTypeParamId, Either<ast::Trait, ast::TypeParam>>,
78+
pub lifetime_params: ArenaMap<LocalLifetimeParamId, ast::LifetimeParam>,
79+
}
7680

7781
impl GenericParams {
7882
pub(crate) fn generic_params_query(
@@ -129,9 +133,9 @@ impl GenericParams {
129133
Arc::new(generics)
130134
}
131135

132-
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
136+
fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMaps>) {
133137
let mut generics = GenericParams::default();
134-
let mut sm = ArenaMap::default();
138+
let mut sm = SourceMaps::default();
135139

136140
// FIXME: add `: Sized` bound for everything except for `Self` in traits
137141
let file_id = match def {
@@ -174,7 +178,7 @@ impl GenericParams {
174178
default: None,
175179
provenance: TypeParamProvenance::TraitSelf,
176180
});
177-
sm.insert(self_param_id, Either::Left(src.value.clone()));
181+
sm.type_params.insert(self_param_id, Either::Left(src.value.clone()));
178182
// add super traits as bounds on Self
179183
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
180184
let self_param = TypeRef::Path(name![Self].into());
@@ -210,7 +214,7 @@ impl GenericParams {
210214
pub(crate) fn fill(
211215
&mut self,
212216
lower_ctx: &LowerCtx,
213-
sm: &mut SourceMap,
217+
sm: &mut SourceMaps,
214218
node: &dyn GenericParamsOwner,
215219
) {
216220
if let Some(params) = node.generic_param_list() {
@@ -237,7 +241,7 @@ impl GenericParams {
237241
fn fill_params(
238242
&mut self,
239243
lower_ctx: &LowerCtx,
240-
sm: &mut SourceMap,
244+
sm: &mut SourceMaps,
241245
params: ast::GenericParamList,
242246
) {
243247
for type_param in params.type_params() {
@@ -250,7 +254,7 @@ impl GenericParams {
250254
provenance: TypeParamProvenance::TypeParamList,
251255
};
252256
let param_id = self.types.alloc(param);
253-
sm.insert(param_id, Either::Right(type_param.clone()));
257+
sm.type_params.insert(param_id, Either::Right(type_param.clone()));
254258

255259
let type_ref = TypeRef::Path(name.into());
256260
self.fill_bounds(&lower_ctx, &type_param, Either::Left(type_ref));
@@ -260,7 +264,8 @@ impl GenericParams {
260264
.lifetime_token()
261265
.map_or_else(Name::missing, |tok| Name::new_lifetime(&tok));
262266
let param = LifetimeParamData { name: name.clone() };
263-
let _param_id = self.lifetimes.alloc(param);
267+
let param_id = self.lifetimes.alloc(param);
268+
sm.lifetime_params.insert(param_id, lifetime_param.clone());
264269
let lifetime_ref = LifetimeRef::new_name(name);
265270
self.fill_bounds(&lower_ctx, &lifetime_param, Either::Right(lifetime_ref));
266271
}
@@ -340,27 +345,29 @@ impl GenericParams {
340345
})
341346
}
342347
}
343-
344-
impl HasChildSource for GenericDefId {
345-
type ChildId = LocalTypeParamId;
346-
type Value = Either<ast::Trait, ast::TypeParam>;
347-
fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMap> {
348-
let (_, sm) = GenericParams::new(db, *self);
349-
sm
348+
impl GenericDefId {
349+
// FIXME: Change HasChildSource's ChildId AssocItem to be a generic parameter instead
350+
pub fn child_source(&self, db: &dyn DefDatabase) -> InFile<SourceMaps> {
351+
GenericParams::new(db, *self).1
350352
}
351353
}
352354

353355
impl ChildBySource for GenericDefId {
354356
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
355357
let mut res = DynMap::default();
356-
let arena_map = self.child_source(db);
357-
let arena_map = arena_map.as_ref();
358-
for (local_id, src) in arena_map.value.iter() {
358+
let (_, sm) = GenericParams::new(db, *self);
359+
360+
let sm = sm.as_ref();
361+
for (local_id, src) in sm.value.type_params.iter() {
359362
let id = TypeParamId { parent: *self, local_id };
360363
if let Either::Right(type_param) = src {
361-
res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id)
364+
res[keys::TYPE_PARAM].insert(sm.with_value(type_param.clone()), id)
362365
}
363366
}
367+
for (local_id, src) in sm.value.lifetime_params.iter() {
368+
let id = LifetimeParamId { parent: *self, local_id };
369+
res[keys::LIFETIME_PARAM].insert(sm.with_value(src.clone()), id);
370+
}
364371
res
365372
}
366373
}

crates/hir_def/src/item_tree/lower.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::{collections::hash_map::Entry, mem, sync::Arc};
44

5-
use arena::map::ArenaMap;
65
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, name::known, HirFileId};
76
use smallvec::SmallVec;
87
use syntax::{
@@ -607,7 +606,7 @@ impl Ctx {
607606
owner: GenericsOwner<'_>,
608607
node: &impl ast::GenericParamsOwner,
609608
) -> GenericParamsId {
610-
let mut sm = &mut ArenaMap::default();
609+
let mut sm = &mut Default::default();
611610
let mut generics = GenericParams::default();
612611
match owner {
613612
GenericsOwner::Function(func) => {
@@ -630,7 +629,7 @@ impl Ctx {
630629
default: None,
631630
provenance: TypeParamProvenance::TraitSelf,
632631
});
633-
sm.insert(self_param_id, Either::Left(trait_def.clone()));
632+
sm.type_params.insert(self_param_id, Either::Left(trait_def.clone()));
634633
// add super traits as bounds on Self
635634
// i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
636635
let self_param = TypeRef::Path(name![Self].into());

crates/hir_def/src/keys.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use syntax::{ast, AstNode, AstPtr};
88

99
use crate::{
1010
dyn_map::{DynMap, Policy},
11-
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, StaticId, StructId, TraitId,
12-
TypeAliasId, TypeParamId, UnionId,
11+
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, StaticId,
12+
StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
1313
};
1414

1515
pub type Key<K, V> = crate::dyn_map::Key<InFile<K>, V, AstPtrPolicy<K, V>>;
@@ -28,6 +28,7 @@ pub const VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
2828
pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
2929
pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
3030
pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
31+
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
3132

3233
pub const MACRO: Key<ast::MacroCall, MacroDefId> = Key::new();
3334

0 commit comments

Comments
 (0)