Give closures types

This commit is contained in:
Florian Diebold 2019-09-07 21:03:03 +02:00
parent 36fb3f53d7
commit 619a8185a6
5 changed files with 78 additions and 21 deletions

View file

@ -551,6 +551,14 @@ impl DefWithBody {
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 {
@ -671,6 +679,10 @@ impl Function {
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 {
self.data(db).name.clone()
}
@ -745,6 +757,10 @@ impl Const {
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> {
db.const_data(self)
}
@ -824,6 +840,10 @@ impl Static {
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> {
db.static_data(self)
}

View file

@ -16,7 +16,10 @@ use std::ops::Deref;
use std::sync::Arc;
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};
pub(crate) use autoderef::autoderef;
@ -100,6 +103,12 @@ pub enum TypeCtor {
/// couldn't find a better representation. In that case, we generate
/// an **application type** like `(Iterator::Item)<T>`.
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
@ -481,6 +490,10 @@ impl Ty {
let sig = db.callable_item_signature(def);
Some(sig.subst(&a_ty.parameters))
}
TypeCtor::Closure { .. } => {
let sig_param = &a_ty.parameters[0];
sig_param.callable_sig(db)
}
_ => None,
},
_ => None,
@ -720,6 +733,14 @@ impl HirDisplay for ApplicationTy {
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(())
}

View file

@ -885,18 +885,32 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Expr::Lambda { body, args, arg_types } => {
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()) {
let expected = if let Some(type_ref) = arg_type {
self.make_ty(type_ref)
} else {
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.
let _body_ty = self.infer_expr(*body, &Expectation::none());
Ty::Unknown
// add return type
let ret_ty = self.new_type_var();
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 } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none());

View file

@ -1077,7 +1077,6 @@ fn test(x: &i32) {
}
"#),
@r###"
[9; 10) 'x': &i32
[18; 369) '{ ...o_x; }': ()
[28; 29) 'y': &i32
@ -1107,8 +1106,8 @@ fn test(x: &i32) {
[177; 205) '{ ... }': ()
[191; 192) 'h': {unknown}
[195; 198) 'val': {unknown}
[215; 221) 'lambda': {unknown}
[224; 256) '|a: u6...b; c }': {unknown}
[215; 221) 'lambda': |u64, u64, i32| -> i32
[224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32
[225; 226) 'a': u64
[233; 234) 'b': u64
[236; 237) 'c': i32
@ -2836,12 +2835,11 @@ fn test() -> u64 {
}
"#),
@r###"
[44; 102) '{ ...0(2) }': u64
[54; 55) 'a': S
[58; 59) 'S': S(fn(u32) -> u64) -> 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
[64; 65) '2': i32
[64; 67) '2*i': i32
@ -4019,20 +4017,20 @@ fn test() {
[188; 192) '1i32': i32
[199; 200) 'x': Option<i32>
[199; 215) 'x.map(...v + 1)': {unknown}
[205; 214) '|v| v + 1': {unknown}
[205; 214) '|v| v + 1': |{unknown}| -> i32
[206; 207) 'v': {unknown}
[209; 210) 'v': {unknown}
[209; 214) 'v + 1': i32
[213; 214) '1': i32
[221; 222) 'x': Option<i32>
[221; 237) 'x.map(... 1u64)': {unknown}
[227; 236) '|_v| 1u64': {unknown}
[227; 236) '|_v| 1u64': |{unknown}| -> u64
[228; 230) '_v': {unknown}
[232; 236) '1u64': u64
[247; 248) 'y': Option<i64>
[264; 265) 'x': Option<i32>
[264; 277) 'x.map(|_v| 1)': Option<i64>
[270; 276) '|_v| 1': {unknown}
[270; 276) '|_v| 1': |{unknown}| -> i32
[271; 273) '_v': {unknown}
[275; 276) '1': i32
"###
@ -4060,17 +4058,17 @@ fn test<F: FnOnce(u32) -> u64>(f: F) {
[85; 86) 'f': F
[85; 89) 'f(1)': {unknown}
[87; 88) '1': i32
[99; 100) 'g': {unknown}
[103; 112) '|v| v + 1': {unknown}
[104; 105) 'v': {unknown}
[107; 108) 'v': {unknown}
[99; 100) 'g': |u64| -> i32
[103; 112) '|v| v + 1': |u64| -> i32
[104; 105) 'v': u64
[107; 108) 'v': u64
[107; 112) 'v + 1': i32
[111; 112) '1': i32
[118; 119) 'g': {unknown}
[118; 125) 'g(1u64)': {unknown}
[118; 119) 'g': |u64| -> i32
[118; 125) 'g(1u64)': i32
[120; 124) '1u64': u64
[135; 136) 'h': {unknown}
[139; 152) '|v| 1u128 + v': {unknown}
[135; 136) 'h': |u128| -> u128
[139; 152) '|v| 1u128 + v': |u128| -> u128
[140; 141) 'v': u128
[143; 148) '1u128': u128
[143; 152) '1u128 + v': u128

View file

@ -571,6 +571,10 @@ pub(crate) fn struct_datum_query(
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 {
upstream,