Skip to content

Commit 817fbeb

Browse files
bors[bot]Veykril
andauthored
Merge #6862
6862: Add LifetimeParam resolving to Semantics r=matklad a=Veykril This is stuff required for the lifetime references/definitions PR. I pulled this out to make it easier to review as well as because there is one thing that still has to be addressed which can be found in the review comments. Co-authored-by: Lukas Wirth <[email protected]>
2 parents 134c756 + c6172f3 commit 817fbeb

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)