mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Implement type inference for tuples and refs
This commit is contained in:
parent
afaa26636e
commit
5648dcd36e
@ -36,7 +36,7 @@ use crate::{
|
|||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
type_ref::{TypeRef, Mutability},
|
type_ref::{TypeRef, Mutability},
|
||||||
name::KnownName,
|
name::KnownName,
|
||||||
expr::{Body, Expr, Literal, ExprId, PatId, UnaryOp, BinaryOp, Statement},
|
expr::{Body, Expr, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The ID of a type variable.
|
/// The ID of a type variable.
|
||||||
@ -872,6 +872,35 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Expectation should probably contain a reference to a Ty instead of
|
||||||
|
// a Ty itself
|
||||||
|
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
||||||
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(&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()));
|
||||||
|
}
|
||||||
|
// TODO: implement more
|
||||||
|
(_, ref _expected_ty) => {}
|
||||||
|
};
|
||||||
|
// use a new type variable if we got Ty::Unknown here
|
||||||
|
let ty = self.insert_type_vars_shallow(expected.ty.clone());
|
||||||
|
self.unify(&ty, &expected.ty);
|
||||||
|
let ty = self.resolve_ty_as_possible(ty);
|
||||||
|
self.write_pat_ty(pat, ty.clone());
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
fn infer_expr(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
||||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
let ty = match &body[expr] {
|
let ty = match &body[expr] {
|
||||||
@ -1168,9 +1197,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
decl_ty
|
decl_ty
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: walk the pattern here?
|
self.infer_pat(*pat, &Expectation::has_type(ty))?;
|
||||||
|
|
||||||
self.write_pat_ty(*pat, ty);
|
|
||||||
}
|
}
|
||||||
Statement::Expr(expr) => {
|
Statement::Expr(expr) => {
|
||||||
self.infer_expr(*expr, &Expectation::none());
|
self.infer_expr(*expr, &Expectation::none());
|
||||||
@ -1191,9 +1218,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
let ty = self.make_ty(type_ref);
|
let ty = self.make_ty(type_ref);
|
||||||
let ty = self.insert_type_vars(ty);
|
let ty = self.insert_type_vars(ty);
|
||||||
|
|
||||||
// TODO: walk pattern?
|
self.infer_pat(*pat, &Expectation::has_type(ty))?;
|
||||||
|
|
||||||
self.write_pat_ty(*pat, ty);
|
|
||||||
}
|
}
|
||||||
self.return_ty = {
|
self.return_ty = {
|
||||||
let ty = self.make_ty(signature.ret_type());
|
let ty = self.make_ty(signature.ret_type());
|
||||||
|
@ -362,11 +362,22 @@ fn test(x: &str, y: isize) {
|
|||||||
fn infer_pattern() {
|
fn infer_pattern() {
|
||||||
check_inference(
|
check_inference(
|
||||||
r#"
|
r#"
|
||||||
|
enum E { A { x: usize }, B }
|
||||||
|
|
||||||
fn test(x: &i32) {
|
fn test(x: &i32) {
|
||||||
let y = x;
|
let y = x;
|
||||||
let &z = x;
|
let &z = x;
|
||||||
let a = z;
|
let a = z;
|
||||||
let (c, d) = (1, "hello");
|
let (c, d) = (1, "hello");
|
||||||
|
|
||||||
|
let e = E::A { x: 3 };
|
||||||
|
if let E::A { x: x } = e {
|
||||||
|
x
|
||||||
|
};
|
||||||
|
match e {
|
||||||
|
E::A { x } => x,
|
||||||
|
E::B => 1,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
"pattern.txt",
|
"pattern.txt",
|
||||||
|
15
crates/ra_hir/src/ty/tests/data/pattern.txt
Normal file
15
crates/ra_hir/src/ty/tests/data/pattern.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[9; 10) 'x': &i32
|
||||||
|
[18; 98) '{ ...o"); }': ()
|
||||||
|
[28; 29) 'y': &i32
|
||||||
|
[32; 33) 'x': &i32
|
||||||
|
[43; 45) '&z': &i32
|
||||||
|
[44; 45) 'z': i32
|
||||||
|
[48; 49) 'x': &i32
|
||||||
|
[59; 60) 'a': i32
|
||||||
|
[63; 64) 'z': i32
|
||||||
|
[74; 80) '(c, d)': (i32, &str)
|
||||||
|
[75; 76) 'c': i32
|
||||||
|
[78; 79) 'd': &str
|
||||||
|
[83; 95) '(1, "hello")': (i32, &str)
|
||||||
|
[84; 85) '1': i32
|
||||||
|
[87; 94) '"hello"': &str
|
Loading…
x
Reference in New Issue
Block a user