From 619a8185a607b216c64b58d230c3949ccef98a37 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 7 Sep 2019 21:03:03 +0200 Subject: Give closures types --- crates/ra_hir/src/code_model.rs | 20 ++++++++++++++++++++ crates/ra_hir/src/ty.rs | 23 ++++++++++++++++++++++- crates/ra_hir/src/ty/infer.rs | 22 ++++++++++++++++++---- crates/ra_hir/src/ty/tests.rs | 30 ++++++++++++++---------------- crates/ra_hir/src/ty/traits/chalk.rs | 4 ++++ 5 files changed, 78 insertions(+), 21 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 12399c6ac..99c247a0b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -551,6 +551,14 @@ impl DefWithBody { DefWithBody::Static(s) => s.resolver(db), } } + + pub(crate) fn krate(self, db: &impl HirDatabase) -> Option { + 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 { + 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 { + self.module(db).krate(db) + } + pub fn data(self, db: &impl HirDatabase) -> Arc { db.const_data(self) } @@ -824,6 +840,10 @@ impl Static { self.id.module(db) } + pub fn krate(self, db: &impl DefDatabase) -> Option { + self.module(db).krate(db) + } + pub fn data(self, db: &impl HirDatabase) -> Arc { db.static_data(self) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 36bfb10ce..e6ecbe1ea 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -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)`. 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(()) } diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 81a8623bf..c04f2a0c4 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -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()); diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 3ac1fbdd5..eb8770ec4 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -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 [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 [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 [264; 265) 'x': Option [264; 277) 'x.map(|_v| 1)': Option - [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 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 diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 462156021..34e623931 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs @@ -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, -- cgit v1.2.3