From 8c078a01641518a6b093922d4b1d27d1a98bad08 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Wed, 11 Sep 2019 23:53:41 +0800 Subject: Infer box expression --- crates/ra_hir/src/ty/infer.rs | 26 ++++++++++++++++++++++++++ crates/ra_hir/src/ty/tests.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 9244ff3cb..1057bbbec 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -1259,6 +1259,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let inner_ty = self.infer_expr(*expr, &expectation); Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } + Expr::Box { expr } => { + let inner_ty = self.infer_expr(*expr, &Expectation::none()); + if let Some(box_) = self.resolve_boxed_box() { + Ty::apply_one(TypeCtor::Adt(box_), inner_ty) + } else { + Ty::Unknown + } + } Expr::UnaryOp { expr, op } => { let inner_ty = self.infer_expr(*expr, &Expectation::none()); match op { @@ -1499,6 +1507,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { _ => None, } } + + fn resolve_boxed_box(&self) -> Option { + let boxed_box_path = Path { + kind: PathKind::Abs, + segments: vec![ + PathSegment { name: name::STD, args_and_bindings: None }, + PathSegment { name: name::BOXED_MOD, args_and_bindings: None }, + PathSegment { name: name::BOX_TYPE, args_and_bindings: None }, + ], + }; + + match self.resolver.resolve_path_segments(self.db, &boxed_box_path).into_fully_resolved() { + PerNs { types: Some(Def(ModuleDef::Struct(struct_))), .. } => { + Some(AdtDef::Struct(struct_)) + } + _ => None, + } + } } /// The ID of a type variable. diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 869ae13f1..9a5f6949d 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -55,6 +55,37 @@ mod future { assert_eq!("u64", type_at_pos(&db, pos)); } +#[test] +fn infer_box() { + let (mut db, pos) = MockDatabase::with_position( + r#" +//- /main.rs + +fn test() { + let x = box 1; + let t = (x, box x, box &1, box [1]); + t<|>; +} + +//- /std.rs +#[prelude_import] use prelude::*; +mod prelude {} + +mod boxed { + pub struct Box { + inner: *mut T, + } +} + +"#, + ); + db.set_crate_graph_from_fixture(crate_graph! { + "main": ("/main.rs", ["std"]), + "std": ("/std.rs", []), + }); + assert_eq!("(Box, Box>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos)); +} + #[test] fn infer_try() { let (mut db, pos) = MockDatabase::with_position( -- cgit v1.2.3