Skip to content

Commit 7ec0343

Browse files
Merge #7627
7627: infer: update resolver when descending into block r=jonas-schievink a=jonas-schievink Co-authored-by: Jonas Schievink <[email protected]>
2 parents 82a1b91 + 3c57347 commit 7ec0343

File tree

5 files changed

+139
-32
lines changed

5 files changed

+139
-32
lines changed

crates/hir_ty/src/diagnostics/match_check.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -1495,6 +1495,20 @@ fn main(f: Foo) {
14951495
);
14961496
}
14971497

1498+
#[test]
1499+
fn internal_or() {
1500+
check_diagnostics(
1501+
r#"
1502+
fn main() {
1503+
enum Either { A(bool), B }
1504+
match Either::B {
1505+
//^^^^^^^^^ Missing match arm
1506+
Either::A(true | false) => (),
1507+
}
1508+
}
1509+
"#,
1510+
);
1511+
}
14981512
mod false_negatives {
14991513
//! The implementation of match checking here is a work in progress. As we roll this out, we
15001514
//! prefer false negatives to false positives (ideally there would be no false positives). This
@@ -1518,21 +1532,6 @@ fn main() {
15181532
11..20 => (),
15191533
}
15201534
}
1521-
"#,
1522-
);
1523-
}
1524-
1525-
#[test]
1526-
fn internal_or() {
1527-
// We do not currently handle patterns with internal `or`s.
1528-
check_diagnostics(
1529-
r#"
1530-
fn main() {
1531-
enum Either { A(bool), B }
1532-
match Either::B {
1533-
Either::A(true | false) => (),
1534-
}
1535-
}
15361535
"#,
15371536
);
15381537
}

crates/hir_ty/src/infer/expr.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,33 @@ impl<'a> InferenceContext<'a> {
137137

138138
self.coerce_merge_branch(&then_ty, &else_ty)
139139
}
140-
Expr::Block { statements, tail, label, id: _ } => match label {
141-
Some(_) => {
142-
let break_ty = self.table.new_type_var();
143-
self.breakables.push(BreakableContext {
144-
may_break: false,
145-
break_ty: break_ty.clone(),
146-
label: label.map(|label| self.body[label].name.clone()),
147-
});
148-
let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty));
149-
let ctxt = self.breakables.pop().expect("breakable stack broken");
150-
if ctxt.may_break {
151-
ctxt.break_ty
152-
} else {
153-
ty
140+
Expr::Block { statements, tail, label, id: _ } => {
141+
let old_resolver = mem::replace(
142+
&mut self.resolver,
143+
resolver_for_expr(self.db.upcast(), self.owner, tgt_expr),
144+
);
145+
let ty = match label {
146+
Some(_) => {
147+
let break_ty = self.table.new_type_var();
148+
self.breakables.push(BreakableContext {
149+
may_break: false,
150+
break_ty: break_ty.clone(),
151+
label: label.map(|label| self.body[label].name.clone()),
152+
});
153+
let ty =
154+
self.infer_block(statements, *tail, &Expectation::has_type(break_ty));
155+
let ctxt = self.breakables.pop().expect("breakable stack broken");
156+
if ctxt.may_break {
157+
ctxt.break_ty
158+
} else {
159+
ty
160+
}
154161
}
155-
}
156-
None => self.infer_block(statements, *tail, expected),
157-
},
162+
None => self.infer_block(statements, *tail, expected),
163+
};
164+
self.resolver = old_resolver;
165+
ty
166+
}
158167
Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
159168
Expr::TryBlock { body } => {
160169
let _inner = self.infer_expr(*body, expected);

crates/hir_ty/src/tests/simple.rs

+47
Original file line numberDiff line numberDiff line change
@@ -2415,3 +2415,50 @@ fn infer_const_params() {
24152415
"#]],
24162416
);
24172417
}
2418+
2419+
#[test]
2420+
fn infer_inner_type() {
2421+
check_infer(
2422+
r#"
2423+
fn foo() {
2424+
struct S { field: u32 }
2425+
let s = S { field: 0 };
2426+
let f = s.field;
2427+
}
2428+
"#,
2429+
expect![[r#"
2430+
9..89 '{ ...eld; }': ()
2431+
47..48 's': S
2432+
51..65 'S { field: 0 }': S
2433+
62..63 '0': u32
2434+
75..76 'f': u32
2435+
79..80 's': S
2436+
79..86 's.field': u32
2437+
"#]],
2438+
);
2439+
}
2440+
2441+
#[test]
2442+
fn infer_nested_inner_type() {
2443+
check_infer(
2444+
r#"
2445+
fn foo() {
2446+
{
2447+
let s = S { field: 0 };
2448+
let f = s.field;
2449+
}
2450+
struct S { field: u32 }
2451+
}
2452+
"#,
2453+
expect![[r#"
2454+
9..109 '{ ...32 } }': ()
2455+
15..79 '{ ... }': ()
2456+
29..30 's': S
2457+
33..47 'S { field: 0 }': S
2458+
44..45 '0': u32
2459+
61..62 'f': u32
2460+
65..66 's': S
2461+
65..72 's.field': u32
2462+
"#]],
2463+
);
2464+
}

crates/hir_ty/src/tests/traits.rs

+51
Original file line numberDiff line numberDiff line change
@@ -3151,3 +3151,54 @@ fn test() {
31513151
"#,
31523152
);
31533153
}
3154+
3155+
#[test]
3156+
fn inner_use() {
3157+
check_types(
3158+
r#"
3159+
mod m {
3160+
pub trait Tr {
3161+
fn method(&self) -> u8 { 0 }
3162+
}
3163+
3164+
impl Tr for () {}
3165+
}
3166+
3167+
fn f() {
3168+
use m::Tr;
3169+
3170+
().method();
3171+
//^^^^^^^^^^^ u8
3172+
}
3173+
"#,
3174+
);
3175+
}
3176+
3177+
#[test]
3178+
fn inner_use_in_block() {
3179+
check_types(
3180+
r#"
3181+
mod m {
3182+
pub trait Tr {
3183+
fn method(&self) -> u8 { 0 }
3184+
}
3185+
3186+
impl Tr for () {}
3187+
}
3188+
3189+
fn f() {
3190+
{
3191+
use m::Tr;
3192+
3193+
().method();
3194+
//^^^^^^^^^^^ u8
3195+
}
3196+
3197+
{
3198+
().method();
3199+
//^^^^^^^^^^^ {unknown}
3200+
}
3201+
}
3202+
"#,
3203+
);
3204+
}

crates/ide/src/inlay_hints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,7 @@ fn main() {
654654
let test = "test";
655655
//^^^^ &str
656656
let test = InnerStruct {};
657+
//^^^^ InnerStruct
657658
658659
let test = unresolved();
659660

0 commit comments

Comments
 (0)