diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/expr.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 28 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/simple.rs | 41 |
4 files changed, 81 insertions, 9 deletions
diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 22f24890d..d8cdf5266 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs | |||
@@ -100,7 +100,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
100 | } | 100 | } |
101 | let (_, source_map) = db.body_with_source_map(self.func.into()); | 101 | let (_, source_map) = db.body_with_source_map(self.func.into()); |
102 | 102 | ||
103 | if let Some(source_ptr) = source_map.expr_syntax(id) { | 103 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
104 | if let Some(expr) = source_ptr.value.left() { | 104 | if let Some(expr) = source_ptr.value.left() { |
105 | let root = source_ptr.file_syntax(db); | 105 | let root = source_ptr.file_syntax(db); |
106 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { | 106 | if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { |
@@ -145,7 +145,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
145 | if params.len() == 2 && params[0] == mismatch.actual { | 145 | if params.len() == 2 && params[0] == mismatch.actual { |
146 | let (_, source_map) = db.body_with_source_map(self.func.into()); | 146 | let (_, source_map) = db.body_with_source_map(self.func.into()); |
147 | 147 | ||
148 | if let Some(source_ptr) = source_map.expr_syntax(id) { | 148 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
149 | if let Some(expr) = source_ptr.value.left() { | 149 | if let Some(expr) = source_ptr.value.left() { |
150 | self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); | 150 | self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); |
151 | } | 151 | } |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 377f44fa7..39f144216 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -425,7 +425,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
425 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | 425 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
426 | // FIXME: this should resolve assoc items as well, see this example: | 426 | // FIXME: this should resolve assoc items as well, see this example: |
427 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 | 427 | // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 |
428 | match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { | 428 | return match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { |
429 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { | 429 | Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { |
430 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); | 430 | let substs = Ty::substs_from_path(&ctx, path, strukt.into()); |
431 | let ty = self.db.ty(strukt.into()); | 431 | let ty = self.db.ty(strukt.into()); |
@@ -438,7 +438,33 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
438 | let ty = self.insert_type_vars(ty.subst(&substs)); | 438 | let ty = self.insert_type_vars(ty.subst(&substs)); |
439 | (ty, Some(var.into())) | 439 | (ty, Some(var.into())) |
440 | } | 440 | } |
441 | Some(TypeNs::SelfType(impl_id)) => { | ||
442 | let generics = crate::utils::generics(self.db, impl_id.into()); | ||
443 | let substs = Substs::type_params_for_generics(&generics); | ||
444 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | ||
445 | let variant = ty_variant(&ty); | ||
446 | (ty, variant) | ||
447 | } | ||
448 | Some(TypeNs::TypeAliasId(it)) => { | ||
449 | let substs = Substs::build_for_def(self.db, it) | ||
450 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | ||
451 | .build(); | ||
452 | let ty = self.db.ty(it.into()).subst(&substs); | ||
453 | let variant = ty_variant(&ty); | ||
454 | (ty, variant) | ||
455 | } | ||
441 | Some(_) | None => (Ty::Unknown, None), | 456 | Some(_) | None => (Ty::Unknown, None), |
457 | }; | ||
458 | |||
459 | fn ty_variant(ty: &Ty) -> Option<VariantId> { | ||
460 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { | ||
461 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | ||
462 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | ||
463 | AdtId::EnumId(_) => { | ||
464 | // Error E0071, expected struct, variant or union type, found enum `Foo` | ||
465 | None | ||
466 | } | ||
467 | }) | ||
442 | } | 468 | } |
443 | } | 469 | } |
444 | 470 | ||
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 087edcc92..7e9547340 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -11,8 +11,13 @@ use std::fmt::Write; | |||
11 | use std::sync::Arc; | 11 | use std::sync::Arc; |
12 | 12 | ||
13 | use hir_def::{ | 13 | use hir_def::{ |
14 | body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, item_scope::ItemScope, | 14 | body::{BodySourceMap, SyntheticSyntax}, |
15 | keys, nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 15 | child_by_source::ChildBySource, |
16 | db::DefDatabase, | ||
17 | item_scope::ItemScope, | ||
18 | keys, | ||
19 | nameres::CrateDefMap, | ||
20 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | ||
16 | }; | 21 | }; |
17 | use hir_expand::InFile; | 22 | use hir_expand::InFile; |
18 | use insta::assert_snapshot; | 23 | use insta::assert_snapshot; |
@@ -67,20 +72,20 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
67 | 72 | ||
68 | for (pat, ty) in inference_result.type_of_pat.iter() { | 73 | for (pat, ty) in inference_result.type_of_pat.iter() { |
69 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 74 | let syntax_ptr = match body_source_map.pat_syntax(pat) { |
70 | Some(sp) => { | 75 | Ok(sp) => { |
71 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) | 76 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) |
72 | } | 77 | } |
73 | None => continue, | 78 | Err(SyntheticSyntax) => continue, |
74 | }; | 79 | }; |
75 | types.push((syntax_ptr, ty)); | 80 | types.push((syntax_ptr, ty)); |
76 | } | 81 | } |
77 | 82 | ||
78 | for (expr, ty) in inference_result.type_of_expr.iter() { | 83 | for (expr, ty) in inference_result.type_of_expr.iter() { |
79 | let syntax_ptr = match body_source_map.expr_syntax(expr) { | 84 | let syntax_ptr = match body_source_map.expr_syntax(expr) { |
80 | Some(sp) => { | 85 | Ok(sp) => { |
81 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) | 86 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) |
82 | } | 87 | } |
83 | None => continue, | 88 | Err(SyntheticSyntax) => continue, |
84 | }; | 89 | }; |
85 | types.push((syntax_ptr, ty)); | 90 | types.push((syntax_ptr, ty)); |
86 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { | 91 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { |
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 3803f5938..c140bd513 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs | |||
@@ -51,6 +51,47 @@ fn test() { | |||
51 | } | 51 | } |
52 | 52 | ||
53 | #[test] | 53 | #[test] |
54 | fn self_in_struct_lit() { | ||
55 | assert_snapshot!(infer( | ||
56 | r#" | ||
57 | //- /main.rs | ||
58 | struct S<T> { x: T } | ||
59 | |||
60 | impl S<u32> { | ||
61 | fn foo() { | ||
62 | Self { x: 1 }; | ||
63 | } | ||
64 | } | ||
65 | "#, | ||
66 | ), @r###" | ||
67 | [63; 93) '{ ... }': () | ||
68 | [73; 86) 'Self { x: 1 }': S<u32> | ||
69 | [83; 84) '1': u32 | ||
70 | "###); | ||
71 | } | ||
72 | |||
73 | #[test] | ||
74 | fn type_alias_in_struct_lit() { | ||
75 | assert_snapshot!(infer( | ||
76 | r#" | ||
77 | //- /main.rs | ||
78 | struct S<T> { x: T } | ||
79 | |||
80 | type SS = S<u32>; | ||
81 | |||
82 | fn foo() { | ||
83 | SS { x: 1 }; | ||
84 | } | ||
85 | |||
86 | "#, | ||
87 | ), @r###" | ||
88 | [64; 84) '{ ...1 }; }': () | ||
89 | [70; 81) 'SS { x: 1 }': S<u32> | ||
90 | [78; 79) '1': u32 | ||
91 | "###); | ||
92 | } | ||
93 | |||
94 | #[test] | ||
54 | fn infer_ranges() { | 95 | fn infer_ranges() { |
55 | let (db, pos) = TestDB::with_position( | 96 | let (db, pos) = TestDB::with_position( |
56 | r#" | 97 | r#" |