Fix handling of const patterns

E.g. in `match x { None => ... }`, `None` is a path pattern (resolving to the
option variant), not a binding. To determine this, we need to try to resolve the
name during lowering. This isn't too hard since we already need to resolve names
for macro expansion anyway (though maybe a bit hacky).

Fixes #1618.
This commit is contained in:
Florian Diebold 2020-02-21 16:56:34 +01:00
parent e3037c2631
commit f1f45f9191
5 changed files with 85 additions and 6 deletions

View file

@ -189,7 +189,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
};
// use a new type variable if we got Ty::Unknown here
let ty = self.insert_type_vars_shallow(ty);
self.unify(&ty, expected);
if !self.unify(&ty, expected) {
// FIXME record mismatch, we need to change the type of self.type_mismatches for that
}
let ty = self.resolve_ty_as_possible(ty);
self.write_pat_ty(pat, ty.clone());
ty

View file

@ -1,4 +1,4 @@
use super::infer;
use super::{infer, infer_with_mismatches};
use insta::assert_snapshot;
use test_utils::covers;
@ -236,3 +236,47 @@ fn test(a1: A<u32>, o: Option<u64>) {
"###
);
}
#[test]
fn infer_const_pattern() {
assert_snapshot!(
infer_with_mismatches(r#"
enum Option<T> { None }
use Option::None;
struct Foo;
const Bar: usize = 1;
fn test() {
let a: Option<u32> = None;
let b: Option<i64> = match a {
None => None,
};
let _: () = match () { Foo => Foo }; // Expected mismatch
let _: () = match () { Bar => Bar }; // Expected mismatch
}
"#, true),
@r###"
[74; 75) '1': usize
[88; 310) '{ ...atch }': ()
[98; 99) 'a': Option<u32>
[115; 119) 'None': Option<u32>
[129; 130) 'b': Option<i64>
[146; 183) 'match ... }': Option<i64>
[152; 153) 'a': Option<u32>
[164; 168) 'None': Option<u32>
[172; 176) 'None': Option<i64>
[193; 194) '_': ()
[201; 224) 'match ... Foo }': Foo
[207; 209) '()': ()
[212; 215) 'Foo': Foo
[219; 222) 'Foo': Foo
[255; 256) '_': ()
[263; 286) 'match ... Bar }': usize
[269; 271) '()': ()
[274; 277) 'Bar': usize
[281; 284) 'Bar': usize
[201; 224): expected (), got Foo
[263; 286): expected (), got usize
"###
);
}