diff options
author | Florian Diebold <[email protected]> | 2019-02-23 14:24:07 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-23 14:36:38 +0000 |
commit | dcfb4ee70254ec696801cbdb22d2de2bb1c939ed (patch) | |
tree | 8d36f12550779a0d51c46d706f96a09df16059a3 /crates/ra_hir/src/ty | |
parent | 460ceb4cf2b8217abd002f8a30ef52f2aa25fee9 (diff) |
Split ty.rs into several modules
It was just getting too big. We now have:
- ty: the `Ty` enum and helpers
- ty::infer: actual type inference
- ty::lower: lowering from HIR to `Ty`
- ty::op: helpers for binary operations, currently
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 1079 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 318 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/op.rs | 81 |
3 files changed, 1478 insertions, 0 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs new file mode 100644 index 000000000..6ee9080d3 --- /dev/null +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -0,0 +1,1079 @@ | |||
1 | //! Type inference, i.e. the process of walking through the code and determining | ||
2 | //! the type of each expression and pattern. | ||
3 | //! | ||
4 | //! For type inference, compare the implementations in rustc (the various | ||
5 | //! check_* methods in librustc_typeck/check/mod.rs are a good entry point) and | ||
6 | //! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for | ||
7 | //! inference here is the `infer` function, which infers the types of all | ||
8 | //! expressions in a given function. | ||
9 | //! | ||
10 | //! During inference, types (i.e. the `Ty` struct) can contain type 'variables' | ||
11 | //! which represent currently unknown types; as we walk through the expressions, | ||
12 | //! we might determine that certain variables need to be equal to each other, or | ||
13 | //! to certain types. To record this, we use the union-find implementation from | ||
14 | //! the `ena` crate, which is extracted from rustc. | ||
15 | |||
16 | use std::borrow::Cow; | ||
17 | use std::iter::repeat; | ||
18 | use std::ops::Index; | ||
19 | use std::sync::Arc; | ||
20 | use std::mem; | ||
21 | |||
22 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; | ||
23 | use ra_arena::map::ArenaMap; | ||
24 | use rustc_hash::FxHashMap; | ||
25 | |||
26 | use test_utils::tested_by; | ||
27 | |||
28 | use crate::{ | ||
29 | Function, StructField, Path, Name, | ||
30 | FnSignature, AdtDef, | ||
31 | HirDatabase, | ||
32 | type_ref::{TypeRef, Mutability}, | ||
33 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, | ||
34 | generics::GenericParams, | ||
35 | path::{GenericArgs, GenericArg}, | ||
36 | adt::VariantDef, | ||
37 | resolve::{Resolver, Resolution}, | ||
38 | nameres::Namespace | ||
39 | }; | ||
40 | use super::{Ty, TypableDef, Substs, primitive, op}; | ||
41 | |||
42 | /// The entry point of type inference. | ||
43 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | ||
44 | db.check_canceled(); | ||
45 | let body = func.body(db); | ||
46 | let resolver = func.resolver(db); | ||
47 | let mut ctx = InferenceContext::new(db, body, resolver); | ||
48 | |||
49 | let signature = func.signature(db); | ||
50 | ctx.collect_fn_signature(&signature); | ||
51 | |||
52 | ctx.infer_body(); | ||
53 | |||
54 | Arc::new(ctx.resolve_all()) | ||
55 | } | ||
56 | |||
57 | /// The result of type inference: A mapping from expressions and patterns to types. | ||
58 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
59 | pub struct InferenceResult { | ||
60 | /// For each method call expr, records the function it resolves to. | ||
61 | method_resolutions: FxHashMap<ExprId, Function>, | ||
62 | /// For each field access expr, records the field it resolves to. | ||
63 | field_resolutions: FxHashMap<ExprId, StructField>, | ||
64 | pub(super) type_of_expr: ArenaMap<ExprId, Ty>, | ||
65 | pub(super) type_of_pat: ArenaMap<PatId, Ty>, | ||
66 | } | ||
67 | |||
68 | impl InferenceResult { | ||
69 | pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { | ||
70 | self.method_resolutions.get(&expr).map(|it| *it) | ||
71 | } | ||
72 | pub fn field_resolution(&self, expr: ExprId) -> Option<StructField> { | ||
73 | self.field_resolutions.get(&expr).map(|it| *it) | ||
74 | } | ||
75 | } | ||
76 | |||
77 | impl Index<ExprId> for InferenceResult { | ||
78 | type Output = Ty; | ||
79 | |||
80 | fn index(&self, expr: ExprId) -> &Ty { | ||
81 | self.type_of_expr.get(expr).unwrap_or(&Ty::Unknown) | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl Index<PatId> for InferenceResult { | ||
86 | type Output = Ty; | ||
87 | |||
88 | fn index(&self, pat: PatId) -> &Ty { | ||
89 | self.type_of_pat.get(pat).unwrap_or(&Ty::Unknown) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | /// The inference context contains all information needed during type inference. | ||
94 | #[derive(Clone, Debug)] | ||
95 | struct InferenceContext<'a, D: HirDatabase> { | ||
96 | db: &'a D, | ||
97 | body: Arc<Body>, | ||
98 | resolver: Resolver, | ||
99 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | ||
100 | method_resolutions: FxHashMap<ExprId, Function>, | ||
101 | field_resolutions: FxHashMap<ExprId, StructField>, | ||
102 | type_of_expr: ArenaMap<ExprId, Ty>, | ||
103 | type_of_pat: ArenaMap<PatId, Ty>, | ||
104 | /// The return type of the function being inferred. | ||
105 | return_ty: Ty, | ||
106 | } | ||
107 | |||
108 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | ||
109 | fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { | ||
110 | InferenceContext { | ||
111 | method_resolutions: FxHashMap::default(), | ||
112 | field_resolutions: FxHashMap::default(), | ||
113 | type_of_expr: ArenaMap::default(), | ||
114 | type_of_pat: ArenaMap::default(), | ||
115 | var_unification_table: InPlaceUnificationTable::new(), | ||
116 | return_ty: Ty::Unknown, // set in collect_fn_signature | ||
117 | db, | ||
118 | body, | ||
119 | resolver, | ||
120 | } | ||
121 | } | ||
122 | |||
123 | fn resolve_all(mut self) -> InferenceResult { | ||
124 | let mut tv_stack = Vec::new(); | ||
125 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); | ||
126 | for ty in expr_types.values_mut() { | ||
127 | let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); | ||
128 | *ty = resolved; | ||
129 | } | ||
130 | let mut pat_types = mem::replace(&mut self.type_of_pat, ArenaMap::default()); | ||
131 | for ty in pat_types.values_mut() { | ||
132 | let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); | ||
133 | *ty = resolved; | ||
134 | } | ||
135 | InferenceResult { | ||
136 | method_resolutions: self.method_resolutions, | ||
137 | field_resolutions: self.field_resolutions, | ||
138 | type_of_expr: expr_types, | ||
139 | type_of_pat: pat_types, | ||
140 | } | ||
141 | } | ||
142 | |||
143 | fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) { | ||
144 | self.type_of_expr.insert(expr, ty); | ||
145 | } | ||
146 | |||
147 | fn write_method_resolution(&mut self, expr: ExprId, func: Function) { | ||
148 | self.method_resolutions.insert(expr, func); | ||
149 | } | ||
150 | |||
151 | fn write_field_resolution(&mut self, expr: ExprId, field: StructField) { | ||
152 | self.field_resolutions.insert(expr, field); | ||
153 | } | ||
154 | |||
155 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { | ||
156 | self.type_of_pat.insert(pat, ty); | ||
157 | } | ||
158 | |||
159 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { | ||
160 | let ty = Ty::from_hir( | ||
161 | self.db, | ||
162 | // TODO use right resolver for block | ||
163 | &self.resolver, | ||
164 | type_ref, | ||
165 | ); | ||
166 | let ty = self.insert_type_vars(ty); | ||
167 | ty | ||
168 | } | ||
169 | |||
170 | fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { | ||
171 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) | ||
172 | } | ||
173 | |||
174 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | ||
175 | self.unify_inner(ty1, ty2, 0) | ||
176 | } | ||
177 | |||
178 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | ||
179 | if depth > 1000 { | ||
180 | // prevent stackoverflows | ||
181 | panic!("infinite recursion in unification"); | ||
182 | } | ||
183 | if ty1 == ty2 { | ||
184 | return true; | ||
185 | } | ||
186 | // try to resolve type vars first | ||
187 | let ty1 = self.resolve_ty_shallow(ty1); | ||
188 | let ty2 = self.resolve_ty_shallow(ty2); | ||
189 | match (&*ty1, &*ty2) { | ||
190 | (Ty::Unknown, ..) => true, | ||
191 | (.., Ty::Unknown) => true, | ||
192 | (Ty::Int(t1), Ty::Int(t2)) => match (t1, t2) { | ||
193 | (primitive::UncertainIntTy::Unknown, _) | ||
194 | | (_, primitive::UncertainIntTy::Unknown) => true, | ||
195 | _ => t1 == t2, | ||
196 | }, | ||
197 | (Ty::Float(t1), Ty::Float(t2)) => match (t1, t2) { | ||
198 | (primitive::UncertainFloatTy::Unknown, _) | ||
199 | | (_, primitive::UncertainFloatTy::Unknown) => true, | ||
200 | _ => t1 == t2, | ||
201 | }, | ||
202 | (Ty::Bool, _) | (Ty::Str, _) | (Ty::Never, _) | (Ty::Char, _) => ty1 == ty2, | ||
203 | ( | ||
204 | Ty::Adt { def_id: def_id1, substs: substs1, .. }, | ||
205 | Ty::Adt { def_id: def_id2, substs: substs2, .. }, | ||
206 | ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1), | ||
207 | (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1), | ||
208 | (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => { | ||
209 | self.unify_inner(t1, t2, depth + 1) | ||
210 | } | ||
211 | (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), | ||
212 | (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, | ||
213 | (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { | ||
214 | ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) | ||
215 | } | ||
216 | (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | ||
217 | | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) | ||
218 | | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) => { | ||
219 | // both type vars are unknown since we tried to resolve them | ||
220 | self.var_unification_table.union(*tv1, *tv2); | ||
221 | true | ||
222 | } | ||
223 | (Ty::Infer(InferTy::TypeVar(tv)), other) | ||
224 | | (other, Ty::Infer(InferTy::TypeVar(tv))) | ||
225 | | (Ty::Infer(InferTy::IntVar(tv)), other) | ||
226 | | (other, Ty::Infer(InferTy::IntVar(tv))) | ||
227 | | (Ty::Infer(InferTy::FloatVar(tv)), other) | ||
228 | | (other, Ty::Infer(InferTy::FloatVar(tv))) => { | ||
229 | // the type var is unknown since we tried to resolve it | ||
230 | self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); | ||
231 | true | ||
232 | } | ||
233 | _ => false, | ||
234 | } | ||
235 | } | ||
236 | |||
237 | fn new_type_var(&mut self) -> Ty { | ||
238 | Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | ||
239 | } | ||
240 | |||
241 | fn new_integer_var(&mut self) -> Ty { | ||
242 | Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | ||
243 | } | ||
244 | |||
245 | fn new_float_var(&mut self) -> Ty { | ||
246 | Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) | ||
247 | } | ||
248 | |||
249 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | ||
250 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | ||
251 | match ty { | ||
252 | Ty::Unknown => self.new_type_var(), | ||
253 | Ty::Int(primitive::UncertainIntTy::Unknown) => self.new_integer_var(), | ||
254 | Ty::Float(primitive::UncertainFloatTy::Unknown) => self.new_float_var(), | ||
255 | _ => ty, | ||
256 | } | ||
257 | } | ||
258 | |||
259 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { | ||
260 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | ||
261 | } | ||
262 | |||
263 | /// Resolves the type as far as currently possible, replacing type variables | ||
264 | /// by their known types. All types returned by the infer_* functions should | ||
265 | /// be resolved as far as possible, i.e. contain no type variables with | ||
266 | /// known type. | ||
267 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | ||
268 | ty.fold(&mut |ty| match ty { | ||
269 | Ty::Infer(tv) => { | ||
270 | let inner = tv.to_inner(); | ||
271 | if tv_stack.contains(&inner) { | ||
272 | tested_by!(type_var_cycles_resolve_as_possible); | ||
273 | // recursive type | ||
274 | return tv.fallback_value(); | ||
275 | } | ||
276 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | ||
277 | // known_ty may contain other variables that are known by now | ||
278 | tv_stack.push(inner); | ||
279 | let result = self.resolve_ty_as_possible(tv_stack, known_ty.clone()); | ||
280 | tv_stack.pop(); | ||
281 | result | ||
282 | } else { | ||
283 | ty | ||
284 | } | ||
285 | } | ||
286 | _ => ty, | ||
287 | }) | ||
288 | } | ||
289 | |||
290 | /// If `ty` is a type variable with known type, returns that type; | ||
291 | /// otherwise, return ty. | ||
292 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { | ||
293 | let mut ty = Cow::Borrowed(ty); | ||
294 | // The type variable could resolve to a int/float variable. Hence try | ||
295 | // resolving up to three times; each type of variable shouldn't occur | ||
296 | // more than once | ||
297 | for i in 0..3 { | ||
298 | if i > 0 { | ||
299 | tested_by!(type_var_resolves_to_int_var); | ||
300 | } | ||
301 | match &*ty { | ||
302 | Ty::Infer(tv) => { | ||
303 | let inner = tv.to_inner(); | ||
304 | match self.var_unification_table.probe_value(inner).known() { | ||
305 | Some(known_ty) => { | ||
306 | // The known_ty can't be a type var itself | ||
307 | ty = Cow::Owned(known_ty.clone()); | ||
308 | } | ||
309 | _ => return ty, | ||
310 | } | ||
311 | } | ||
312 | _ => return ty, | ||
313 | } | ||
314 | } | ||
315 | log::error!("Inference variable still not resolved: {:?}", ty); | ||
316 | ty | ||
317 | } | ||
318 | |||
319 | /// Resolves the type completely; type variables without known type are | ||
320 | /// replaced by Ty::Unknown. | ||
321 | fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | ||
322 | ty.fold(&mut |ty| match ty { | ||
323 | Ty::Infer(tv) => { | ||
324 | let inner = tv.to_inner(); | ||
325 | if tv_stack.contains(&inner) { | ||
326 | tested_by!(type_var_cycles_resolve_completely); | ||
327 | // recursive type | ||
328 | return tv.fallback_value(); | ||
329 | } | ||
330 | if let Some(known_ty) = self.var_unification_table.probe_value(inner).known() { | ||
331 | // known_ty may contain other variables that are known by now | ||
332 | tv_stack.push(inner); | ||
333 | let result = self.resolve_ty_completely(tv_stack, known_ty.clone()); | ||
334 | tv_stack.pop(); | ||
335 | result | ||
336 | } else { | ||
337 | tv.fallback_value() | ||
338 | } | ||
339 | } | ||
340 | _ => ty, | ||
341 | }) | ||
342 | } | ||
343 | |||
344 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { | ||
345 | let resolved = resolver.resolve_path_segments(self.db, &path); | ||
346 | |||
347 | let (def, remaining_index) = resolved.into_inner(); | ||
348 | |||
349 | log::debug!( | ||
350 | "path {:?} resolved to {:?} with remaining index {:?}", | ||
351 | path, | ||
352 | def, | ||
353 | remaining_index | ||
354 | ); | ||
355 | |||
356 | // if the remaining_index is None, we expect the path | ||
357 | // to be fully resolved, in this case we continue with | ||
358 | // the default by attempting to `take_values´ from the resolution. | ||
359 | // Otherwise the path was partially resolved, which means | ||
360 | // we might have resolved into a type for which | ||
361 | // we may find some associated item starting at the | ||
362 | // path.segment pointed to by `remaining_index´ | ||
363 | let resolved = | ||
364 | if remaining_index.is_none() { def.take_values()? } else { def.take_types()? }; | ||
365 | |||
366 | match resolved { | ||
367 | Resolution::Def(def) => { | ||
368 | let typable: Option<TypableDef> = def.into(); | ||
369 | let typable = typable?; | ||
370 | |||
371 | if let Some(remaining_index) = remaining_index { | ||
372 | let ty = self.db.type_for_def(typable, Namespace::Types); | ||
373 | // TODO: Keep resolving the segments | ||
374 | // if we have more segments to process | ||
375 | let segment = &path.segments[remaining_index]; | ||
376 | |||
377 | log::debug!("looking for path segment: {:?}", segment); | ||
378 | |||
379 | // Attempt to find an impl_item for the type which has a name matching | ||
380 | // the current segment | ||
381 | let ty = ty.iterate_impl_items(self.db, |item| match item { | ||
382 | crate::ImplItem::Method(func) => { | ||
383 | let sig = func.signature(self.db); | ||
384 | if segment.name == *sig.name() { | ||
385 | return Some(func.ty(self.db)); | ||
386 | } | ||
387 | None | ||
388 | } | ||
389 | |||
390 | // TODO: Resolve associated const | ||
391 | crate::ImplItem::Const(_) => None, | ||
392 | |||
393 | // TODO: Resolve associated types | ||
394 | crate::ImplItem::Type(_) => None, | ||
395 | }); | ||
396 | ty | ||
397 | } else { | ||
398 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
399 | let ty = self.db.type_for_def(typable, Namespace::Values).apply_substs(substs); | ||
400 | let ty = self.insert_type_vars(ty); | ||
401 | Some(ty) | ||
402 | } | ||
403 | } | ||
404 | Resolution::LocalBinding(pat) => { | ||
405 | let ty = self.type_of_pat.get(pat)?; | ||
406 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); | ||
407 | Some(ty) | ||
408 | } | ||
409 | Resolution::GenericParam(..) => { | ||
410 | // generic params can't refer to values... yet | ||
411 | None | ||
412 | } | ||
413 | Resolution::SelfType(_) => { | ||
414 | log::error!("path expr {:?} resolved to Self type in values ns", path); | ||
415 | None | ||
416 | } | ||
417 | } | ||
418 | } | ||
419 | |||
420 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { | ||
421 | let path = match path { | ||
422 | Some(path) => path, | ||
423 | None => return (Ty::Unknown, None), | ||
424 | }; | ||
425 | let resolver = &self.resolver; | ||
426 | let typable: Option<TypableDef> = match resolver.resolve_path(self.db, &path).take_types() { | ||
427 | Some(Resolution::Def(def)) => def.into(), | ||
428 | Some(Resolution::LocalBinding(..)) => { | ||
429 | // this cannot happen | ||
430 | log::error!("path resolved to local binding in type ns"); | ||
431 | return (Ty::Unknown, None); | ||
432 | } | ||
433 | Some(Resolution::GenericParam(..)) => { | ||
434 | // generic params can't be used in struct literals | ||
435 | return (Ty::Unknown, None); | ||
436 | } | ||
437 | Some(Resolution::SelfType(..)) => { | ||
438 | // TODO this is allowed in an impl for a struct, handle this | ||
439 | return (Ty::Unknown, None); | ||
440 | } | ||
441 | None => return (Ty::Unknown, None), | ||
442 | }; | ||
443 | let def = match typable { | ||
444 | None => return (Ty::Unknown, None), | ||
445 | Some(it) => it, | ||
446 | }; | ||
447 | // TODO remove the duplication between here and `Ty::from_path`? | ||
448 | let substs = Ty::substs_from_path(self.db, resolver, path, def); | ||
449 | match def { | ||
450 | TypableDef::Struct(s) => { | ||
451 | let ty = s.ty(self.db); | ||
452 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
453 | (ty, Some(s.into())) | ||
454 | } | ||
455 | TypableDef::EnumVariant(var) => { | ||
456 | let ty = var.parent_enum(self.db).ty(self.db); | ||
457 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | ||
458 | (ty, Some(var.into())) | ||
459 | } | ||
460 | TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None), | ||
461 | } | ||
462 | } | ||
463 | |||
464 | fn infer_tuple_struct_pat( | ||
465 | &mut self, | ||
466 | path: Option<&Path>, | ||
467 | subpats: &[PatId], | ||
468 | expected: &Ty, | ||
469 | ) -> Ty { | ||
470 | let (ty, def) = self.resolve_variant(path); | ||
471 | |||
472 | self.unify(&ty, expected); | ||
473 | |||
474 | let substs = ty.substs().unwrap_or_else(Substs::empty); | ||
475 | |||
476 | for (i, &subpat) in subpats.iter().enumerate() { | ||
477 | let expected_ty = def | ||
478 | .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) | ||
479 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | ||
480 | .subst(&substs); | ||
481 | self.infer_pat(subpat, &expected_ty); | ||
482 | } | ||
483 | |||
484 | ty | ||
485 | } | ||
486 | |||
487 | fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat], expected: &Ty) -> Ty { | ||
488 | let (ty, def) = self.resolve_variant(path); | ||
489 | |||
490 | self.unify(&ty, expected); | ||
491 | |||
492 | let substs = ty.substs().unwrap_or_else(Substs::empty); | ||
493 | |||
494 | for subpat in subpats { | ||
495 | let matching_field = def.and_then(|it| it.field(self.db, &subpat.name)); | ||
496 | let expected_ty = | ||
497 | matching_field.map_or(Ty::Unknown, |field| field.ty(self.db)).subst(&substs); | ||
498 | self.infer_pat(subpat.pat, &expected_ty); | ||
499 | } | ||
500 | |||
501 | ty | ||
502 | } | ||
503 | |||
504 | fn infer_pat(&mut self, pat: PatId, expected: &Ty) -> Ty { | ||
505 | let body = Arc::clone(&self.body); // avoid borrow checker problem | ||
506 | |||
507 | let ty = match &body[pat] { | ||
508 | Pat::Tuple(ref args) => { | ||
509 | let expectations = match *expected { | ||
510 | Ty::Tuple(ref tuple_args) => &**tuple_args, | ||
511 | _ => &[], | ||
512 | }; | ||
513 | let expectations_iter = expectations.iter().chain(repeat(&Ty::Unknown)); | ||
514 | |||
515 | let inner_tys = args | ||
516 | .iter() | ||
517 | .zip(expectations_iter) | ||
518 | .map(|(&pat, ty)| self.infer_pat(pat, ty)) | ||
519 | .collect::<Vec<_>>() | ||
520 | .into(); | ||
521 | |||
522 | Ty::Tuple(inner_tys) | ||
523 | } | ||
524 | Pat::Ref { pat, mutability } => { | ||
525 | let expectation = match *expected { | ||
526 | Ty::Ref(ref sub_ty, exp_mut) => { | ||
527 | if *mutability != exp_mut { | ||
528 | // TODO: emit type error? | ||
529 | } | ||
530 | &**sub_ty | ||
531 | } | ||
532 | _ => &Ty::Unknown, | ||
533 | }; | ||
534 | let subty = self.infer_pat(*pat, expectation); | ||
535 | Ty::Ref(subty.into(), *mutability) | ||
536 | } | ||
537 | Pat::TupleStruct { path: ref p, args: ref subpats } => { | ||
538 | self.infer_tuple_struct_pat(p.as_ref(), subpats, expected) | ||
539 | } | ||
540 | Pat::Struct { path: ref p, args: ref fields } => { | ||
541 | self.infer_struct_pat(p.as_ref(), fields, expected) | ||
542 | } | ||
543 | Pat::Path(path) => { | ||
544 | // TODO use correct resolver for the surrounding expression | ||
545 | let resolver = self.resolver.clone(); | ||
546 | self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) | ||
547 | } | ||
548 | Pat::Bind { mode, name: _name, subpat } => { | ||
549 | let inner_ty = if let Some(subpat) = subpat { | ||
550 | self.infer_pat(*subpat, expected) | ||
551 | } else { | ||
552 | expected.clone() | ||
553 | }; | ||
554 | let inner_ty = self.insert_type_vars_shallow(inner_ty); | ||
555 | |||
556 | let bound_ty = match mode { | ||
557 | BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared), | ||
558 | BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut), | ||
559 | BindingAnnotation::Mutable | BindingAnnotation::Unannotated => inner_ty.clone(), | ||
560 | }; | ||
561 | let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); | ||
562 | self.write_pat_ty(pat, bound_ty); | ||
563 | return inner_ty; | ||
564 | } | ||
565 | _ => Ty::Unknown, | ||
566 | }; | ||
567 | // use a new type variable if we got Ty::Unknown here | ||
568 | let ty = self.insert_type_vars_shallow(ty); | ||
569 | self.unify(&ty, expected); | ||
570 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
571 | self.write_pat_ty(pat, ty.clone()); | ||
572 | ty | ||
573 | } | ||
574 | |||
575 | fn substs_for_method_call( | ||
576 | &mut self, | ||
577 | def_generics: Option<Arc<GenericParams>>, | ||
578 | generic_args: &Option<GenericArgs>, | ||
579 | ) -> Substs { | ||
580 | let (parent_param_count, param_count) = | ||
581 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | ||
582 | let mut substs = Vec::with_capacity(parent_param_count + param_count); | ||
583 | for _ in 0..parent_param_count { | ||
584 | substs.push(Ty::Unknown); | ||
585 | } | ||
586 | // handle provided type arguments | ||
587 | if let Some(generic_args) = generic_args { | ||
588 | // if args are provided, it should be all of them, but we can't rely on that | ||
589 | for arg in generic_args.args.iter().take(param_count) { | ||
590 | match arg { | ||
591 | GenericArg::Type(type_ref) => { | ||
592 | let ty = self.make_ty(type_ref); | ||
593 | substs.push(ty); | ||
594 | } | ||
595 | } | ||
596 | } | ||
597 | }; | ||
598 | let supplied_params = substs.len(); | ||
599 | for _ in supplied_params..parent_param_count + param_count { | ||
600 | substs.push(Ty::Unknown); | ||
601 | } | ||
602 | assert_eq!(substs.len(), parent_param_count + param_count); | ||
603 | Substs(substs.into()) | ||
604 | } | ||
605 | |||
606 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | ||
607 | let body = Arc::clone(&self.body); // avoid borrow checker problem | ||
608 | let ty = match &body[tgt_expr] { | ||
609 | Expr::Missing => Ty::Unknown, | ||
610 | Expr::If { condition, then_branch, else_branch } => { | ||
611 | // if let is desugared to match, so this is always simple if | ||
612 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); | ||
613 | let then_ty = self.infer_expr(*then_branch, expected); | ||
614 | match else_branch { | ||
615 | Some(else_branch) => { | ||
616 | self.infer_expr(*else_branch, expected); | ||
617 | } | ||
618 | None => { | ||
619 | // no else branch -> unit | ||
620 | self.unify(&then_ty, &Ty::unit()); // actually coerce | ||
621 | } | ||
622 | }; | ||
623 | then_ty | ||
624 | } | ||
625 | Expr::Block { statements, tail } => self.infer_block(statements, *tail, expected), | ||
626 | Expr::Loop { body } => { | ||
627 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | ||
628 | // TODO handle break with value | ||
629 | Ty::Never | ||
630 | } | ||
631 | Expr::While { condition, body } => { | ||
632 | // while let is desugared to a match loop, so this is always simple while | ||
633 | self.infer_expr(*condition, &Expectation::has_type(Ty::Bool)); | ||
634 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | ||
635 | Ty::unit() | ||
636 | } | ||
637 | Expr::For { iterable, body, pat } => { | ||
638 | let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | ||
639 | self.infer_pat(*pat, &Ty::Unknown); | ||
640 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | ||
641 | Ty::unit() | ||
642 | } | ||
643 | Expr::Lambda { body, args, arg_types } => { | ||
644 | assert_eq!(args.len(), arg_types.len()); | ||
645 | |||
646 | for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { | ||
647 | let expected = if let Some(type_ref) = arg_type { | ||
648 | let ty = self.make_ty(type_ref); | ||
649 | ty | ||
650 | } else { | ||
651 | Ty::Unknown | ||
652 | }; | ||
653 | self.infer_pat(*arg_pat, &expected); | ||
654 | } | ||
655 | |||
656 | // TODO: infer lambda type etc. | ||
657 | let _body_ty = self.infer_expr(*body, &Expectation::none()); | ||
658 | Ty::Unknown | ||
659 | } | ||
660 | Expr::Call { callee, args } => { | ||
661 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | ||
662 | let (param_tys, ret_ty) = match &callee_ty { | ||
663 | Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), | ||
664 | Ty::FnDef { substs, sig, .. } => { | ||
665 | let ret_ty = sig.output.clone().subst(&substs); | ||
666 | let param_tys = | ||
667 | sig.input.iter().map(|ty| ty.clone().subst(&substs)).collect(); | ||
668 | (param_tys, ret_ty) | ||
669 | } | ||
670 | _ => { | ||
671 | // not callable | ||
672 | // TODO report an error? | ||
673 | (Vec::new(), Ty::Unknown) | ||
674 | } | ||
675 | }; | ||
676 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
677 | for (arg, param) in args.iter().zip(param_iter) { | ||
678 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
679 | } | ||
680 | ret_ty | ||
681 | } | ||
682 | Expr::MethodCall { receiver, args, method_name, generic_args } => { | ||
683 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | ||
684 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | ||
685 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | ||
686 | Some((ty, func)) => { | ||
687 | self.write_method_resolution(tgt_expr, func); | ||
688 | ( | ||
689 | ty, | ||
690 | self.db.type_for_def(func.into(), Namespace::Values), | ||
691 | Some(func.generic_params(self.db)), | ||
692 | ) | ||
693 | } | ||
694 | None => (Ty::Unknown, receiver_ty, None), | ||
695 | }; | ||
696 | let substs = self.substs_for_method_call(def_generics, generic_args); | ||
697 | let method_ty = method_ty.apply_substs(substs); | ||
698 | let method_ty = self.insert_type_vars(method_ty); | ||
699 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | ||
700 | Ty::FnPtr(sig) => { | ||
701 | if !sig.input.is_empty() { | ||
702 | (sig.input[0].clone(), sig.input[1..].to_vec(), sig.output.clone()) | ||
703 | } else { | ||
704 | (Ty::Unknown, Vec::new(), sig.output.clone()) | ||
705 | } | ||
706 | } | ||
707 | Ty::FnDef { substs, sig, .. } => { | ||
708 | let ret_ty = sig.output.clone().subst(&substs); | ||
709 | |||
710 | if !sig.input.is_empty() { | ||
711 | let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs)); | ||
712 | let receiver_ty = arg_iter.next().unwrap(); | ||
713 | (receiver_ty, arg_iter.collect(), ret_ty) | ||
714 | } else { | ||
715 | (Ty::Unknown, Vec::new(), ret_ty) | ||
716 | } | ||
717 | } | ||
718 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
719 | }; | ||
720 | // Apply autoref so the below unification works correctly | ||
721 | let actual_receiver_ty = match expected_receiver_ty { | ||
722 | Ty::Ref(_, mutability) => Ty::Ref(Arc::new(derefed_receiver_ty), mutability), | ||
723 | _ => derefed_receiver_ty, | ||
724 | }; | ||
725 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
726 | |||
727 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
728 | for (arg, param) in args.iter().zip(param_iter) { | ||
729 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
730 | } | ||
731 | ret_ty | ||
732 | } | ||
733 | Expr::Match { expr, arms } => { | ||
734 | let expected = if expected.ty == Ty::Unknown { | ||
735 | Expectation::has_type(self.new_type_var()) | ||
736 | } else { | ||
737 | expected.clone() | ||
738 | }; | ||
739 | let input_ty = self.infer_expr(*expr, &Expectation::none()); | ||
740 | |||
741 | for arm in arms { | ||
742 | for &pat in &arm.pats { | ||
743 | let _pat_ty = self.infer_pat(pat, &input_ty); | ||
744 | } | ||
745 | if let Some(guard_expr) = arm.guard { | ||
746 | self.infer_expr(guard_expr, &Expectation::has_type(Ty::Bool)); | ||
747 | } | ||
748 | self.infer_expr(arm.expr, &expected); | ||
749 | } | ||
750 | |||
751 | expected.ty | ||
752 | } | ||
753 | Expr::Path(p) => { | ||
754 | // TODO this could be more efficient... | ||
755 | let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); | ||
756 | self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) | ||
757 | } | ||
758 | Expr::Continue => Ty::Never, | ||
759 | Expr::Break { expr } => { | ||
760 | if let Some(expr) = expr { | ||
761 | // TODO handle break with value | ||
762 | self.infer_expr(*expr, &Expectation::none()); | ||
763 | } | ||
764 | Ty::Never | ||
765 | } | ||
766 | Expr::Return { expr } => { | ||
767 | if let Some(expr) = expr { | ||
768 | self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); | ||
769 | } | ||
770 | Ty::Never | ||
771 | } | ||
772 | Expr::StructLit { path, fields, spread } => { | ||
773 | let (ty, def_id) = self.resolve_variant(path.as_ref()); | ||
774 | let substs = ty.substs().unwrap_or_else(Substs::empty); | ||
775 | for field in fields { | ||
776 | let field_ty = def_id | ||
777 | .and_then(|it| it.field(self.db, &field.name)) | ||
778 | .map_or(Ty::Unknown, |field| field.ty(self.db)) | ||
779 | .subst(&substs); | ||
780 | self.infer_expr(field.expr, &Expectation::has_type(field_ty)); | ||
781 | } | ||
782 | if let Some(expr) = spread { | ||
783 | self.infer_expr(*expr, &Expectation::has_type(ty.clone())); | ||
784 | } | ||
785 | ty | ||
786 | } | ||
787 | Expr::Field { expr, name } => { | ||
788 | let receiver_ty = self.infer_expr(*expr, &Expectation::none()); | ||
789 | let ty = receiver_ty | ||
790 | .autoderef(self.db) | ||
791 | .find_map(|derefed_ty| match derefed_ty { | ||
792 | Ty::Tuple(fields) => { | ||
793 | let i = name.to_string().parse::<usize>().ok(); | ||
794 | i.and_then(|i| fields.get(i).cloned()) | ||
795 | } | ||
796 | Ty::Adt { def_id: AdtDef::Struct(s), ref substs, .. } => { | ||
797 | s.field(self.db, name).map(|field| { | ||
798 | self.write_field_resolution(tgt_expr, field); | ||
799 | field.ty(self.db).subst(substs) | ||
800 | }) | ||
801 | } | ||
802 | _ => None, | ||
803 | }) | ||
804 | .unwrap_or(Ty::Unknown); | ||
805 | self.insert_type_vars(ty) | ||
806 | } | ||
807 | Expr::Try { expr } => { | ||
808 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | ||
809 | Ty::Unknown | ||
810 | } | ||
811 | Expr::Cast { expr, type_ref } => { | ||
812 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | ||
813 | let cast_ty = self.make_ty(type_ref); | ||
814 | // TODO check the cast... | ||
815 | cast_ty | ||
816 | } | ||
817 | Expr::Ref { expr, mutability } => { | ||
818 | let expectation = if let Ty::Ref(ref subty, expected_mutability) = expected.ty { | ||
819 | if expected_mutability == Mutability::Mut && *mutability == Mutability::Shared { | ||
820 | // TODO: throw type error - expected mut reference but found shared ref, | ||
821 | // which cannot be coerced | ||
822 | } | ||
823 | Expectation::has_type((**subty).clone()) | ||
824 | } else { | ||
825 | Expectation::none() | ||
826 | }; | ||
827 | // TODO reference coercions etc. | ||
828 | let inner_ty = self.infer_expr(*expr, &expectation); | ||
829 | Ty::Ref(Arc::new(inner_ty), *mutability) | ||
830 | } | ||
831 | Expr::UnaryOp { expr, op } => { | ||
832 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | ||
833 | match op { | ||
834 | UnaryOp::Deref => { | ||
835 | if let Some(derefed_ty) = inner_ty.builtin_deref() { | ||
836 | derefed_ty | ||
837 | } else { | ||
838 | // TODO Deref::deref | ||
839 | Ty::Unknown | ||
840 | } | ||
841 | } | ||
842 | UnaryOp::Neg => { | ||
843 | match inner_ty { | ||
844 | Ty::Int(primitive::UncertainIntTy::Unknown) | ||
845 | | Ty::Int(primitive::UncertainIntTy::Signed(..)) | ||
846 | | Ty::Infer(InferTy::IntVar(..)) | ||
847 | | Ty::Infer(InferTy::FloatVar(..)) | ||
848 | | Ty::Float(..) => inner_ty, | ||
849 | // TODO: resolve ops::Neg trait | ||
850 | _ => Ty::Unknown, | ||
851 | } | ||
852 | } | ||
853 | UnaryOp::Not => { | ||
854 | match inner_ty { | ||
855 | Ty::Bool | Ty::Int(_) | Ty::Infer(InferTy::IntVar(..)) => inner_ty, | ||
856 | // TODO: resolve ops::Not trait for inner_ty | ||
857 | _ => Ty::Unknown, | ||
858 | } | ||
859 | } | ||
860 | } | ||
861 | } | ||
862 | Expr::BinaryOp { lhs, rhs, op } => match op { | ||
863 | Some(op) => { | ||
864 | let lhs_expectation = match op { | ||
865 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => { | ||
866 | Expectation::has_type(Ty::Bool) | ||
867 | } | ||
868 | _ => Expectation::none(), | ||
869 | }; | ||
870 | let lhs_ty = self.infer_expr(*lhs, &lhs_expectation); | ||
871 | // TODO: find implementation of trait corresponding to operation | ||
872 | // symbol and resolve associated `Output` type | ||
873 | let rhs_expectation = op::binary_op_rhs_expectation(*op, lhs_ty); | ||
874 | let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(rhs_expectation)); | ||
875 | |||
876 | // TODO: similar as above, return ty is often associated trait type | ||
877 | op::binary_op_return_ty(*op, rhs_ty) | ||
878 | } | ||
879 | _ => Ty::Unknown, | ||
880 | }, | ||
881 | Expr::Tuple { exprs } => { | ||
882 | let mut ty_vec = Vec::with_capacity(exprs.len()); | ||
883 | for arg in exprs.iter() { | ||
884 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())); | ||
885 | } | ||
886 | |||
887 | Ty::Tuple(Arc::from(ty_vec)) | ||
888 | } | ||
889 | Expr::Array { exprs } => { | ||
890 | let elem_ty = match &expected.ty { | ||
891 | Ty::Slice(inner) | Ty::Array(inner) => Ty::clone(&inner), | ||
892 | _ => self.new_type_var(), | ||
893 | }; | ||
894 | |||
895 | for expr in exprs.iter() { | ||
896 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); | ||
897 | } | ||
898 | |||
899 | Ty::Array(Arc::new(elem_ty)) | ||
900 | } | ||
901 | Expr::Literal(lit) => match lit { | ||
902 | Literal::Bool(..) => Ty::Bool, | ||
903 | Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), | ||
904 | Literal::ByteString(..) => { | ||
905 | let byte_type = Arc::new(Ty::Int(primitive::UncertainIntTy::Unsigned( | ||
906 | primitive::UintTy::U8, | ||
907 | ))); | ||
908 | let slice_type = Arc::new(Ty::Slice(byte_type)); | ||
909 | Ty::Ref(slice_type, Mutability::Shared) | ||
910 | } | ||
911 | Literal::Char(..) => Ty::Char, | ||
912 | Literal::Int(_v, ty) => Ty::Int(*ty), | ||
913 | Literal::Float(_v, ty) => Ty::Float(*ty), | ||
914 | }, | ||
915 | }; | ||
916 | // use a new type variable if we got Ty::Unknown here | ||
917 | let ty = self.insert_type_vars_shallow(ty); | ||
918 | self.unify(&ty, &expected.ty); | ||
919 | let ty = self.resolve_ty_as_possible(&mut vec![], ty); | ||
920 | self.write_expr_ty(tgt_expr, ty.clone()); | ||
921 | ty | ||
922 | } | ||
923 | |||
924 | fn infer_block( | ||
925 | &mut self, | ||
926 | statements: &[Statement], | ||
927 | tail: Option<ExprId>, | ||
928 | expected: &Expectation, | ||
929 | ) -> Ty { | ||
930 | for stmt in statements { | ||
931 | match stmt { | ||
932 | Statement::Let { pat, type_ref, initializer } => { | ||
933 | let decl_ty = | ||
934 | type_ref.as_ref().map(|tr| self.make_ty(tr)).unwrap_or(Ty::Unknown); | ||
935 | let decl_ty = self.insert_type_vars(decl_ty); | ||
936 | let ty = if let Some(expr) = initializer { | ||
937 | let expr_ty = self.infer_expr(*expr, &Expectation::has_type(decl_ty)); | ||
938 | expr_ty | ||
939 | } else { | ||
940 | decl_ty | ||
941 | }; | ||
942 | |||
943 | self.infer_pat(*pat, &ty); | ||
944 | } | ||
945 | Statement::Expr(expr) => { | ||
946 | self.infer_expr(*expr, &Expectation::none()); | ||
947 | } | ||
948 | } | ||
949 | } | ||
950 | let ty = if let Some(expr) = tail { self.infer_expr(expr, expected) } else { Ty::unit() }; | ||
951 | ty | ||
952 | } | ||
953 | |||
954 | fn collect_fn_signature(&mut self, signature: &FnSignature) { | ||
955 | let body = Arc::clone(&self.body); // avoid borrow checker problem | ||
956 | for (type_ref, pat) in signature.params().iter().zip(body.params()) { | ||
957 | let ty = self.make_ty(type_ref); | ||
958 | |||
959 | self.infer_pat(*pat, &ty); | ||
960 | } | ||
961 | self.return_ty = self.make_ty(signature.ret_type()); | ||
962 | } | ||
963 | |||
964 | fn infer_body(&mut self) { | ||
965 | self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone())); | ||
966 | } | ||
967 | } | ||
968 | |||
969 | /// The ID of a type variable. | ||
970 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
971 | pub struct TypeVarId(u32); | ||
972 | |||
973 | impl UnifyKey for TypeVarId { | ||
974 | type Value = TypeVarValue; | ||
975 | |||
976 | fn index(&self) -> u32 { | ||
977 | self.0 | ||
978 | } | ||
979 | |||
980 | fn from_index(i: u32) -> Self { | ||
981 | TypeVarId(i) | ||
982 | } | ||
983 | |||
984 | fn tag() -> &'static str { | ||
985 | "TypeVarId" | ||
986 | } | ||
987 | } | ||
988 | |||
989 | /// The value of a type variable: either we already know the type, or we don't | ||
990 | /// know it yet. | ||
991 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
992 | pub enum TypeVarValue { | ||
993 | Known(Ty), | ||
994 | Unknown, | ||
995 | } | ||
996 | |||
997 | impl TypeVarValue { | ||
998 | fn known(&self) -> Option<&Ty> { | ||
999 | match self { | ||
1000 | TypeVarValue::Known(ty) => Some(ty), | ||
1001 | TypeVarValue::Unknown => None, | ||
1002 | } | ||
1003 | } | ||
1004 | } | ||
1005 | |||
1006 | impl UnifyValue for TypeVarValue { | ||
1007 | type Error = NoError; | ||
1008 | |||
1009 | fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> { | ||
1010 | match (value1, value2) { | ||
1011 | // We should never equate two type variables, both of which have | ||
1012 | // known types. Instead, we recursively equate those types. | ||
1013 | (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!( | ||
1014 | "equating two type variables, both of which have known types: {:?} and {:?}", | ||
1015 | t1, t2 | ||
1016 | ), | ||
1017 | |||
1018 | // If one side is known, prefer that one. | ||
1019 | (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), | ||
1020 | (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()), | ||
1021 | |||
1022 | (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown), | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | /// The kinds of placeholders we need during type inference. There's separate | ||
1028 | /// values for general types, and for integer and float variables. The latter | ||
1029 | /// two are used for inference of literal values (e.g. `100` could be one of | ||
1030 | /// several integer types). | ||
1031 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | ||
1032 | pub enum InferTy { | ||
1033 | TypeVar(TypeVarId), | ||
1034 | IntVar(TypeVarId), | ||
1035 | FloatVar(TypeVarId), | ||
1036 | } | ||
1037 | |||
1038 | impl InferTy { | ||
1039 | fn to_inner(self) -> TypeVarId { | ||
1040 | match self { | ||
1041 | InferTy::TypeVar(ty) | InferTy::IntVar(ty) | InferTy::FloatVar(ty) => ty, | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | fn fallback_value(self) -> Ty { | ||
1046 | match self { | ||
1047 | InferTy::TypeVar(..) => Ty::Unknown, | ||
1048 | InferTy::IntVar(..) => { | ||
1049 | Ty::Int(primitive::UncertainIntTy::Signed(primitive::IntTy::I32)) | ||
1050 | } | ||
1051 | InferTy::FloatVar(..) => { | ||
1052 | Ty::Float(primitive::UncertainFloatTy::Known(primitive::FloatTy::F64)) | ||
1053 | } | ||
1054 | } | ||
1055 | } | ||
1056 | } | ||
1057 | |||
1058 | /// When inferring an expression, we propagate downward whatever type hint we | ||
1059 | /// are able in the form of an `Expectation`. | ||
1060 | #[derive(Clone, PartialEq, Eq, Debug)] | ||
1061 | struct Expectation { | ||
1062 | ty: Ty, | ||
1063 | // TODO: In some cases, we need to be aware whether the expectation is that | ||
1064 | // the type match exactly what we passed, or whether it just needs to be | ||
1065 | // coercible to the expected type. See Expectation::rvalue_hint in rustc. | ||
1066 | } | ||
1067 | |||
1068 | impl Expectation { | ||
1069 | /// The expectation that the type of the expression needs to equal the given | ||
1070 | /// type. | ||
1071 | fn has_type(ty: Ty) -> Self { | ||
1072 | Expectation { ty } | ||
1073 | } | ||
1074 | |||
1075 | /// This expresses no expectation on the type. | ||
1076 | fn none() -> Self { | ||
1077 | Expectation { ty: Ty::Unknown } | ||
1078 | } | ||
1079 | } | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs new file mode 100644 index 000000000..cc9e0fd40 --- /dev/null +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -0,0 +1,318 @@ | |||
1 | //! Methods for lowering the HIR to types. There are two main cases here: | ||
2 | //! | ||
3 | //! - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a | ||
4 | //! type: The entry point for this is `Ty::from_hir`. | ||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | ||
6 | //! | ||
7 | //! This usually involves resolving names, collecting generic arguments etc. | ||
8 | |||
9 | use std::sync::Arc; | ||
10 | |||
11 | use crate::{ | ||
12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | ||
13 | ModuleDef, | ||
14 | HirDatabase, | ||
15 | type_ref::TypeRef, | ||
16 | name::KnownName, | ||
17 | nameres::Namespace, | ||
18 | resolve::{Resolver, Resolution}, | ||
19 | path::GenericArg, | ||
20 | generics::GenericParams, | ||
21 | adt::VariantDef, | ||
22 | }; | ||
23 | use super::{Ty, primitive, FnSig, Substs}; | ||
24 | |||
25 | impl Ty { | ||
26 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | ||
27 | match type_ref { | ||
28 | TypeRef::Never => Ty::Never, | ||
29 | TypeRef::Tuple(inner) => { | ||
30 | let inner_tys = | ||
31 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | ||
32 | Ty::Tuple(inner_tys.into()) | ||
33 | } | ||
34 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | ||
35 | TypeRef::RawPtr(inner, mutability) => { | ||
36 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
37 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | ||
38 | } | ||
39 | TypeRef::Array(inner) => { | ||
40 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
41 | Ty::Array(Arc::new(inner_ty)) | ||
42 | } | ||
43 | TypeRef::Slice(inner) => { | ||
44 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
45 | Ty::Slice(Arc::new(inner_ty)) | ||
46 | } | ||
47 | TypeRef::Reference(inner, mutability) => { | ||
48 | let inner_ty = Ty::from_hir(db, resolver, inner); | ||
49 | Ty::Ref(Arc::new(inner_ty), *mutability) | ||
50 | } | ||
51 | TypeRef::Placeholder => Ty::Unknown, | ||
52 | TypeRef::Fn(params) => { | ||
53 | let mut inner_tys = | ||
54 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | ||
55 | let return_ty = | ||
56 | inner_tys.pop().expect("TypeRef::Fn should always have at least return type"); | ||
57 | let sig = FnSig { input: inner_tys, output: return_ty }; | ||
58 | Ty::FnPtr(Arc::new(sig)) | ||
59 | } | ||
60 | TypeRef::Error => Ty::Unknown, | ||
61 | } | ||
62 | } | ||
63 | |||
64 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { | ||
65 | if let Some(name) = path.as_ident() { | ||
66 | // TODO handle primitive type names in resolver as well? | ||
67 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { | ||
68 | return Ty::Int(int_ty); | ||
69 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { | ||
70 | return Ty::Float(float_ty); | ||
71 | } else if let Some(known) = name.as_known_name() { | ||
72 | match known { | ||
73 | KnownName::Bool => return Ty::Bool, | ||
74 | KnownName::Char => return Ty::Char, | ||
75 | KnownName::Str => return Ty::Str, | ||
76 | _ => {} | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | // Resolve the path (in type namespace) | ||
82 | let resolution = resolver.resolve_path(db, path).take_types(); | ||
83 | |||
84 | let def = match resolution { | ||
85 | Some(Resolution::Def(def)) => def, | ||
86 | Some(Resolution::LocalBinding(..)) => { | ||
87 | // this should never happen | ||
88 | panic!("path resolved to local binding in type ns"); | ||
89 | } | ||
90 | Some(Resolution::GenericParam(idx)) => { | ||
91 | return Ty::Param { | ||
92 | idx, | ||
93 | // TODO: maybe return name in resolution? | ||
94 | name: path | ||
95 | .as_ident() | ||
96 | .expect("generic param should be single-segment path") | ||
97 | .clone(), | ||
98 | }; | ||
99 | } | ||
100 | Some(Resolution::SelfType(impl_block)) => { | ||
101 | return impl_block.target_ty(db); | ||
102 | } | ||
103 | None => return Ty::Unknown, | ||
104 | }; | ||
105 | |||
106 | let typable: TypableDef = match def.into() { | ||
107 | None => return Ty::Unknown, | ||
108 | Some(it) => it, | ||
109 | }; | ||
110 | let ty = db.type_for_def(typable, Namespace::Types); | ||
111 | let substs = Ty::substs_from_path(db, resolver, path, typable); | ||
112 | ty.apply_substs(substs) | ||
113 | } | ||
114 | |||
115 | /// Collect generic arguments from a path into a `Substs`. See also | ||
116 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | ||
117 | pub(super) fn substs_from_path( | ||
118 | db: &impl HirDatabase, | ||
119 | resolver: &Resolver, | ||
120 | path: &Path, | ||
121 | resolved: TypableDef, | ||
122 | ) -> Substs { | ||
123 | let mut substs = Vec::new(); | ||
124 | let last = path.segments.last().expect("path should have at least one segment"); | ||
125 | let (def_generics, segment) = match resolved { | ||
126 | TypableDef::Function(func) => (func.generic_params(db), last), | ||
127 | TypableDef::Struct(s) => (s.generic_params(db), last), | ||
128 | TypableDef::Enum(e) => (e.generic_params(db), last), | ||
129 | TypableDef::EnumVariant(var) => { | ||
130 | // the generic args for an enum variant may be either specified | ||
131 | // on the segment referring to the enum, or on the segment | ||
132 | // referring to the variant. So `Option::<T>::None` and | ||
133 | // `Option::None::<T>` are both allowed (though the former is | ||
134 | // preferred). See also `def_ids_for_path_segments` in rustc. | ||
135 | let len = path.segments.len(); | ||
136 | let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { | ||
137 | // Option::<T>::None | ||
138 | &path.segments[len - 2] | ||
139 | } else { | ||
140 | // Option::None::<T> | ||
141 | last | ||
142 | }; | ||
143 | (var.parent_enum(db).generic_params(db), segment) | ||
144 | } | ||
145 | }; | ||
146 | let parent_param_count = def_generics.count_parent_params(); | ||
147 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | ||
148 | if let Some(generic_args) = &segment.args_and_bindings { | ||
149 | // if args are provided, it should be all of them, but we can't rely on that | ||
150 | let param_count = def_generics.params.len(); | ||
151 | for arg in generic_args.args.iter().take(param_count) { | ||
152 | match arg { | ||
153 | GenericArg::Type(type_ref) => { | ||
154 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
155 | substs.push(ty); | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | } | ||
160 | // add placeholders for args that were not provided | ||
161 | // TODO: handle defaults | ||
162 | let supplied_params = substs.len(); | ||
163 | for _ in supplied_params..def_generics.count_params_including_parent() { | ||
164 | substs.push(Ty::Unknown); | ||
165 | } | ||
166 | assert_eq!(substs.len(), def_generics.count_params_including_parent()); | ||
167 | Substs(substs.into()) | ||
168 | } | ||
169 | } | ||
170 | |||
171 | /// Build the declared type of an item. This depends on the namespace; e.g. for | ||
172 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | ||
173 | /// the constructor function `(usize) -> Foo` which lives in the values | ||
174 | /// namespace. | ||
175 | pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { | ||
176 | match (def, ns) { | ||
177 | (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f), | ||
178 | (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s), | ||
179 | (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), | ||
180 | (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), | ||
181 | (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), | ||
182 | |||
183 | // 'error' cases: | ||
184 | (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, | ||
185 | (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown, | ||
186 | (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown, | ||
187 | } | ||
188 | } | ||
189 | |||
190 | /// Build the type of a specific field of a struct or enum variant. | ||
191 | pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | ||
192 | let parent_def = field.parent_def(db); | ||
193 | let resolver = match parent_def { | ||
194 | VariantDef::Struct(it) => it.resolver(db), | ||
195 | VariantDef::EnumVariant(it) => it.parent_enum(db).resolver(db), | ||
196 | }; | ||
197 | let var_data = parent_def.variant_data(db); | ||
198 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; | ||
199 | Ty::from_hir(db, &resolver, type_ref) | ||
200 | } | ||
201 | |||
202 | /// Build the declared type of a function. This should not need to look at the | ||
203 | /// function body. | ||
204 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | ||
205 | let signature = def.signature(db); | ||
206 | let resolver = def.resolver(db); | ||
207 | let generics = def.generic_params(db); | ||
208 | let name = def.name(db); | ||
209 | let input = | ||
210 | signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | ||
211 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); | ||
212 | let sig = Arc::new(FnSig { input, output }); | ||
213 | let substs = make_substs(&generics); | ||
214 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
215 | } | ||
216 | |||
217 | /// Build the type of a tuple struct constructor. | ||
218 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | ||
219 | let var_data = def.variant_data(db); | ||
220 | let fields = match var_data.fields() { | ||
221 | Some(fields) => fields, | ||
222 | None => return type_for_struct(db, def), // Unit struct | ||
223 | }; | ||
224 | let resolver = def.resolver(db); | ||
225 | let generics = def.generic_params(db); | ||
226 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
227 | let input = fields | ||
228 | .iter() | ||
229 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
230 | .collect::<Vec<_>>(); | ||
231 | let output = type_for_struct(db, def); | ||
232 | let sig = Arc::new(FnSig { input, output }); | ||
233 | let substs = make_substs(&generics); | ||
234 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
235 | } | ||
236 | |||
237 | /// Build the type of a tuple enum variant constructor. | ||
238 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | ||
239 | let var_data = def.variant_data(db); | ||
240 | let fields = match var_data.fields() { | ||
241 | Some(fields) => fields, | ||
242 | None => return type_for_enum(db, def.parent_enum(db)), // Unit variant | ||
243 | }; | ||
244 | let resolver = def.parent_enum(db).resolver(db); | ||
245 | let generics = def.parent_enum(db).generic_params(db); | ||
246 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
247 | let input = fields | ||
248 | .iter() | ||
249 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | ||
250 | .collect::<Vec<_>>(); | ||
251 | let substs = make_substs(&generics); | ||
252 | let output = type_for_enum(db, def.parent_enum(db)).apply_substs(substs.clone()); | ||
253 | let sig = Arc::new(FnSig { input, output }); | ||
254 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
255 | } | ||
256 | |||
257 | fn make_substs(generics: &GenericParams) -> Substs { | ||
258 | Substs( | ||
259 | generics | ||
260 | .params_including_parent() | ||
261 | .into_iter() | ||
262 | .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() }) | ||
263 | .collect::<Vec<_>>() | ||
264 | .into(), | ||
265 | ) | ||
266 | } | ||
267 | |||
268 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | ||
269 | let generics = s.generic_params(db); | ||
270 | Ty::Adt { | ||
271 | def_id: s.into(), | ||
272 | name: s.name(db).unwrap_or_else(Name::missing), | ||
273 | substs: make_substs(&generics), | ||
274 | } | ||
275 | } | ||
276 | |||
277 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | ||
278 | let generics = s.generic_params(db); | ||
279 | Ty::Adt { | ||
280 | def_id: s.into(), | ||
281 | name: s.name(db).unwrap_or_else(Name::missing), | ||
282 | substs: make_substs(&generics), | ||
283 | } | ||
284 | } | ||
285 | |||
286 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
287 | pub enum TypableDef { | ||
288 | Function(Function), | ||
289 | Struct(Struct), | ||
290 | Enum(Enum), | ||
291 | EnumVariant(EnumVariant), | ||
292 | } | ||
293 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); | ||
294 | |||
295 | impl From<ModuleDef> for Option<TypableDef> { | ||
296 | fn from(def: ModuleDef) -> Option<TypableDef> { | ||
297 | let res = match def { | ||
298 | ModuleDef::Function(f) => f.into(), | ||
299 | ModuleDef::Struct(s) => s.into(), | ||
300 | ModuleDef::Enum(e) => e.into(), | ||
301 | ModuleDef::EnumVariant(v) => v.into(), | ||
302 | ModuleDef::Const(_) | ||
303 | | ModuleDef::Static(_) | ||
304 | | ModuleDef::Module(_) | ||
305 | | ModuleDef::Trait(_) | ||
306 | | ModuleDef::Type(_) => return None, | ||
307 | }; | ||
308 | Some(res) | ||
309 | } | ||
310 | } | ||
311 | |||
312 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
313 | pub enum CallableDef { | ||
314 | Function(Function), | ||
315 | Struct(Struct), | ||
316 | EnumVariant(EnumVariant), | ||
317 | } | ||
318 | impl_froms!(CallableDef: Function, Struct, EnumVariant); | ||
diff --git a/crates/ra_hir/src/ty/op.rs b/crates/ra_hir/src/ty/op.rs new file mode 100644 index 000000000..8703cf236 --- /dev/null +++ b/crates/ra_hir/src/ty/op.rs | |||
@@ -0,0 +1,81 @@ | |||
1 | use crate::expr::BinaryOp; | ||
2 | use super::{Ty, InferTy}; | ||
3 | |||
4 | pub(super) fn binary_op_return_ty(op: BinaryOp, rhs_ty: Ty) -> Ty { | ||
5 | match op { | ||
6 | BinaryOp::BooleanOr | ||
7 | | BinaryOp::BooleanAnd | ||
8 | | BinaryOp::EqualityTest | ||
9 | | BinaryOp::NegatedEqualityTest | ||
10 | | BinaryOp::LesserEqualTest | ||
11 | | BinaryOp::GreaterEqualTest | ||
12 | | BinaryOp::LesserTest | ||
13 | | BinaryOp::GreaterTest => Ty::Bool, | ||
14 | BinaryOp::Assignment | ||
15 | | BinaryOp::AddAssign | ||
16 | | BinaryOp::SubAssign | ||
17 | | BinaryOp::DivAssign | ||
18 | | BinaryOp::MulAssign | ||
19 | | BinaryOp::RemAssign | ||
20 | | BinaryOp::ShrAssign | ||
21 | | BinaryOp::ShlAssign | ||
22 | | BinaryOp::BitAndAssign | ||
23 | | BinaryOp::BitOrAssign | ||
24 | | BinaryOp::BitXorAssign => Ty::unit(), | ||
25 | BinaryOp::Addition | ||
26 | | BinaryOp::Subtraction | ||
27 | | BinaryOp::Multiplication | ||
28 | | BinaryOp::Division | ||
29 | | BinaryOp::Remainder | ||
30 | | BinaryOp::LeftShift | ||
31 | | BinaryOp::RightShift | ||
32 | | BinaryOp::BitwiseAnd | ||
33 | | BinaryOp::BitwiseOr | ||
34 | | BinaryOp::BitwiseXor => match rhs_ty { | ||
35 | Ty::Int(..) | ||
36 | | Ty::Float(..) | ||
37 | | Ty::Infer(InferTy::IntVar(..)) | ||
38 | | Ty::Infer(InferTy::FloatVar(..)) => rhs_ty, | ||
39 | _ => Ty::Unknown, | ||
40 | }, | ||
41 | BinaryOp::RangeRightOpen | BinaryOp::RangeRightClosed => Ty::Unknown, | ||
42 | } | ||
43 | } | ||
44 | |||
45 | pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | ||
46 | match op { | ||
47 | BinaryOp::BooleanAnd | BinaryOp::BooleanOr => Ty::Bool, | ||
48 | BinaryOp::Assignment | BinaryOp::EqualityTest => match lhs_ty { | ||
49 | Ty::Int(..) | Ty::Float(..) | Ty::Str | Ty::Char | Ty::Bool => lhs_ty, | ||
50 | _ => Ty::Unknown, | ||
51 | }, | ||
52 | BinaryOp::LesserEqualTest | ||
53 | | BinaryOp::GreaterEqualTest | ||
54 | | BinaryOp::LesserTest | ||
55 | | BinaryOp::GreaterTest | ||
56 | | BinaryOp::AddAssign | ||
57 | | BinaryOp::SubAssign | ||
58 | | BinaryOp::DivAssign | ||
59 | | BinaryOp::MulAssign | ||
60 | | BinaryOp::RemAssign | ||
61 | | BinaryOp::ShrAssign | ||
62 | | BinaryOp::ShlAssign | ||
63 | | BinaryOp::BitAndAssign | ||
64 | | BinaryOp::BitOrAssign | ||
65 | | BinaryOp::BitXorAssign | ||
66 | | BinaryOp::Addition | ||
67 | | BinaryOp::Subtraction | ||
68 | | BinaryOp::Multiplication | ||
69 | | BinaryOp::Division | ||
70 | | BinaryOp::Remainder | ||
71 | | BinaryOp::LeftShift | ||
72 | | BinaryOp::RightShift | ||
73 | | BinaryOp::BitwiseAnd | ||
74 | | BinaryOp::BitwiseOr | ||
75 | | BinaryOp::BitwiseXor => match lhs_ty { | ||
76 | Ty::Int(..) | Ty::Float(..) => lhs_ty, | ||
77 | _ => Ty::Unknown, | ||
78 | }, | ||
79 | _ => Ty::Unknown, | ||
80 | } | ||
81 | } | ||