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;
|
return Ty::Unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
// walk subpats
|
|
||||||
if fields.len() != sub_pats.len() {
|
if fields.len() != sub_pats.len() {
|
||||||
return Ty::Unknown;
|
return Ty::Unknown;
|
||||||
}
|
}
|
||||||
@ -944,44 +943,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Expectation should probably contain a reference to a Ty instead of
|
// TODO: Expectation should probably contain a Cow pointer to Ty?
|
||||||
// a Ty itself
|
// so that we can make new expectations of subtypes cheaply
|
||||||
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
||||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
|
|
||||||
// FIXME: we can do some inference even if the expected ty isnt already
|
let ty = match &body[pat] {
|
||||||
// of the right form
|
Pat::Tuple(ref args) => {
|
||||||
let ty = match (&body[pat], &expected.ty) {
|
// this can probably be done without cloning/ collecting
|
||||||
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
let expectations = match expected.ty {
|
||||||
if args.len() == tuple_args.len() =>
|
Ty::Tuple(ref tuple_args) if args.len() == tuple_args.len() => {
|
||||||
{
|
tuple_args.iter().cloned().collect()
|
||||||
for (&pat, ty) in args.iter().zip(tuple_args.iter()) {
|
}
|
||||||
// FIXME: can we do w/o cloning?
|
_ => vec![Ty::Unknown; args.len()],
|
||||||
self.infer_pat(pat, &Expectation::has_type(ty.clone()));
|
};
|
||||||
}
|
|
||||||
expected.ty.clone()
|
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))
|
Pat::Ref { pat, mutability } => {
|
||||||
if mutability == ty_mut =>
|
let expectation = match expected.ty {
|
||||||
{
|
Ty::Ref(ref sub_ty, exp_mut) if *mutability == exp_mut => {
|
||||||
self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone()));
|
Expectation::has_type((&**sub_ty).clone())
|
||||||
expected.ty.clone()
|
}
|
||||||
|
_ => Expectation::none(),
|
||||||
|
};
|
||||||
|
let subty = self.infer_pat(*pat, &expectation);
|
||||||
|
Ty::Ref(subty.into(), *mutability)
|
||||||
}
|
}
|
||||||
(
|
Pat::TupleStruct {
|
||||||
&Pat::TupleStruct {
|
path: ref p,
|
||||||
path: ref p,
|
args: ref sub_pats,
|
||||||
args: ref sub_pats,
|
} => self.infer_tuple_struct(p.as_ref(), sub_pats),
|
||||||
},
|
Pat::Struct {
|
||||||
_,
|
path: ref p,
|
||||||
) => self.infer_tuple_struct(p.as_ref(), sub_pats),
|
args: ref fields,
|
||||||
(
|
} => self.infer_struct(p.as_ref(), fields),
|
||||||
&Pat::Struct {
|
_ => Ty::Unknown,
|
||||||
path: ref p,
|
|
||||||
args: ref fields,
|
|
||||||
},
|
|
||||||
_,
|
|
||||||
) => self.infer_struct(p.as_ref(), fields),
|
|
||||||
(_, ref _expected_ty) => expected.ty.clone(),
|
|
||||||
};
|
};
|
||||||
// use a new type variable if we got Ty::Unknown here
|
// use a new type variable if we got Ty::Unknown here
|
||||||
let ty = self.insert_type_vars_shallow(ty);
|
let ty = self.insert_type_vars_shallow(ty);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[9; 10) 'x': &i32
|
[9; 10) 'x': &i32
|
||||||
[18; 98) '{ ...o"); }': ()
|
[18; 259) '{ ...c }; }': ()
|
||||||
[28; 29) 'y': &i32
|
[28; 29) 'y': &i32
|
||||||
[32; 33) 'x': &i32
|
[32; 33) 'x': &i32
|
||||||
[43; 45) '&z': &i32
|
[43; 45) '&z': &i32
|
||||||
@ -13,3 +13,27 @@
|
|||||||
[83; 95) '(1, "hello")': (i32, &str)
|
[83; 95) '(1, "hello")': (i32, &str)
|
||||||
[84; 85) '1': i32
|
[84; 85) '1': i32
|
||||||
[87; 94) '"hello"': &str
|
[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