mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Use type variables to determine exact type for ambiguous numeric literals
This commit is contained in:
parent
5f5dc20d85
commit
1574715be5
@ -699,7 +699,22 @@ impl ExprCollector {
|
||||
// TODO: actually parse integer
|
||||
Literal::Int(0u64, ty)
|
||||
}
|
||||
SyntaxKind::FLOAT_NUMBER => Literal::Float(0, UncertainFloatTy::Unknown),
|
||||
SyntaxKind::FLOAT_NUMBER => {
|
||||
let text = c.text().to_string();
|
||||
|
||||
// FIXME: don't do it like this. maybe use something like
|
||||
// the IntTy::from_name functions
|
||||
let ty = if text.ends_with("f64") {
|
||||
UncertainFloatTy::Known(FloatTy::F64)
|
||||
} else if text.ends_with("f32") {
|
||||
UncertainFloatTy::Known(FloatTy::F32)
|
||||
} else {
|
||||
UncertainFloatTy::Unknown
|
||||
};
|
||||
|
||||
// TODO: actually parse value
|
||||
Literal::Float(0, ty)
|
||||
}
|
||||
SyntaxKind::STRING => {
|
||||
// FIXME: this likely includes the " characters
|
||||
let text = c.text().to_string();
|
||||
|
@ -114,6 +114,8 @@ impl UnifyValue for TypeVarValue {
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum InferTy {
|
||||
TypeVar(TypeVarId),
|
||||
IntVar(TypeVarId),
|
||||
FloatVar(TypeVarId),
|
||||
}
|
||||
|
||||
/// When inferring an expression, we propagate downward whatever type hint we
|
||||
@ -718,12 +720,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
.iter()
|
||||
.zip(ts2.iter())
|
||||
.all(|(t1, t2)| self.unify(t1, t2)),
|
||||
(Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) => {
|
||||
(Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
|
||||
| (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
|
||||
| (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => {
|
||||
// both type vars are unknown since we tried to resolve them
|
||||
self.var_unification_table.union(*tv1, *tv2);
|
||||
true
|
||||
}
|
||||
(Ty::Infer(InferTy::TypeVar(tv)), other) | (other, Ty::Infer(InferTy::TypeVar(tv))) => {
|
||||
(Ty::Infer(InferTy::TypeVar(tv)), other)
|
||||
| (other, Ty::Infer(InferTy::TypeVar(tv)))
|
||||
| (Ty::Infer(InferTy::IntVar(tv)), other)
|
||||
| (other, Ty::Infer(InferTy::IntVar(tv)))
|
||||
| (Ty::Infer(InferTy::FloatVar(tv)), other)
|
||||
| (other, Ty::Infer(InferTy::FloatVar(tv))) => {
|
||||
// the type var is unknown since we tried to resolve it
|
||||
self.var_unification_table
|
||||
.union_value(*tv, TypeVarValue::Known(other.clone()));
|
||||
@ -739,10 +748,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
))
|
||||
}
|
||||
|
||||
fn new_integer_var(&mut self) -> Ty {
|
||||
Ty::Infer(InferTy::IntVar(
|
||||
self.var_unification_table.new_key(TypeVarValue::Unknown),
|
||||
))
|
||||
}
|
||||
|
||||
fn new_float_var(&mut self) -> Ty {
|
||||
Ty::Infer(InferTy::FloatVar(
|
||||
self.var_unification_table.new_key(TypeVarValue::Unknown),
|
||||
))
|
||||
}
|
||||
|
||||
/// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
|
||||
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
|
||||
match ty {
|
||||
Ty::Unknown => self.new_type_var(),
|
||||
Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(),
|
||||
Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(),
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
@ -757,12 +780,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
/// known type.
|
||||
fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
|
||||
ty.fold(&mut |ty| match ty {
|
||||
Ty::Infer(InferTy::TypeVar(tv)) => {
|
||||
Ty::Infer(InferTy::TypeVar(tv))
|
||||
| Ty::Infer(InferTy::IntVar(tv))
|
||||
| Ty::Infer(InferTy::FloatVar(tv)) => {
|
||||
if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
|
||||
// known_ty may contain other variables that are known by now
|
||||
self.resolve_ty_as_possible(known_ty.clone())
|
||||
} else {
|
||||
Ty::Infer(InferTy::TypeVar(tv))
|
||||
ty
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
@ -790,12 +815,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
/// replaced by Ty::Unknown.
|
||||
fn resolve_ty_completely(&mut self, ty: Ty) -> Ty {
|
||||
ty.fold(&mut |ty| match ty {
|
||||
Ty::Infer(InferTy::TypeVar(tv)) => {
|
||||
Ty::Infer(i) => {
|
||||
let tv = match i {
|
||||
InferTy::TypeVar(tv) | InferTy::IntVar(tv) | InferTy::FloatVar(tv) => tv,
|
||||
};
|
||||
|
||||
if let Some(known_ty) = self.var_unification_table.probe_value(tv).known() {
|
||||
// known_ty may contain other variables that are known by now
|
||||
self.resolve_ty_completely(known_ty.clone())
|
||||
} else {
|
||||
Ty::Unknown
|
||||
match i {
|
||||
InferTy::TypeVar(..) => Ty::Unknown,
|
||||
InferTy::IntVar(..) => Ty::Int(primitive::UncertainIntTy::Unknown),
|
||||
InferTy::FloatVar(..) => Ty::Float(primitive::UncertainFloatTy::Unknown),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ty,
|
||||
|
@ -145,6 +145,7 @@ fn test() {
|
||||
3.14;
|
||||
5000;
|
||||
(0u32, -5isize);
|
||||
false;
|
||||
[true, true, false]
|
||||
}
|
||||
"#,
|
||||
|
@ -10,4 +10,4 @@
|
||||
[76; 82) '1usize': usize
|
||||
[88; 94) '1isize': isize
|
||||
[100; 106) '"test"': &str
|
||||
[112; 118) '1.0f32': [unknown]
|
||||
[112; 118) '1.0f32': f32
|
||||
|
@ -1,10 +1,11 @@
|
||||
[11; 135) '{ ...lse] }': ()
|
||||
[11; 146) '{ ...lse] }': ()
|
||||
[17; 21) '5i32': i32
|
||||
[27; 34) '"hello"': &str
|
||||
[40; 48) 'b"bytes"': &[u8]
|
||||
[54; 57) ''c'': char
|
||||
[63; 67) 'b'b'': u8
|
||||
[73; 77) '3.14': [unknown]
|
||||
[83; 87) '5000': [unknown]
|
||||
[73; 77) '3.14': {float}
|
||||
[83; 87) '5000': {integer}
|
||||
[93; 108) '(0u32, -5isize)': [unknown]
|
||||
[114; 133) '[true,...false]': ()
|
||||
[114; 119) 'false': bool
|
||||
[125; 144) '[true,...false]': ()
|
||||
|
@ -2,14 +2,14 @@
|
||||
[82; 83) 'c': [unknown]
|
||||
[86; 87) 'C': [unknown]
|
||||
[86; 90) 'C(1)': [unknown]
|
||||
[88; 89) '1': [unknown]
|
||||
[88; 89) '1': {integer}
|
||||
[96; 97) 'B': [unknown]
|
||||
[107; 108) 'a': A
|
||||
[114; 133) 'A { b:...C(1) }': A
|
||||
[121; 122) 'B': B
|
||||
[127; 128) 'C': [unknown]
|
||||
[127; 131) 'C(1)': C
|
||||
[129; 130) '1': [unknown]
|
||||
[129; 130) '1': {integer}
|
||||
[139; 140) 'a': A
|
||||
[139; 142) 'a.b': B
|
||||
[148; 149) 'a': A
|
||||
|
Loading…
x
Reference in New Issue
Block a user