aboutsummaryrefslogtreecommitdiff
path: root/crates/hir
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-14 15:15:52 +0000
committerGitHub <[email protected]>2020-12-14 15:15:52 +0000
commit817fbebbb5f9187994b1a09a603ba9c7b2755a06 (patch)
tree7f5d35fc2aad9880c6c7573d76ef0947c7b613fc /crates/hir
parent134c7563be05d120ffb45d9b971ba95735a0fcb5 (diff)
parentc6172f3f6d3fb0982ae17f48507608609d46d179 (diff)
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]>
Diffstat (limited to 'crates/hir')
-rw-r--r--crates/hir/src/code_model.rs8
-rw-r--r--crates/hir/src/from_id.rs17
-rw-r--r--crates/hir/src/has_source.rs14
-rw-r--r--crates/hir/src/semantics.rs51
-rw-r--r--crates/hir/src/semantics/source_to_def.rs21
5 files changed, 98 insertions, 13 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index fcc42c6bb..42dc35b76 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1250,6 +1250,14 @@ impl LifetimeParam {
1250 let params = db.generic_params(self.id.parent); 1250 let params = db.generic_params(self.id.parent);
1251 params.lifetimes[self.id.local_id].name.clone() 1251 params.lifetimes[self.id.local_id].name.clone()
1252 } 1252 }
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 }
1253} 1261}
1254 1262
1255// FIXME: rename from `ImplDef` to `Impl` 1263// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs
index 265ef6d1f..dd3fcfe4a 100644
--- a/crates/hir/src/from_id.rs
+++ b/crates/hir/src/from_id.rs
@@ -41,6 +41,7 @@ from_id![
41 (hir_def::FunctionId, crate::Function), 41 (hir_def::FunctionId, crate::Function),
42 (hir_def::ImplId, crate::ImplDef), 42 (hir_def::ImplId, crate::ImplDef),
43 (hir_def::TypeParamId, crate::TypeParam), 43 (hir_def::TypeParamId, crate::TypeParam),
44 (hir_def::LifetimeParamId, crate::LifetimeParam),
44 (hir_expand::MacroDefId, crate::MacroDef) 45 (hir_expand::MacroDefId, crate::MacroDef)
45]; 46];
46 47
@@ -154,6 +155,22 @@ impl From<GenericDef> for GenericDefId {
154 } 155 }
155} 156}
156 157
158impl 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
157impl From<Adt> for GenericDefId { 174impl From<Adt> for GenericDefId {
158 fn from(id: Adt) -> Self { 175 fn from(id: Adt) -> Self {
159 match id { 176 match id {
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs
index c77494152..1e64a1614 100644
--- a/crates/hir/src/has_source.rs
+++ b/crates/hir/src/has_source.rs
@@ -10,8 +10,8 @@ use hir_expand::InFile;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef, MacroDef, 13 db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, ImplDef,
14 Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, 14 LifetimeParam, MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
15}; 15};
16 16
17pub trait HasSource { 17pub trait HasSource {
@@ -129,6 +129,14 @@ impl HasSource for TypeParam {
129 type Ast = Either<ast::Trait, ast::TypeParam>; 129 type Ast = Either<ast::Trait, ast::TypeParam>;
130 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { 130 fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> {
131 let child_source = self.id.parent.child_source(db.upcast()); 131 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
136impl 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())
133 } 141 }
134} 142}
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 4bd22ed27..e4fc21ced 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -13,7 +13,11 @@ use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
13use hir_ty::associated_type_shorthand_candidates; 13use hir_ty::associated_type_shorthand_candidates;
14use itertools::Itertools; 14use itertools::Itertools;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
16use syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode, SyntaxToken, TextSize}; 16use syntax::{
17 algo::find_node_at_offset,
18 ast::{self, GenericParamsOwner},
19 match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
20};
17 21
18use crate::{ 22use crate::{
19 code_model::Access, 23 code_model::Access,
@@ -21,8 +25,9 @@ use crate::{
21 diagnostics::Diagnostic, 25 diagnostics::Diagnostic,
22 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 26 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
23 source_analyzer::{resolve_hir_path, SourceAnalyzer}, 27 source_analyzer::{resolve_hir_path, SourceAnalyzer},
24 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, 28 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, LifetimeParam, Local,
25 Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 29 MacroDef, Module, ModuleDef, Name, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam,
30 VariantDef,
26}; 31};
27 32
28#[derive(Debug, Clone, PartialEq, Eq)] 33#[derive(Debug, Clone, PartialEq, Eq)]
@@ -173,6 +178,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
173 self.imp.descend_node_at_offset(node, offset).find_map(N::cast) 178 self.imp.descend_node_at_offset(node, offset).find_map(N::cast)
174 } 179 }
175 180
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
176 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 186 pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
177 self.imp.type_of_expr(expr) 187 self.imp.type_of_expr(expr)
178 } 188 }
@@ -392,16 +402,44 @@ impl<'db> SemanticsImpl<'db> {
392 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len()) 402 .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
393 } 403 }
394 404
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
395 fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> { 433 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)
397 } 435 }
398 436
399 fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> { 437 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)
401 } 439 }
402 440
403 fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> { 441 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)
405 } 443 }
406 444
407 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> { 445 fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
@@ -684,6 +722,7 @@ to_def_impls![
684 (crate::Field, ast::TupleField, tuple_field_to_def), 722 (crate::Field, ast::TupleField, tuple_field_to_def),
685 (crate::EnumVariant, ast::Variant, enum_variant_to_def), 723 (crate::EnumVariant, ast::Variant, enum_variant_to_def),
686 (crate::TypeParam, ast::TypeParam, type_param_to_def), 724 (crate::TypeParam, ast::TypeParam, type_param_to_def),
725 (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
687 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros 726 (crate::MacroDef, ast::MacroCall, macro_call_to_def), // this one is dubious, not all calls are macros
688 (crate::Local, ast::IdentPat, bind_pat_to_def), 727 (crate::Local, ast::IdentPat, bind_pat_to_def),
689]; 728];
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 66fc11611..badcf0ae8 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -7,7 +7,8 @@ use hir_def::{
7 expr::PatId, 7 expr::PatId,
8 keys::{self, Key}, 8 keys::{self, Key},
9 ConstId, DefWithBodyId, EnumId, EnumVariantId, FieldId, FunctionId, GenericDefId, ImplId, 9 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,
11}; 12};
12use hir_expand::{name::AsName, AstId, MacroDefKind}; 13use hir_expand::{name::AsName, AstId, MacroDefKind};
13use rustc_hash::FxHashMap; 14use rustc_hash::FxHashMap;
@@ -128,13 +129,25 @@ impl SourceToDefCtx<'_, '_> {
128 129
129 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> { 130 pub(super) fn type_param_to_def(&mut self, src: InFile<ast::TypeParam>) -> Option<TypeParamId> {
130 let container: ChildContainer = 131 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();
132 let db = self.db; 133 let db = self.db;
133 let dyn_map = 134 let dyn_map =
134 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db)); 135 &*self.cache.entry(container).or_insert_with(|| container.child_by_source(db));
135 dyn_map[keys::TYPE_PARAM].get(&src).copied() 136 dyn_map[keys::TYPE_PARAM].get(&src).copied()
136 } 137 }
137 138
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
138 // FIXME: use DynMap as well? 151 // FIXME: use DynMap as well?
139 pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> { 152 pub(super) fn macro_call_to_def(&mut self, src: InFile<ast::MacroCall>) -> Option<MacroDefId> {
140 let kind = MacroDefKind::Declarative; 153 let kind = MacroDefKind::Declarative;
@@ -203,7 +216,7 @@ impl SourceToDefCtx<'_, '_> {
203 Some(def.into()) 216 Some(def.into())
204 } 217 }
205 218
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> {
207 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) { 220 for container in src.cloned().ancestors_with_macros(self.db.upcast()).skip(1) {
208 let res: GenericDefId = match_ast! { 221 let res: GenericDefId = match_ast! {
209 match (container.value) { 222 match (container.value) {
@@ -247,7 +260,7 @@ pub(crate) enum ChildContainer {
247 VariantId(VariantId), 260 VariantId(VariantId),
248 TypeAliasId(TypeAliasId), 261 TypeAliasId(TypeAliasId),
249 /// XXX: this might be the same def as, for example an `EnumId`. However, 262 /// 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.
251 GenericDefId(GenericDefId), 264 GenericDefId(GenericDefId),
252} 265}
253impl_from! { 266impl_from! {