mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 05:15:04 +00:00
Add type params to FnSignature
This commit is contained in:
parent
67e40e431a
commit
aa06893a14
9 changed files with 106 additions and 136 deletions
|
@ -388,6 +388,7 @@ pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FnSignature {
|
||||
pub(crate) name: Name,
|
||||
pub(crate) type_params: Arc<GenericParams>,
|
||||
pub(crate) args: Vec<TypeRef>,
|
||||
pub(crate) ret_type: TypeRef,
|
||||
/// True if the first param is `self`. This is relevant to decide whether this
|
||||
|
@ -413,6 +414,10 @@ impl FnSignature {
|
|||
pub fn has_self_param(&self) -> bool {
|
||||
self.has_self_param
|
||||
}
|
||||
|
||||
pub fn generics(&self) -> &GenericParams {
|
||||
&self.type_params
|
||||
}
|
||||
}
|
||||
|
||||
impl Function {
|
||||
|
|
|
@ -58,6 +58,7 @@ impl FnSignature {
|
|||
args.push(type_ref);
|
||||
}
|
||||
}
|
||||
let type_params = db.generic_params(func.into());
|
||||
let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) {
|
||||
TypeRef::from_ast(type_ref)
|
||||
} else {
|
||||
|
@ -66,6 +67,7 @@ impl FnSignature {
|
|||
|
||||
let sig = FnSignature {
|
||||
name,
|
||||
type_params,
|
||||
args,
|
||||
ret_type,
|
||||
has_self_param,
|
||||
|
|
|
@ -49,8 +49,7 @@ impl GenericParams {
|
|||
Arc::new(generics)
|
||||
}
|
||||
|
||||
// FIXME: probably shouldnt be pub(crate)
|
||||
pub(crate) fn fill(&mut self, node: &impl TypeParamsOwner) {
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
self.fill_params(params)
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ mod tests;
|
|||
pub(crate) mod method_resolution;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::iter::repeat;
|
||||
use std::ops::Index;
|
||||
use std::sync::Arc;
|
||||
use std::{fmt, mem};
|
||||
|
@ -225,7 +226,7 @@ pub enum Ty {
|
|||
/// For display
|
||||
name: Name,
|
||||
/// Substitutions for the generic parameters of the type
|
||||
substs: Substs
|
||||
substs: Substs,
|
||||
},
|
||||
|
||||
/// A pointer to a function. Written as `fn() -> i32`.
|
||||
|
@ -543,11 +544,7 @@ impl Ty {
|
|||
name,
|
||||
substs,
|
||||
},
|
||||
Ty::FnDef { def, name, .. } => Ty::FnDef {
|
||||
def,
|
||||
name,
|
||||
substs,
|
||||
},
|
||||
Ty::FnDef { def, name, .. } => Ty::FnDef { def, name, substs },
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
@ -651,30 +648,10 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty {
|
|||
Ty::FnDef {
|
||||
def: f.into(),
|
||||
name,
|
||||
substs
|
||||
substs,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig {
|
||||
let signature = f.signature(db);
|
||||
let module = f.module(db);
|
||||
let impl_block = f.impl_block(db);
|
||||
let generics = f.generic_params(db);
|
||||
let input = signature
|
||||
.args()
|
||||
.iter()
|
||||
.map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr))
|
||||
.collect::<Vec<_>>();
|
||||
let output = Ty::from_hir(
|
||||
db,
|
||||
&module,
|
||||
impl_block.as_ref(),
|
||||
&generics,
|
||||
signature.ret_type(),
|
||||
);
|
||||
FnSig { input, output }
|
||||
}
|
||||
|
||||
fn make_substs(generics: &GenericParams) -> Substs {
|
||||
Substs(
|
||||
generics
|
||||
|
@ -946,9 +923,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
self.type_of_pat.insert(pat, ty);
|
||||
}
|
||||
|
||||
fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
|
||||
// TODO provide generics of function
|
||||
let generics = GenericParams::default();
|
||||
fn make_ty(&mut self, type_ref: &TypeRef, generics: &GenericParams) -> Ty {
|
||||
let ty = Ty::from_hir(
|
||||
self.db,
|
||||
&self.module,
|
||||
|
@ -1249,9 +1224,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
Ty::Tuple(ref tuple_args) => &**tuple_args,
|
||||
_ => &[],
|
||||
};
|
||||
let expectations_iter = expectations
|
||||
.into_iter()
|
||||
.chain(std::iter::repeat(&Ty::Unknown));
|
||||
let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown));
|
||||
|
||||
let inner_tys = args
|
||||
.iter()
|
||||
|
@ -1370,7 +1343,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
|
||||
for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
|
||||
let expected = if let Some(type_ref) = arg_type {
|
||||
let ty = self.make_ty(type_ref);
|
||||
let ty = self.make_ty(type_ref, &GenericParams::default());
|
||||
ty
|
||||
} else {
|
||||
Ty::Unknown
|
||||
|
@ -1386,22 +1359,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
// TODO: we should use turbofish hints like this:
|
||||
// f::<u32>(x)
|
||||
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
||||
// FIXME: so manu unnecessary clones
|
||||
let (param_tys, ret_ty) = match &callee_ty {
|
||||
Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()),
|
||||
Ty::FnDef { def, substs, .. } => {
|
||||
let fn_sig = def.signature(self.db);
|
||||
// TODO: get input and return types from the fn_sig.
|
||||
// it contains typerefs which we can make into proper tys
|
||||
|
||||
let sig = get_func_sig(self.db, *def);
|
||||
(
|
||||
sig.input
|
||||
.iter()
|
||||
.map(|ty| ty.clone().subst(&substs))
|
||||
.collect(),
|
||||
sig.output.clone().subst(&substs),
|
||||
)
|
||||
let ret_ty = self
|
||||
.make_ty(fn_sig.ret_type(), fn_sig.generics())
|
||||
.subst(&substs);
|
||||
let param_tys = fn_sig
|
||||
.args()
|
||||
.iter()
|
||||
.map(|type_ref| {
|
||||
self.make_ty(type_ref, fn_sig.generics()).subst(&substs)
|
||||
})
|
||||
.collect();
|
||||
(param_tys, ret_ty)
|
||||
}
|
||||
_ => {
|
||||
// not callable
|
||||
|
@ -1409,11 +1381,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
(Vec::new(), Ty::Unknown)
|
||||
}
|
||||
};
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
self.infer_expr(
|
||||
*arg,
|
||||
&Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
|
||||
);
|
||||
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
||||
for (arg, param) in args.iter().zip(param_iter) {
|
||||
self.infer_expr(*arg, &Expectation::has_type(param));
|
||||
}
|
||||
ret_ty
|
||||
}
|
||||
|
@ -1435,46 +1405,39 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
|
||||
Ty::FnPtr(sig) => {
|
||||
if sig.input.len() > 0 {
|
||||
(sig.input[0].clone(), sig.input[1..].iter().cloned().collect(), sig.output.clone())
|
||||
(
|
||||
sig.input[0].clone(),
|
||||
sig.input[1..].iter().cloned().collect(),
|
||||
sig.output.clone(),
|
||||
)
|
||||
} else {
|
||||
(Ty::Unknown, Vec::new(), sig.output.clone())
|
||||
}
|
||||
}
|
||||
Ty::FnDef { def, substs, .. } => {
|
||||
// TODO: fix deduplication with Expr::Call block above
|
||||
// TODO: fix the ridiculous number of clones
|
||||
let fn_sig = def.signature(self.db);
|
||||
// TODO: get input and return types from the fn_sig.
|
||||
// it contains typerefs which we can make into proper tys
|
||||
let ret_ty = self
|
||||
.make_ty(fn_sig.ret_type(), fn_sig.generics())
|
||||
.subst(&substs);
|
||||
|
||||
// check that len > 0
|
||||
let sig = get_func_sig(self.db, *def);
|
||||
if sig.input.len() > 0 {
|
||||
(
|
||||
sig.input[0].clone().subst(&substs),
|
||||
sig.input[1..]
|
||||
.iter()
|
||||
.map(|ty| ty.clone().subst(&substs))
|
||||
.collect(),
|
||||
sig.output.clone().subst(&substs),
|
||||
)
|
||||
if fn_sig.args().len() > 0 {
|
||||
let mut arg_iter = fn_sig.args().iter().map(|type_ref| {
|
||||
self.make_ty(type_ref, fn_sig.generics()).subst(&substs)
|
||||
});
|
||||
let receiver_ty = arg_iter.next().unwrap();
|
||||
(receiver_ty, arg_iter.collect(), ret_ty)
|
||||
} else {
|
||||
(Ty::Unknown, Vec::new(), sig.output.clone())
|
||||
(Ty::Unknown, Vec::new(), ret_ty)
|
||||
}
|
||||
}
|
||||
_ => (Ty::Unknown, Vec::new(), Ty::Unknown),
|
||||
};
|
||||
// TODO we would have to apply the autoderef/autoref steps here
|
||||
// to get the correct receiver type to unify...
|
||||
//
|
||||
// TODO: zip param_tys.chain(iter::repeat(Ty::Unknown)) above then its not so bad
|
||||
// that we clone
|
||||
self.unify(&expected_receiver_ty, &receiver_ty);
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
self.infer_expr(
|
||||
*arg,
|
||||
&Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)),
|
||||
);
|
||||
let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
|
||||
for (arg, param) in args.iter().zip(param_iter) {
|
||||
self.infer_expr(*arg, &Expectation::has_type(param));
|
||||
}
|
||||
ret_ty
|
||||
}
|
||||
|
@ -1558,7 +1521,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
let _inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||
let cast_ty = self.make_ty(type_ref);
|
||||
let cast_ty = self.make_ty(type_ref, &GenericParams::default());
|
||||
// TODO check the cast...
|
||||
cast_ty
|
||||
}
|
||||
|
@ -1672,7 +1635,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
} => {
|
||||
let decl_ty = type_ref
|
||||
.as_ref()
|
||||
.map(|tr| self.make_ty(tr))
|
||||
.map(|tr| self.make_ty(tr, &GenericParams::default()))
|
||||
.unwrap_or(Ty::Unknown);
|
||||
let decl_ty = self.insert_type_vars(decl_ty);
|
||||
let ty = if let Some(expr) = initializer {
|
||||
|
@ -1699,12 +1662,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
|
||||
fn collect_fn_signature(&mut self, signature: &FnSignature) {
|
||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||
let generics = signature.generics();
|
||||
for (type_ref, pat) in signature.args().iter().zip(body.params()) {
|
||||
let ty = self.make_ty(type_ref);
|
||||
let ty = self.make_ty(type_ref, generics);
|
||||
|
||||
self.infer_pat(*pat, &ty);
|
||||
}
|
||||
self.return_ty = self.make_ty(signature.ret_type());
|
||||
self.return_ty = self.make_ty(signature.ret_type(), generics);
|
||||
}
|
||||
|
||||
fn infer_body(&mut self) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
created: "2019-01-22T14:44:59.880187500+00:00"
|
||||
creator: insta@0.4.0
|
||||
created: "2019-01-25T23:18:54.943309491+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
---
|
||||
[14; 15) 'x': u32
|
||||
[22; 24) '{}': ()
|
||||
|
@ -10,7 +10,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
|||
[88; 89) 'a': u32
|
||||
[92; 108) 'unknow...nction': [unknown]
|
||||
[92; 110) 'unknow...tion()': u32
|
||||
[116; 125) 'takes_u32': fn(u32) -> ()
|
||||
[116; 125) 'takes_u32': fn takes_u32
|
||||
[116; 128) 'takes_u32(a)': ()
|
||||
[126; 127) 'a': u32
|
||||
[138; 139) 'b': i32
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
---
|
||||
created: "2019-01-22T14:44:59.880187500+00:00"
|
||||
creator: insta@0.4.0
|
||||
created: "2019-01-25T23:18:54.949540810+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
---
|
||||
[6; 7) 'x': bool
|
||||
[22; 34) '{ 0i32 }': i32
|
||||
|
@ -28,7 +28,7 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
|||
[174; 196) 'minus_...ONST_2': bool
|
||||
[189; 196) 'CONST_2': isize
|
||||
[206; 207) 'c': i32
|
||||
[210; 211) 'f': fn(bool) -> i32
|
||||
[210; 211) 'f': fn f
|
||||
[210; 219) 'f(z || y)': i32
|
||||
[210; 223) 'f(z || y) + 5': i32
|
||||
[212; 213) 'z': bool
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
---
|
||||
created: "2019-01-22T14:44:59.954958500+00:00"
|
||||
creator: insta@0.4.0
|
||||
created: "2019-01-25T23:18:54.962273460+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
---
|
||||
[10; 11) 't': [unknown]
|
||||
[21; 26) '{ t }': [unknown]
|
||||
[23; 24) 't': [unknown]
|
||||
[10; 11) 't': T
|
||||
[21; 26) '{ t }': T
|
||||
[23; 24) 't': T
|
||||
[38; 98) '{ ...(1); }': ()
|
||||
[44; 46) 'id': fn(T) -> T
|
||||
[44; 52) 'id(1u32)': T
|
||||
[44; 46) 'id': fn id<u32>
|
||||
[44; 52) 'id(1u32)': u32
|
||||
[47; 51) '1u32': u32
|
||||
[58; 68) 'id::<i128>': fn(T) -> T
|
||||
[58; 71) 'id::<i128>(1)': T
|
||||
[69; 70) '1': T
|
||||
[81; 82) 'x': T
|
||||
[90; 92) 'id': fn(T) -> T
|
||||
[90; 95) 'id(1)': T
|
||||
[93; 94) '1': T
|
||||
[58; 68) 'id::<i128>': fn id<i32>
|
||||
[58; 71) 'id::<i128>(1)': i32
|
||||
[69; 70) '1': i32
|
||||
[81; 82) 'x': u64
|
||||
[90; 92) 'id': fn id<u64>
|
||||
[90; 95) 'id(1)': u64
|
||||
[93; 94) '1': u64
|
||||
|
||||
|
|
|
@ -1,36 +1,36 @@
|
|||
---
|
||||
created: "2019-01-22T14:44:59.961936900+00:00"
|
||||
creator: insta@0.4.0
|
||||
created: "2019-01-25T23:18:54.978506051+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
---
|
||||
[53; 57) 'self': A<[unknown]>
|
||||
[65; 87) '{ ... }': [unknown]
|
||||
[75; 79) 'self': A<[unknown]>
|
||||
[75; 81) 'self.x': [unknown]
|
||||
[99; 100) 't': [unknown]
|
||||
[110; 115) '{ t }': [unknown]
|
||||
[112; 113) 't': [unknown]
|
||||
[99; 100) 't': T
|
||||
[110; 115) '{ t }': T
|
||||
[112; 113) 't': T
|
||||
[135; 261) '{ ....x() }': i128
|
||||
[146; 147) 'x': T
|
||||
[150; 151) '1': T
|
||||
[162; 163) 'y': T
|
||||
[166; 168) 'id': fn(T) -> T
|
||||
[166; 171) 'id(x)': T
|
||||
[169; 170) 'x': T
|
||||
[182; 183) 'a': A<T>
|
||||
[186; 200) 'A { x: id(y) }': A<T>
|
||||
[193; 195) 'id': fn(T) -> T
|
||||
[193; 198) 'id(y)': T
|
||||
[196; 197) 'y': T
|
||||
[211; 212) 'z': T
|
||||
[215; 217) 'id': fn(T) -> T
|
||||
[215; 222) 'id(a.x)': T
|
||||
[218; 219) 'a': A<T>
|
||||
[218; 221) 'a.x': T
|
||||
[233; 234) 'b': A<T>
|
||||
[237; 247) 'A { x: z }': A<T>
|
||||
[244; 245) 'z': T
|
||||
[254; 255) 'b': A<T>
|
||||
[146; 147) 'x': i32
|
||||
[150; 151) '1': i32
|
||||
[162; 163) 'y': i32
|
||||
[166; 168) 'id': fn id<i32>
|
||||
[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>
|
||||
[193; 198) 'id(y)': i32
|
||||
[196; 197) 'y': i32
|
||||
[211; 212) 'z': i32
|
||||
[215; 217) 'id': fn id<i32>
|
||||
[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>
|
||||
[254; 259) 'b.x()': i128
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
---
|
||||
created: "2019-01-22T14:44:59.975899500+00:00"
|
||||
creator: insta@0.4.0
|
||||
created: "2019-01-25T23:18:54.985011010+00:00"
|
||||
creator: insta@0.5.2
|
||||
expression: "&result"
|
||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
||||
source: crates/ra_hir/src/ty/tests.rs
|
||||
---
|
||||
[15; 20) '{ 1 }': u32
|
||||
[17; 18) '1': u32
|
||||
[48; 53) '{ 1 }': u32
|
||||
[50; 51) '1': u32
|
||||
[67; 91) '{ ...c(); }': ()
|
||||
[73; 74) 'a': fn() -> u32
|
||||
[73; 74) 'a': fn a
|
||||
[73; 76) 'a()': u32
|
||||
[82; 86) 'b::c': fn() -> u32
|
||||
[82; 86) 'b::c': fn c
|
||||
[82; 88) 'b::c()': u32
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue