diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-14 15:15:52 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-14 15:15:52 +0000 |
commit | 817fbebbb5f9187994b1a09a603ba9c7b2755a06 (patch) | |
tree | 7f5d35fc2aad9880c6c7573d76ef0947c7b613fc /crates/hir | |
parent | 134c7563be05d120ffb45d9b971ba95735a0fcb5 (diff) | |
parent | c6172f3f6d3fb0982ae17f48507608609d46d179 (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.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/from_id.rs | 17 | ||||
-rw-r--r-- | crates/hir/src/has_source.rs | 14 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 51 | ||||
-rw-r--r-- | crates/hir/src/semantics/source_to_def.rs | 21 |
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 | ||
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 | |||
157 | impl From<Adt> for GenericDefId { | 174 | impl 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; | |||
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | ||
17 | pub trait HasSource { | 17 | pub 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 | |||
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()) | ||
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}; | |||
13 | use hir_ty::associated_type_shorthand_candidates; | 13 | use hir_ty::associated_type_shorthand_candidates; |
14 | use itertools::Itertools; | 14 | use itertools::Itertools; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | 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 | }; | ||
17 | 21 | ||
18 | use crate::{ | 22 | use 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, ¶m) | 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 | }; |
12 | use hir_expand::{name::AsName, AstId, MacroDefKind}; | 13 | use hir_expand::{name::AsName, AstId, MacroDefKind}; |
13 | use rustc_hash::FxHashMap; | 14 | use 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 | } |
253 | impl_from! { | 266 | impl_from! { |