Handle impl generics in method calls

This commit is contained in:
Florian Diebold 2019-02-16 22:06:23 +01:00
parent 2af067b391
commit 65bd9bc3a8
7 changed files with 122 additions and 77 deletions

View file

@ -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 {

View file

@ -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,

View file

@ -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()
}
}

View file

@ -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

View file

@ -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 {

View file

@ -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

View file

@ -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