mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Give closures types
This commit is contained in:
parent
36fb3f53d7
commit
619a8185a6
5 changed files with 78 additions and 21 deletions
|
@ -551,6 +551,14 @@ impl DefWithBody {
|
||||||
DefWithBody::Static(s) => s.resolver(db),
|
DefWithBody::Static(s) => s.resolver(db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
|
||||||
|
match self {
|
||||||
|
DefWithBody::Const(c) => c.krate(db),
|
||||||
|
DefWithBody::Function(f) => f.krate(db),
|
||||||
|
DefWithBody::Static(s) => s.krate(db),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait HasBody: Copy {
|
pub trait HasBody: Copy {
|
||||||
|
@ -671,6 +679,10 @@ impl Function {
|
||||||
self.id.module(db)
|
self.id.module(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||||
|
self.module(db).krate(db)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn name(self, db: &impl HirDatabase) -> Name {
|
pub fn name(self, db: &impl HirDatabase) -> Name {
|
||||||
self.data(db).name.clone()
|
self.data(db).name.clone()
|
||||||
}
|
}
|
||||||
|
@ -745,6 +757,10 @@ impl Const {
|
||||||
self.id.module(db)
|
self.id.module(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||||
|
self.module(db).krate(db)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
|
pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
|
||||||
db.const_data(self)
|
db.const_data(self)
|
||||||
}
|
}
|
||||||
|
@ -824,6 +840,10 @@ impl Static {
|
||||||
self.id.module(db)
|
self.id.module(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
|
||||||
|
self.module(db).krate(db)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
|
pub fn data(self, db: &impl HirDatabase) -> Arc<ConstData> {
|
||||||
db.static_data(self)
|
db.static_data(self)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,10 @@ use std::ops::Deref;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fmt, mem};
|
use std::{fmt, mem};
|
||||||
|
|
||||||
use crate::{db::HirDatabase, type_ref::Mutability, Adt, GenericParams, Name, Trait, TypeAlias};
|
use crate::{
|
||||||
|
db::HirDatabase, expr::ExprId, type_ref::Mutability, Adt, DefWithBody, GenericParams, Name,
|
||||||
|
Trait, TypeAlias,
|
||||||
|
};
|
||||||
use display::{HirDisplay, HirFormatter};
|
use display::{HirDisplay, HirFormatter};
|
||||||
|
|
||||||
pub(crate) use autoderef::autoderef;
|
pub(crate) use autoderef::autoderef;
|
||||||
|
@ -100,6 +103,12 @@ pub enum TypeCtor {
|
||||||
/// couldn't find a better representation. In that case, we generate
|
/// couldn't find a better representation. In that case, we generate
|
||||||
/// an **application type** like `(Iterator::Item)<T>`.
|
/// an **application type** like `(Iterator::Item)<T>`.
|
||||||
AssociatedType(TypeAlias),
|
AssociatedType(TypeAlias),
|
||||||
|
|
||||||
|
/// The type of a specific closure.
|
||||||
|
///
|
||||||
|
/// The closure signature is stored in a `FnPtr` type in the first type
|
||||||
|
/// parameter.
|
||||||
|
Closure { def: DefWithBody, expr: ExprId },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A nominal type with (maybe 0) type parameters. This might be a primitive
|
/// A nominal type with (maybe 0) type parameters. This might be a primitive
|
||||||
|
@ -481,6 +490,10 @@ impl Ty {
|
||||||
let sig = db.callable_item_signature(def);
|
let sig = db.callable_item_signature(def);
|
||||||
Some(sig.subst(&a_ty.parameters))
|
Some(sig.subst(&a_ty.parameters))
|
||||||
}
|
}
|
||||||
|
TypeCtor::Closure { .. } => {
|
||||||
|
let sig_param = &a_ty.parameters[0];
|
||||||
|
sig_param.callable_sig(db)
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -720,6 +733,14 @@ impl HirDisplay for ApplicationTy {
|
||||||
write!(f, ">")?;
|
write!(f, ">")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TypeCtor::Closure { .. } => {
|
||||||
|
let sig = self.parameters[0]
|
||||||
|
.callable_sig(f.db)
|
||||||
|
.expect("first closure parameter should contain signature");
|
||||||
|
write!(f, "|")?;
|
||||||
|
f.write_joined(sig.params(), ", ")?;
|
||||||
|
write!(f, "| -> {}", sig.ret().display(f.db))?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -885,18 +885,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
Expr::Lambda { body, args, arg_types } => {
|
Expr::Lambda { body, args, arg_types } => {
|
||||||
assert_eq!(args.len(), arg_types.len());
|
assert_eq!(args.len(), arg_types.len());
|
||||||
|
|
||||||
|
let mut sig_tys = Vec::new();
|
||||||
|
|
||||||
for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
|
for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
|
||||||
let expected = if let Some(type_ref) = arg_type {
|
let expected = if let Some(type_ref) = arg_type {
|
||||||
self.make_ty(type_ref)
|
self.make_ty(type_ref)
|
||||||
} else {
|
} else {
|
||||||
Ty::Unknown
|
Ty::Unknown
|
||||||
};
|
};
|
||||||
self.infer_pat(*arg_pat, &expected, BindingMode::default());
|
let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default());
|
||||||
|
sig_tys.push(arg_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: infer lambda type etc.
|
// add return type
|
||||||
let _body_ty = self.infer_expr(*body, &Expectation::none());
|
let ret_ty = self.new_type_var();
|
||||||
Ty::Unknown
|
sig_tys.push(ret_ty.clone());
|
||||||
|
let sig_ty = Ty::apply(
|
||||||
|
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
|
||||||
|
sig_tys.into(),
|
||||||
|
);
|
||||||
|
let closure_ty = Ty::apply_one(
|
||||||
|
TypeCtor::Closure { def: self.body.owner(), expr: tgt_expr },
|
||||||
|
sig_ty,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.infer_expr(*body, &Expectation::has_type(ret_ty));
|
||||||
|
closure_ty
|
||||||
}
|
}
|
||||||
Expr::Call { callee, args } => {
|
Expr::Call { callee, args } => {
|
||||||
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
||||||
|
|
|
@ -1077,7 +1077,6 @@ fn test(x: &i32) {
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
@r###"
|
@r###"
|
||||||
|
|
||||||
[9; 10) 'x': &i32
|
[9; 10) 'x': &i32
|
||||||
[18; 369) '{ ...o_x; }': ()
|
[18; 369) '{ ...o_x; }': ()
|
||||||
[28; 29) 'y': &i32
|
[28; 29) 'y': &i32
|
||||||
|
@ -1107,8 +1106,8 @@ fn test(x: &i32) {
|
||||||
[177; 205) '{ ... }': ()
|
[177; 205) '{ ... }': ()
|
||||||
[191; 192) 'h': {unknown}
|
[191; 192) 'h': {unknown}
|
||||||
[195; 198) 'val': {unknown}
|
[195; 198) 'val': {unknown}
|
||||||
[215; 221) 'lambda': {unknown}
|
[215; 221) 'lambda': |u64, u64, i32| -> i32
|
||||||
[224; 256) '|a: u6...b; c }': {unknown}
|
[224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32
|
||||||
[225; 226) 'a': u64
|
[225; 226) 'a': u64
|
||||||
[233; 234) 'b': u64
|
[233; 234) 'b': u64
|
||||||
[236; 237) 'c': i32
|
[236; 237) 'c': i32
|
||||||
|
@ -2836,12 +2835,11 @@ fn test() -> u64 {
|
||||||
}
|
}
|
||||||
"#),
|
"#),
|
||||||
@r###"
|
@r###"
|
||||||
|
|
||||||
[44; 102) '{ ...0(2) }': u64
|
[44; 102) '{ ...0(2) }': u64
|
||||||
[54; 55) 'a': S
|
[54; 55) 'a': S
|
||||||
[58; 59) 'S': S(fn(u32) -> u64) -> S
|
[58; 59) 'S': S(fn(u32) -> u64) -> S
|
||||||
[58; 68) 'S(|i| 2*i)': S
|
[58; 68) 'S(|i| 2*i)': S
|
||||||
[60; 67) '|i| 2*i': fn(u32) -> u64
|
[60; 67) '|i| 2*i': |i32| -> i32
|
||||||
[61; 62) 'i': i32
|
[61; 62) 'i': i32
|
||||||
[64; 65) '2': i32
|
[64; 65) '2': i32
|
||||||
[64; 67) '2*i': i32
|
[64; 67) '2*i': i32
|
||||||
|
@ -4019,20 +4017,20 @@ fn test() {
|
||||||
[188; 192) '1i32': i32
|
[188; 192) '1i32': i32
|
||||||
[199; 200) 'x': Option<i32>
|
[199; 200) 'x': Option<i32>
|
||||||
[199; 215) 'x.map(...v + 1)': {unknown}
|
[199; 215) 'x.map(...v + 1)': {unknown}
|
||||||
[205; 214) '|v| v + 1': {unknown}
|
[205; 214) '|v| v + 1': |{unknown}| -> i32
|
||||||
[206; 207) 'v': {unknown}
|
[206; 207) 'v': {unknown}
|
||||||
[209; 210) 'v': {unknown}
|
[209; 210) 'v': {unknown}
|
||||||
[209; 214) 'v + 1': i32
|
[209; 214) 'v + 1': i32
|
||||||
[213; 214) '1': i32
|
[213; 214) '1': i32
|
||||||
[221; 222) 'x': Option<i32>
|
[221; 222) 'x': Option<i32>
|
||||||
[221; 237) 'x.map(... 1u64)': {unknown}
|
[221; 237) 'x.map(... 1u64)': {unknown}
|
||||||
[227; 236) '|_v| 1u64': {unknown}
|
[227; 236) '|_v| 1u64': |{unknown}| -> u64
|
||||||
[228; 230) '_v': {unknown}
|
[228; 230) '_v': {unknown}
|
||||||
[232; 236) '1u64': u64
|
[232; 236) '1u64': u64
|
||||||
[247; 248) 'y': Option<i64>
|
[247; 248) 'y': Option<i64>
|
||||||
[264; 265) 'x': Option<i32>
|
[264; 265) 'x': Option<i32>
|
||||||
[264; 277) 'x.map(|_v| 1)': Option<i64>
|
[264; 277) 'x.map(|_v| 1)': Option<i64>
|
||||||
[270; 276) '|_v| 1': {unknown}
|
[270; 276) '|_v| 1': |{unknown}| -> i32
|
||||||
[271; 273) '_v': {unknown}
|
[271; 273) '_v': {unknown}
|
||||||
[275; 276) '1': i32
|
[275; 276) '1': i32
|
||||||
"###
|
"###
|
||||||
|
@ -4060,17 +4058,17 @@ fn test<F: FnOnce(u32) -> u64>(f: F) {
|
||||||
[85; 86) 'f': F
|
[85; 86) 'f': F
|
||||||
[85; 89) 'f(1)': {unknown}
|
[85; 89) 'f(1)': {unknown}
|
||||||
[87; 88) '1': i32
|
[87; 88) '1': i32
|
||||||
[99; 100) 'g': {unknown}
|
[99; 100) 'g': |u64| -> i32
|
||||||
[103; 112) '|v| v + 1': {unknown}
|
[103; 112) '|v| v + 1': |u64| -> i32
|
||||||
[104; 105) 'v': {unknown}
|
[104; 105) 'v': u64
|
||||||
[107; 108) 'v': {unknown}
|
[107; 108) 'v': u64
|
||||||
[107; 112) 'v + 1': i32
|
[107; 112) 'v + 1': i32
|
||||||
[111; 112) '1': i32
|
[111; 112) '1': i32
|
||||||
[118; 119) 'g': {unknown}
|
[118; 119) 'g': |u64| -> i32
|
||||||
[118; 125) 'g(1u64)': {unknown}
|
[118; 125) 'g(1u64)': i32
|
||||||
[120; 124) '1u64': u64
|
[120; 124) '1u64': u64
|
||||||
[135; 136) 'h': {unknown}
|
[135; 136) 'h': |u128| -> u128
|
||||||
[139; 152) '|v| 1u128 + v': {unknown}
|
[139; 152) '|v| 1u128 + v': |u128| -> u128
|
||||||
[140; 141) 'v': u128
|
[140; 141) 'v': u128
|
||||||
[143; 148) '1u128': u128
|
[143; 148) '1u128': u128
|
||||||
[143; 152) '1u128 + v': u128
|
[143; 152) '1u128 + v': u128
|
||||||
|
|
|
@ -571,6 +571,10 @@ pub(crate) fn struct_datum_query(
|
||||||
type_alias.krate(db) != Some(krate),
|
type_alias.krate(db) != Some(krate),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
TypeCtor::Closure { def, .. } => {
|
||||||
|
let upstream = def.krate(db) != Some(krate);
|
||||||
|
(1, vec![], upstream)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let flags = chalk_rust_ir::StructFlags {
|
let flags = chalk_rust_ir::StructFlags {
|
||||||
upstream,
|
upstream,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue