mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
Merge #7627
7627: infer: update resolver when descending into block r=jonas-schievink a=jonas-schievink Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
commit
7ec03439a8
5 changed files with 139 additions and 32 deletions
|
@ -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 {
|
mod false_negatives {
|
||||||
//! The implementation of match checking here is a work in progress. As we roll this out, we
|
//! 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
|
//! prefer false negatives to false positives (ideally there would be no false positives). This
|
||||||
|
@ -1518,21 +1532,6 @@ fn main() {
|
||||||
11..20 => (),
|
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) => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,12 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
self.coerce_merge_branch(&then_ty, &else_ty)
|
self.coerce_merge_branch(&then_ty, &else_ty)
|
||||||
}
|
}
|
||||||
Expr::Block { statements, tail, label, id: _ } => match label {
|
Expr::Block { statements, tail, label, id: _ } => {
|
||||||
|
let old_resolver = mem::replace(
|
||||||
|
&mut self.resolver,
|
||||||
|
resolver_for_expr(self.db.upcast(), self.owner, tgt_expr),
|
||||||
|
);
|
||||||
|
let ty = match label {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
let break_ty = self.table.new_type_var();
|
let break_ty = self.table.new_type_var();
|
||||||
self.breakables.push(BreakableContext {
|
self.breakables.push(BreakableContext {
|
||||||
|
@ -145,7 +150,8 @@ impl<'a> InferenceContext<'a> {
|
||||||
break_ty: break_ty.clone(),
|
break_ty: break_ty.clone(),
|
||||||
label: label.map(|label| self.body[label].name.clone()),
|
label: label.map(|label| self.body[label].name.clone()),
|
||||||
});
|
});
|
||||||
let ty = self.infer_block(statements, *tail, &Expectation::has_type(break_ty));
|
let ty =
|
||||||
|
self.infer_block(statements, *tail, &Expectation::has_type(break_ty));
|
||||||
let ctxt = self.breakables.pop().expect("breakable stack broken");
|
let ctxt = self.breakables.pop().expect("breakable stack broken");
|
||||||
if ctxt.may_break {
|
if ctxt.may_break {
|
||||||
ctxt.break_ty
|
ctxt.break_ty
|
||||||
|
@ -154,7 +160,10 @@ impl<'a> InferenceContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => self.infer_block(statements, *tail, expected),
|
None => self.infer_block(statements, *tail, expected),
|
||||||
},
|
};
|
||||||
|
self.resolver = old_resolver;
|
||||||
|
ty
|
||||||
|
}
|
||||||
Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
|
Expr::Unsafe { body } | Expr::Const { body } => self.infer_expr(*body, expected),
|
||||||
Expr::TryBlock { body } => {
|
Expr::TryBlock { body } => {
|
||||||
let _inner = self.infer_expr(*body, expected);
|
let _inner = self.infer_expr(*body, expected);
|
||||||
|
|
|
@ -2415,3 +2415,50 @@ 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
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -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}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -654,6 +654,7 @@ fn main() {
|
||||||
let test = "test";
|
let test = "test";
|
||||||
//^^^^ &str
|
//^^^^ &str
|
||||||
let test = InnerStruct {};
|
let test = InnerStruct {};
|
||||||
|
//^^^^ InnerStruct
|
||||||
|
|
||||||
let test = unresolved();
|
let test = unresolved();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue