From e837df84792d2cbf5c606788c7cab7ea4d1829d0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 10 Feb 2021 14:41:54 +0100 Subject: infer: update resolver when descending into block --- crates/hir_ty/src/infer/expr.rs | 36 ++++++++++++++++++++---------------- crates/hir_ty/src/tests/simple.rs | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 12f1591c8..d05c715e7 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -137,24 +137,28 @@ impl<'a> InferenceContext<'a> { self.coerce_merge_branch(&then_ty, &else_ty) } - Expr::Block { statements, tail, label, id: _ } => match label { - Some(_) => { - let break_ty = self.table.new_type_var(); - self.breakables.push(BreakableContext { - may_break: false, - break_ty: break_ty.clone(), - label: label.map(|label| self.body[label].name.clone()), - }); - let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); - let ctxt = self.breakables.pop().expect("breakable stack broken"); - if ctxt.may_break { - ctxt.break_ty - } else { - ty + Expr::Block { statements, tail, label, id: _ } => { + self.resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); + match label { + Some(_) => { + let break_ty = self.table.new_type_var(); + self.breakables.push(BreakableContext { + may_break: false, + break_ty: break_ty.clone(), + label: label.map(|label| self.body[label].name.clone()), + }); + let ty = + self.infer_block(statements, *tail, &Expectation::has_type(break_ty)); + let ctxt = self.breakables.pop().expect("breakable stack broken"); + if ctxt.may_break { + ctxt.break_ty + } else { + ty + } } + None => self.infer_block(statements, *tail, expected), } - None => self.infer_block(statements, *tail, expected), - }, + } Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), Expr::TryBlock { body } => { let _inner = self.infer_expr(*body, expected); diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 16682f76f..ab21332fb 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2415,3 +2415,22 @@ fn infer_const_params() { "#]], ); } + +#[test] +fn infer_inner_type() { + check_infer(r#" + fn foo() { + struct S { field: u32 } + let s = S { field: 0 }; + let f = s.field; + } + "#, expect![[r#" + 9..89 '{ ...eld; }': () + 47..48 's': S + 51..65 'S { field: 0 }': S + 62..63 '0': u32 + 75..76 'f': u32 + 79..80 's': S + 79..86 's.field': u32 + "#]]); +} -- cgit v1.2.3 From 244d8e37f1cf42e30d3b668dfb088813e54adee2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 10 Feb 2021 14:48:52 +0100 Subject: Update fixed tests --- crates/hir_ty/src/diagnostics/match_check.rs | 29 ++++++++++++++-------------- crates/hir_ty/src/tests/simple.rs | 9 ++++++--- crates/ide/src/inlay_hints.rs | 1 + 3 files changed, 21 insertions(+), 18 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index fbe760c39..1c1423fbf 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs @@ -1495,6 +1495,20 @@ fn main(f: Foo) { ); } + #[test] + fn internal_or() { + check_diagnostics( + r#" +fn main() { + enum Either { A(bool), B } + match Either::B { + //^^^^^^^^^ Missing match arm + Either::A(true | false) => (), + } +} +"#, + ); + } mod false_negatives { //! The implementation of match checking here is a work in progress. As we roll this out, we //! prefer false negatives to false positives (ideally there would be no false positives). This @@ -1518,21 +1532,6 @@ fn main() { 11..20 => (), } } -"#, - ); - } - - #[test] - fn internal_or() { - // We do not currently handle patterns with internal `or`s. - check_diagnostics( - r#" -fn main() { - enum Either { A(bool), B } - match Either::B { - Either::A(true | false) => (), - } -} "#, ); } diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index ab21332fb..b364c2e58 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2418,13 +2418,15 @@ fn infer_const_params() { #[test] fn infer_inner_type() { - check_infer(r#" + check_infer( + r#" fn foo() { struct S { field: u32 } let s = S { field: 0 }; let f = s.field; } - "#, expect![[r#" + "#, + expect![[r#" 9..89 '{ ...eld; }': () 47..48 's': S 51..65 'S { field: 0 }': S @@ -2432,5 +2434,6 @@ fn infer_inner_type() { 75..76 'f': u32 79..80 's': S 79..86 's.field': u32 - "#]]); + "#]], + ); } diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index 2f37c8040..42d0a38e8 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -654,6 +654,7 @@ fn main() { let test = "test"; //^^^^ &str let test = InnerStruct {}; + //^^^^ InnerStruct let test = unresolved(); -- cgit v1.2.3 From a00fa0c06f70a377279ae77a01f19b05b3cb7437 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 10 Feb 2021 15:12:45 +0100 Subject: Put the old resolver back --- crates/hir_ty/src/infer/expr.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index d05c715e7..cb59a6937 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs @@ -138,8 +138,11 @@ impl<'a> InferenceContext<'a> { self.coerce_merge_branch(&then_ty, &else_ty) } Expr::Block { statements, tail, label, id: _ } => { - self.resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr); - match label { + let old_resolver = mem::replace( + &mut self.resolver, + resolver_for_expr(self.db.upcast(), self.owner, tgt_expr), + ); + let ty = match label { Some(_) => { let break_ty = self.table.new_type_var(); self.breakables.push(BreakableContext { @@ -157,7 +160,9 @@ impl<'a> InferenceContext<'a> { } } None => self.infer_block(statements, *tail, expected), - } + }; + self.resolver = old_resolver; + ty } Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected), Expr::TryBlock { body } => { -- cgit v1.2.3 From 3c5734712a074a5bb3100dbec8b690e60b5beac0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 10 Feb 2021 15:54:21 +0100 Subject: Add more tests --- crates/hir_ty/src/tests/simple.rs | 41 +++++++++++++++++++++++++------ crates/hir_ty/src/tests/traits.rs | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) (limited to 'crates') diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index b364c2e58..20ceb7415 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs @@ -2427,13 +2427,38 @@ fn infer_inner_type() { } "#, expect![[r#" - 9..89 '{ ...eld; }': () - 47..48 's': S - 51..65 'S { field: 0 }': S - 62..63 '0': u32 - 75..76 'f': u32 - 79..80 's': S - 79..86 's.field': u32 - "#]], + 9..89 '{ ...eld; }': () + 47..48 's': S + 51..65 'S { field: 0 }': S + 62..63 '0': u32 + 75..76 'f': u32 + 79..80 's': S + 79..86 's.field': u32 + "#]], + ); +} + +#[test] +fn infer_nested_inner_type() { + check_infer( + r#" + fn foo() { + { + let s = S { field: 0 }; + let f = s.field; + } + struct S { field: u32 } + } + "#, + expect![[r#" + 9..109 '{ ...32 } }': () + 15..79 '{ ... }': () + 29..30 's': S + 33..47 'S { field: 0 }': S + 44..45 '0': u32 + 61..62 'f': u32 + 65..66 's': S + 65..72 's.field': u32 + "#]], ); } diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index e5a3f95a6..e030f4a97 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -3151,3 +3151,54 @@ fn test() { "#, ); } + +#[test] +fn inner_use() { + check_types( + r#" +mod m { + pub trait Tr { + fn method(&self) -> u8 { 0 } + } + + impl Tr for () {} +} + +fn f() { + use m::Tr; + + ().method(); + //^^^^^^^^^^^ u8 +} + "#, + ); +} + +#[test] +fn inner_use_in_block() { + check_types( + r#" +mod m { + pub trait Tr { + fn method(&self) -> u8 { 0 } + } + + impl Tr for () {} +} + +fn f() { + { + use m::Tr; + + ().method(); + //^^^^^^^^^^^ u8 + } + + { + ().method(); + //^^^^^^^^^^^ {unknown} + } +} + "#, + ); +} -- cgit v1.2.3