mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Handle impl generics in method calls
This commit is contained in:
parent
2af067b391
commit
65bd9bc3a8
7 changed files with 122 additions and 77 deletions
|
@ -463,7 +463,7 @@ impl Function {
|
|||
self.id.source(db)
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl HirDatabase) -> Module {
|
||||
pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
|
@ -497,6 +497,12 @@ impl Function {
|
|||
db.generic_params((*self).into())
|
||||
}
|
||||
|
||||
/// The containing impl block, if this is a method.
|
||||
pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
|
||||
let module_impls = db.impls_in_module(self.module(db));
|
||||
ImplBlock::containing(module_impls, (*self).into())
|
||||
}
|
||||
|
||||
// TODO: move to a more general type for 'body-having' items
|
||||
/// Builds a resolver for code inside this item.
|
||||
pub fn resolver(&self, db: &impl HirDatabase) -> Resolver {
|
||||
|
@ -527,6 +533,16 @@ impl Const {
|
|||
pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) {
|
||||
self.id.source(db)
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
/// The containing impl block, if this is a method.
|
||||
pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
|
||||
let module_impls = db.impls_in_module(self.module(db));
|
||||
ImplBlock::containing(module_impls, (*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Docs for Const {
|
||||
|
@ -544,6 +560,10 @@ impl Static {
|
|||
pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) {
|
||||
self.id.source(db)
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl Docs for Static {
|
||||
|
@ -562,6 +582,10 @@ impl Trait {
|
|||
self.id.source(db)
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
|
||||
db.generic_params((*self).into())
|
||||
}
|
||||
|
@ -586,6 +610,16 @@ impl Type {
|
|||
pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> {
|
||||
db.generic_params((*self).into())
|
||||
}
|
||||
|
||||
pub fn module(&self, db: &impl PersistentHirDatabase) -> Module {
|
||||
self.id.module(db)
|
||||
}
|
||||
|
||||
/// The containing impl block, if this is a method.
|
||||
pub fn impl_block(&self, db: &impl PersistentHirDatabase) -> Option<ImplBlock> {
|
||||
let module_impls = db.impls_in_module(self.module(db));
|
||||
ImplBlock::containing(module_impls, (*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Docs for Type {
|
||||
|
|
|
@ -3,22 +3,11 @@ use std::sync::Arc;
|
|||
use ra_syntax::ast::{self, NameOwner};
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Name, AsName, Function, FnSignature,
|
||||
Name, AsName, Function, FnSignature,
|
||||
type_ref::{TypeRef, Mutability},
|
||||
PersistentHirDatabase,
|
||||
impl_block::ImplBlock,
|
||||
};
|
||||
|
||||
impl Function {
|
||||
// TODO impl_block should probably also be part of the code model API?
|
||||
|
||||
/// The containing impl block, if this is a method.
|
||||
pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
|
||||
let module_impls = db.impls_in_module(self.module(db));
|
||||
ImplBlock::containing(module_impls, (*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl FnSignature {
|
||||
pub(crate) fn fn_signature_query(
|
||||
db: &impl PersistentHirDatabase,
|
||||
|
|
|
@ -20,6 +20,7 @@ pub struct GenericParam {
|
|||
/// Data about the generic parameters of a function, struct, impl, etc.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Default)]
|
||||
pub struct GenericParams {
|
||||
pub(crate) parent_params: Option<Arc<GenericParams>>,
|
||||
pub(crate) params: Vec<GenericParam>,
|
||||
}
|
||||
|
||||
|
@ -40,28 +41,36 @@ impl GenericParams {
|
|||
def: GenericDef,
|
||||
) -> Arc<GenericParams> {
|
||||
let mut generics = GenericParams::default();
|
||||
let parent = match def {
|
||||
GenericDef::Function(it) => it.impl_block(db),
|
||||
GenericDef::Type(it) => it.impl_block(db),
|
||||
GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None,
|
||||
GenericDef::ImplBlock(_) => None,
|
||||
};
|
||||
generics.parent_params = parent.map(|p| p.generic_params(db));
|
||||
let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
|
||||
match def {
|
||||
GenericDef::Function(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Struct(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Enum(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Trait(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Type(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Function(it) => generics.fill(&*it.source(db).1, start),
|
||||
GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start),
|
||||
GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
|
||||
GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start),
|
||||
GenericDef::Type(it) => generics.fill(&*it.source(db).1, start),
|
||||
GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start),
|
||||
}
|
||||
|
||||
Arc::new(generics)
|
||||
}
|
||||
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner) {
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
self.fill_params(params)
|
||||
self.fill_params(params, start)
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_params(&mut self, params: &ast::TypeParamList) {
|
||||
fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
|
||||
for (idx, type_param) in params.type_params().enumerate() {
|
||||
let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
|
||||
let param = GenericParam { idx: idx as u32, name };
|
||||
let param = GenericParam { idx: idx as u32 + start, name };
|
||||
self.params.push(param);
|
||||
}
|
||||
}
|
||||
|
@ -69,4 +78,13 @@ impl GenericParams {
|
|||
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
|
||||
self.params.iter().find(|p| &p.name == name)
|
||||
}
|
||||
|
||||
pub fn count_parent_params(&self) -> usize {
|
||||
self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn count_params_including_parent(&self) -> usize {
|
||||
let parent_count = self.count_parent_params();
|
||||
parent_count + self.params.len()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast};
|
|||
use ra_arena::{Arena, RawId, ArenaId, impl_arena_id};
|
||||
|
||||
use crate::{
|
||||
HirDatabase,
|
||||
Module,
|
||||
PersistentHirDatabase,
|
||||
};
|
||||
|
@ -215,7 +214,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone {
|
|||
N::cast(&syntax).unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)).to_owned();
|
||||
(loc.raw.file_id, ast)
|
||||
}
|
||||
fn module(self, db: &impl HirDatabase) -> Module {
|
||||
fn module(self, db: &impl PersistentHirDatabase) -> Module {
|
||||
let int = Self::interner(db.as_ref());
|
||||
let loc = int.id2loc(self);
|
||||
loc.module
|
||||
|
|
|
@ -421,7 +421,8 @@ impl Ty {
|
|||
(var.parent_enum(db).generic_params(db), segment)
|
||||
}
|
||||
};
|
||||
// substs_from_path
|
||||
let parent_param_count = def_generics.count_parent_params();
|
||||
substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
|
||||
if let Some(generic_args) = &segment.args_and_bindings {
|
||||
// if args are provided, it should be all of them, but we can't rely on that
|
||||
let param_count = def_generics.params.len();
|
||||
|
@ -436,9 +437,8 @@ impl Ty {
|
|||
}
|
||||
// add placeholders for args that were not provided
|
||||
// TODO: handle defaults
|
||||
let supplied_params =
|
||||
segment.args_and_bindings.as_ref().map(|ga| ga.args.len()).unwrap_or(0);
|
||||
for _ in supplied_params..def_generics.params.len() {
|
||||
let supplied_params = substs.len();
|
||||
for _ in supplied_params..def_generics.count_params_including_parent() {
|
||||
substs.push(Ty::Unknown);
|
||||
}
|
||||
assert_eq!(substs.len(), def_generics.params.len());
|
||||
|
@ -666,7 +666,12 @@ fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
|
|||
}
|
||||
|
||||
fn make_substs(generics: &GenericParams) -> Substs {
|
||||
Substs(generics.params.iter().map(|_p| Ty::Unknown).collect::<Vec<_>>().into())
|
||||
Substs(
|
||||
(0..generics.count_params_including_parent())
|
||||
.map(|_p| Ty::Unknown)
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
---
|
||||
created: "2019-01-27T14:52:29.938713255+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
created: "2019-02-16T20:53:59.655361804Z"
|
||||
creator: insta@0.6.2
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
expression: "&result"
|
||||
---
|
||||
[53; 57) 'self': A<[unknown]>
|
||||
[65; 87) '{ ... }': [unknown]
|
||||
[75; 79) 'self': A<[unknown]>
|
||||
[75; 81) 'self.x': [unknown]
|
||||
[53; 57) 'self': A<T2>
|
||||
[65; 87) '{ ... }': T2
|
||||
[75; 79) 'self': A<T2>
|
||||
[75; 81) 'self.x': T2
|
||||
[99; 100) 't': T
|
||||
[110; 115) '{ t }': T
|
||||
[112; 113) 't': T
|
||||
[135; 261) '{ ....x() }': i128
|
||||
[146; 147) 'x': i32
|
||||
[150; 151) '1': i32
|
||||
[162; 163) 'y': i32
|
||||
[166; 168) 'id': fn id<i32>(T) -> T
|
||||
[166; 171) 'id(x)': i32
|
||||
[169; 170) 'x': i32
|
||||
[182; 183) 'a': A<i32>
|
||||
[186; 200) 'A { x: id(y) }': A<i32>
|
||||
[193; 195) 'id': fn id<i32>(T) -> T
|
||||
[193; 198) 'id(y)': i32
|
||||
[196; 197) 'y': i32
|
||||
[211; 212) 'z': i32
|
||||
[215; 217) 'id': fn id<i32>(T) -> T
|
||||
[215; 222) 'id(a.x)': i32
|
||||
[218; 219) 'a': A<i32>
|
||||
[218; 221) 'a.x': i32
|
||||
[233; 234) 'b': A<i32>
|
||||
[237; 247) 'A { x: z }': A<i32>
|
||||
[244; 245) 'z': i32
|
||||
[254; 255) 'b': A<i32>
|
||||
[146; 147) 'x': i128
|
||||
[150; 151) '1': i128
|
||||
[162; 163) 'y': i128
|
||||
[166; 168) 'id': fn id<i128>(T) -> T
|
||||
[166; 171) 'id(x)': i128
|
||||
[169; 170) 'x': i128
|
||||
[182; 183) 'a': A<i128>
|
||||
[186; 200) 'A { x: id(y) }': A<i128>
|
||||
[193; 195) 'id': fn id<i128>(T) -> T
|
||||
[193; 198) 'id(y)': i128
|
||||
[196; 197) 'y': i128
|
||||
[211; 212) 'z': i128
|
||||
[215; 217) 'id': fn id<i128>(T) -> T
|
||||
[215; 222) 'id(a.x)': i128
|
||||
[218; 219) 'a': A<i128>
|
||||
[218; 221) 'a.x': i128
|
||||
[233; 234) 'b': A<i128>
|
||||
[237; 247) 'A { x: z }': A<i128>
|
||||
[244; 245) 'z': i128
|
||||
[254; 255) 'b': A<i128>
|
||||
[254; 259) 'b.x()': i128
|
||||
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
---
|
||||
created: "2019-02-16T19:27:11.573533475Z"
|
||||
created: "2019-02-16T20:53:59.657979128Z"
|
||||
creator: insta@0.6.2
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
expression: "&result"
|
||||
---
|
||||
[74; 78) 'self': A<[unknown], [unknown]>
|
||||
[85; 107) '{ ... }': [unknown]
|
||||
[95; 99) 'self': A<[unknown], [unknown]>
|
||||
[95; 101) 'self.x': [unknown]
|
||||
[117; 121) 'self': A<[unknown], [unknown]>
|
||||
[128; 150) '{ ... }': [unknown]
|
||||
[138; 142) 'self': A<[unknown], [unknown]>
|
||||
[138; 144) 'self.y': [unknown]
|
||||
[163; 167) 'self': A<[unknown], [unknown]>
|
||||
[74; 78) 'self': A<X, Y>
|
||||
[85; 107) '{ ... }': X
|
||||
[95; 99) 'self': A<X, Y>
|
||||
[95; 101) 'self.x': X
|
||||
[117; 121) 'self': A<X, Y>
|
||||
[128; 150) '{ ... }': Y
|
||||
[138; 142) 'self': A<X, Y>
|
||||
[138; 144) 'self.y': Y
|
||||
[163; 167) 'self': A<X, Y>
|
||||
[169; 170) 't': T
|
||||
[188; 223) '{ ... }': ([unknown], [unknown], T)
|
||||
[198; 217) '(self.....y, t)': ([unknown], [unknown], T)
|
||||
[199; 203) 'self': A<[unknown], [unknown]>
|
||||
[199; 205) 'self.x': [unknown]
|
||||
[207; 211) 'self': A<[unknown], [unknown]>
|
||||
[207; 213) 'self.y': [unknown]
|
||||
[188; 223) '{ ... }': (X, Y, T)
|
||||
[198; 217) '(self.....y, t)': (X, Y, T)
|
||||
[199; 203) 'self': A<X, Y>
|
||||
[199; 205) 'self.x': X
|
||||
[207; 211) 'self': A<X, Y>
|
||||
[207; 213) 'self.y': Y
|
||||
[215; 216) 't': T
|
||||
[245; 342) '{ ...(1); }': ()
|
||||
[255; 256) 'a': A<u64, i64>
|
||||
|
@ -27,13 +27,13 @@ expression: "&result"
|
|||
[266; 270) '1u64': u64
|
||||
[275; 279) '1i64': i64
|
||||
[287; 288) 'a': A<u64, i64>
|
||||
[287; 292) 'a.x()': [unknown]
|
||||
[287; 292) 'a.x()': u64
|
||||
[298; 299) 'a': A<u64, i64>
|
||||
[298; 303) 'a.y()': [unknown]
|
||||
[298; 303) 'a.y()': i64
|
||||
[309; 310) 'a': A<u64, i64>
|
||||
[309; 319) 'a.z(1i128)': ([unknown], [unknown], i128)
|
||||
[309; 319) 'a.z(1i128)': (u64, i64, i128)
|
||||
[313; 318) '1i128': i128
|
||||
[325; 326) 'a': A<u64, i64>
|
||||
[325; 339) 'a.z::<u128>(1)': ([unknown], [unknown], i32)
|
||||
[325; 339) 'a.z::<u128>(1)': (u64, i64, i32)
|
||||
[337; 338) '1': i32
|
||||
|
||||
|
|
Loading…
Reference in a new issue