aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/expr.rs4
-rw-r--r--crates/ra_hir_ty/src/infer.rs28
-rw-r--r--crates/ra_hir_ty/src/tests.rs17
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs41
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;
11use std::sync::Arc; 11use std::sync::Arc;
12 12
13use hir_def::{ 13use 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};
17use hir_expand::InFile; 22use hir_expand::InFile;
18use insta::assert_snapshot; 23use 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]
54fn self_in_struct_lit() {
55 assert_snapshot!(infer(
56 r#"
57//- /main.rs
58struct S<T> { x: T }
59
60impl 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]
74fn type_alias_in_struct_lit() {
75 assert_snapshot!(infer(
76 r#"
77//- /main.rs
78struct S<T> { x: T }
79
80type SS = S<u32>;
81
82fn 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]
54fn infer_ranges() { 95fn infer_ranges() {
55 let (db, pos) = TestDB::with_position( 96 let (db, pos) = TestDB::with_position(
56 r#" 97 r#"