Give closures types
This commit is contained in:
parent
36fb3f53d7
commit
619a8185a6
@ -551,6 +551,14 @@ pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
|
||||
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 @@ pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
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 @@ pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
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 @@ pub fn module(self, db: &impl DefDatabase) -> Module {
|
||||
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)
|
||||
}
|
||||
|
@ -16,7 +16,10 @@
|
||||
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 @@ fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> {
|
||||
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 @@ fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
|
||||
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(())
|
||||
}
|
||||
|
@ -885,18 +885,32 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
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());
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user