mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Add crude implementation of tuplestruct pattern inference
This commit is contained in:
parent
3b0de53904
commit
9c2d83a4c8
3 changed files with 89 additions and 40 deletions
|
@ -877,7 +877,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
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
|
||||||
|
|
||||||
match (&body[pat], &expected.ty) {
|
let ty = match (&body[pat], &expected.ty) {
|
||||||
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
||||||
if args.len() == tuple_args.len() =>
|
if args.len() == tuple_args.len() =>
|
||||||
{
|
{
|
||||||
|
@ -885,42 +885,71 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
// FIXME: can we do w/o cloning?
|
// FIXME: can we do w/o cloning?
|
||||||
self.infer_pat(pat, &Expectation::has_type(ty.clone()));
|
self.infer_pat(pat, &Expectation::has_type(ty.clone()));
|
||||||
}
|
}
|
||||||
|
expected.ty.clone()
|
||||||
}
|
}
|
||||||
(&Pat::Ref { pat, mutability }, &Ty::Ref(ref sub_ty, ty_mut))
|
(&Pat::Ref { pat, mutability }, &Ty::Ref(ref sub_ty, ty_mut))
|
||||||
if mutability == ty_mut =>
|
if mutability == ty_mut =>
|
||||||
{
|
{
|
||||||
self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone()));
|
self.infer_pat(pat, &Expectation::has_type((&**sub_ty).clone()));
|
||||||
|
expected.ty.clone()
|
||||||
}
|
}
|
||||||
(pattern, &Ty::Adt { def_id, .. }) => {
|
(
|
||||||
let adt_def = def_id.resolve(self.db);
|
&Pat::TupleStruct {
|
||||||
match (pattern, adt_def) {
|
path: ref p,
|
||||||
(&Pat::Struct, Def::Struct(s)) => {}
|
args: ref sub_pats,
|
||||||
(
|
},
|
||||||
&Pat::TupleStruct {
|
_expected,
|
||||||
path: ref p,
|
) => {
|
||||||
args: ref sub_pats,
|
let def = p
|
||||||
},
|
.as_ref()
|
||||||
Def::Enum(ref e),
|
.and_then(|path| self.module.resolve_path(self.db, &path).take_types())
|
||||||
) => {
|
.map(|def_id| def_id.resolve(self.db));
|
||||||
// TODO: resolve enum
|
|
||||||
|
if let Some(def) = def {
|
||||||
|
let (ty, fields) = match def {
|
||||||
|
Def::Struct(s) => {
|
||||||
|
let fields: Vec<_> = self
|
||||||
|
.db
|
||||||
|
.struct_data(s.def_id())
|
||||||
|
.variant_data
|
||||||
|
.fields()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
(type_for_struct(self.db, s), fields)
|
||||||
|
}
|
||||||
|
Def::EnumVariant(ev) => {
|
||||||
|
let fields: Vec<_> =
|
||||||
|
ev.variant_data(self.db).fields().iter().cloned().collect();
|
||||||
|
(type_for_enum_variant(self.db, ev), fields)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
// walk subpats
|
||||||
|
if fields.len() == sub_pats.len() {
|
||||||
|
for (&sub_pat, field) in sub_pats.iter().zip(fields.iter()) {
|
||||||
|
let sub_ty = Ty::from_hir(
|
||||||
|
self.db,
|
||||||
|
&self.module,
|
||||||
|
self.impl_block.as_ref(),
|
||||||
|
&field.type_ref,
|
||||||
|
);
|
||||||
|
|
||||||
|
self.infer_pat(sub_pat, &Expectation::has_type(sub_ty));
|
||||||
|
}
|
||||||
|
|
||||||
|
ty
|
||||||
|
} else {
|
||||||
|
expected.ty.clone()
|
||||||
}
|
}
|
||||||
(
|
} else {
|
||||||
&Pat::TupleStruct {
|
expected.ty.clone()
|
||||||
path: ref p,
|
|
||||||
args: ref sub_pats,
|
|
||||||
},
|
|
||||||
Def::EnumVariant(ref e),
|
|
||||||
) => {
|
|
||||||
let variant_data = self.db.enum_variant_data(e.def_id);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: implement more
|
(_, ref _expected_ty) => expected.ty.clone(),
|
||||||
(_, ref _expected_ty) => {}
|
|
||||||
};
|
};
|
||||||
// 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(expected.ty.clone());
|
let ty = self.insert_type_vars_shallow(ty);
|
||||||
self.unify(&ty, &expected.ty);
|
self.unify(&ty, &expected.ty);
|
||||||
let ty = self.resolve_ty_as_possible(ty);
|
let ty = self.resolve_ty_as_possible(ty);
|
||||||
self.write_pat_ty(pat, ty.clone());
|
self.write_pat_ty(pat, ty.clone());
|
||||||
|
|
|
@ -359,7 +359,22 @@ fn test(x: &str, y: isize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_pattern() {
|
fn infer_simple_pattern() {
|
||||||
|
check_inference(
|
||||||
|
r#"
|
||||||
|
fn test(x: &i32) {
|
||||||
|
let y = x;
|
||||||
|
let &z = x;
|
||||||
|
let a = z;
|
||||||
|
let (c, d) = (1, "hello");
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
"pattern.txt",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_adt_pattern() {
|
||||||
check_inference(
|
check_inference(
|
||||||
r#"
|
r#"
|
||||||
enum E {
|
enum E {
|
||||||
|
@ -367,23 +382,16 @@ enum E {
|
||||||
B
|
B
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test(x: &i32) {
|
struct S(u32, E);
|
||||||
let y = x;
|
|
||||||
let &z = x;
|
|
||||||
let a = z;
|
|
||||||
let (c, d) = (1, "hello");
|
|
||||||
|
|
||||||
|
fn test() {
|
||||||
let e = E::A { x: 3 };
|
let e = E::A { x: 3 };
|
||||||
if let E::A { x: x } = e {
|
|
||||||
x
|
let S(y, z) = foo;
|
||||||
};
|
let E::A { x: new_var } = e;
|
||||||
match e {
|
|
||||||
E::A { x } => x,
|
|
||||||
E::B => 1,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
"pattern.txt",
|
"adt_pattern.txt",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
crates/ra_hir/src/ty/tests/data/adt_pattern.txt
Normal file
12
crates/ra_hir/src/ty/tests/data/adt_pattern.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[49; 192) '{ ... }; }': ()
|
||||||
|
[59; 60) 'e': E
|
||||||
|
[63; 76) 'E::A { x: 3 }': E
|
||||||
|
[73; 74) '3': usize
|
||||||
|
[82; 124) 'if let... }': [unknown]
|
||||||
|
[105; 106) 'e': E
|
||||||
|
[107; 124) '{ ... }': [unknown]
|
||||||
|
[117; 118) 'x': [unknown]
|
||||||
|
[130; 189) 'match ... }': [unknown]
|
||||||
|
[136; 137) 'e': E
|
||||||
|
[162; 163) 'x': [unknown]
|
||||||
|
[181; 182) '1': i32
|
Loading…
Add table
Add a link
Reference in a new issue