Make pattern inference work w/o proper expecations
This commit is contained in:
parent
be1b4034a5
commit
9433a108cf
@ -911,7 +911,6 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
return Ty::Unknown;
|
||||
};
|
||||
|
||||
// walk subpats
|
||||
if fields.len() != sub_pats.len() {
|
||||
return Ty::Unknown;
|
||||
}
|
||||
@ -944,44 +943,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
ty
|
||||
}
|
||||
|
||||
// FIXME: Expectation should probably contain a reference to a Ty instead of
|
||||
// a Ty itself
|
||||
// TODO: Expectation should probably contain a Cow pointer to Ty?
|
||||
// so that we can make new expectations of subtypes cheaply
|
||||
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||
|
||||
// FIXME: we can do some inference even if the expected ty isnt already
|
||||
// of the right form
|
||||
let ty = match (&body[pat], &expected.ty) {
|
||||
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
||||
if args.len() == tuple_args.len() =>
|
||||
{
|
||||
for (&pat, ty) in args.iter().zip(tuple_args.iter()) {
|
||||
// FIXME: can we do w/o cloning?
|
||||
self.infer_pat(pat, &Expectation::has_type(ty.clone()));
|
||||
}
|
||||
expected.ty.clone()
|
||||
let ty = match &body[pat] {
|
||||
Pat::Tuple(ref args) => {
|
||||
// this can probably be done without cloning/ collecting
|
||||
let expectations = match expected.ty {
|
||||
Ty::Tuple(ref tuple_args) if args.len() == tuple_args.len() => {
|
||||
tuple_args.iter().cloned().collect()
|
||||
}
|
||||
_ => vec![Ty::Unknown; args.len()],
|
||||
};
|
||||
|
||||
let inner_tys = args
|
||||
.iter()
|
||||
.zip(expectations.into_iter())
|
||||
.map(|(&pat, ty)| self.infer_pat(pat, &Expectation::has_type(ty)))
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
|
||||
Ty::Tuple(inner_tys)
|
||||
}
|
||||
(&Pat::Ref { pat, mutability }, &Ty::Ref(ref sub_ty, ty_mut))
|
||||
if mutability == ty_mut =>
|
||||
{
|
||||
self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone()));
|
||||
expected.ty.clone()
|
||||
Pat::Ref { pat, mutability } => {
|
||||
let expectation = match expected.ty {
|
||||
Ty::Ref(ref sub_ty, exp_mut) if *mutability == exp_mut => {
|
||||
Expectation::has_type((&**sub_ty).clone())
|
||||
}
|
||||
_ => Expectation::none(),
|
||||
};
|
||||
let subty = self.infer_pat(*pat, &expectation);
|
||||
Ty::Ref(subty.into(), *mutability)
|
||||
}
|
||||
(
|
||||
&Pat::TupleStruct {
|
||||
path: ref p,
|
||||
args: ref sub_pats,
|
||||
},
|
||||
_,
|
||||
) => self.infer_tuple_struct(p.as_ref(), sub_pats),
|
||||
(
|
||||
&Pat::Struct {
|
||||
path: ref p,
|
||||
args: ref fields,
|
||||
},
|
||||
_,
|
||||
) => self.infer_struct(p.as_ref(), fields),
|
||||
(_, ref _expected_ty) => expected.ty.clone(),
|
||||
Pat::TupleStruct {
|
||||
path: ref p,
|
||||
args: ref sub_pats,
|
||||
} => self.infer_tuple_struct(p.as_ref(), sub_pats),
|
||||
Pat::Struct {
|
||||
path: ref p,
|
||||
args: ref fields,
|
||||
} => self.infer_struct(p.as_ref(), fields),
|
||||
_ => Ty::Unknown,
|
||||
};
|
||||
// use a new type variable if we got Ty::Unknown here
|
||||
let ty = self.insert_type_vars_shallow(ty);
|
||||
|
@ -1,5 +1,5 @@
|
||||
[9; 10) 'x': &i32
|
||||
[18; 98) '{ ...o"); }': ()
|
||||
[18; 259) '{ ...c }; }': ()
|
||||
[28; 29) 'y': &i32
|
||||
[32; 33) 'x': &i32
|
||||
[43; 45) '&z': &i32
|
||||
@ -13,3 +13,27 @@
|
||||
[83; 95) '(1, "hello")': (i32, &str)
|
||||
[84; 85) '1': i32
|
||||
[87; 94) '"hello"': &str
|
||||
[102; 152) 'for (e... }': ()
|
||||
[106; 112) '(e, f)': ([unknown], [unknown])
|
||||
[107; 108) 'e': [unknown]
|
||||
[110; 111) 'f': [unknown]
|
||||
[116; 125) 'some_iter': [unknown]
|
||||
[126; 152) '{ ... }': ()
|
||||
[140; 141) 'g': [unknown]
|
||||
[144; 145) 'e': [unknown]
|
||||
[158; 205) 'if let... }': ()
|
||||
[165; 170) '[val]': [unknown]
|
||||
[173; 176) 'opt': [unknown]
|
||||
[177; 205) '{ ... }': ()
|
||||
[191; 192) 'h': [unknown]
|
||||
[195; 198) 'val': [unknown]
|
||||
[215; 221) 'lambda': [unknown]
|
||||
[224; 256) '|a: u6...b; c }': [unknown]
|
||||
[225; 226) 'a': u64
|
||||
[233; 234) 'b': u64
|
||||
[236; 237) 'c': i32
|
||||
[244; 256) '{ a + b; c }': i32
|
||||
[246; 247) 'a': u64
|
||||
[246; 251) 'a + b': u64
|
||||
[250; 251) 'b': u64
|
||||
[253; 254) 'c': i32
|
||||
|
Loading…
x
Reference in New Issue
Block a user