aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src/infer.rs')
-rw-r--r--crates/ra_hir_ty/src/infer.rs803
1 files changed, 0 insertions, 803 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
deleted file mode 100644
index 3d12039a6..000000000
--- a/crates/ra_hir_ty/src/infer.rs
+++ /dev/null
@@ -1,803 +0,0 @@
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
16use std::borrow::Cow;
17use std::mem;
18use std::ops::Index;
19use std::sync::Arc;
20
21use hir_def::{
22 body::Body,
23 data::{ConstData, FunctionData, StaticData},
24 expr::{BindingAnnotation, ExprId, PatId},
25 lang_item::LangItemTarget,
26 path::{path, Path},
27 resolver::{HasResolver, Resolver, TypeNs},
28 type_ref::{Mutability, TypeRef},
29 AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId,
30 TypeAliasId, VariantId,
31};
32use hir_expand::{diagnostics::DiagnosticSink, name::name};
33use ra_arena::map::ArenaMap;
34use ra_prof::profile;
35use ra_syntax::SmolStr;
36use rustc_hash::FxHashMap;
37use stdx::impl_from;
38
39use super::{
40 primitive::{FloatTy, IntTy},
41 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
42 InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
43};
44use crate::{
45 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
46};
47
48pub(crate) use unify::unify;
49
50macro_rules! ty_app {
51 ($ctor:pat, $param:pat) => {
52 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
53 };
54 ($ctor:pat) => {
55 ty_app!($ctor, _)
56 };
57}
58
59mod unify;
60mod path;
61mod expr;
62mod pat;
63mod coerce;
64
65/// The entry point of type inference.
66pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
67 let _p = profile("infer_query");
68 let resolver = def.resolver(db.upcast());
69 let mut ctx = InferenceContext::new(db, def, resolver);
70
71 match def {
72 DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
73 DefWithBodyId::FunctionId(f) => ctx.collect_fn(&db.function_data(f)),
74 DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
75 }
76
77 ctx.infer_body();
78
79 Arc::new(ctx.resolve_all())
80}
81
82#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
83enum ExprOrPatId {
84 ExprId(ExprId),
85 PatId(PatId),
86}
87impl_from!(ExprId, PatId for ExprOrPatId);
88
89/// Binding modes inferred for patterns.
90/// https://doc.rust-lang.org/reference/patterns.html#binding-modes
91#[derive(Copy, Clone, Debug, Eq, PartialEq)]
92enum BindingMode {
93 Move,
94 Ref(Mutability),
95}
96
97impl BindingMode {
98 pub fn convert(annotation: BindingAnnotation) -> BindingMode {
99 match annotation {
100 BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,
101 BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared),
102 BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),
103 }
104 }
105}
106
107impl Default for BindingMode {
108 fn default() -> Self {
109 BindingMode::Move
110 }
111}
112
113/// A mismatch between an expected and an inferred type.
114#[derive(Clone, PartialEq, Eq, Debug, Hash)]
115pub struct TypeMismatch {
116 pub expected: Ty,
117 pub actual: Ty,
118}
119
120/// The result of type inference: A mapping from expressions and patterns to types.
121#[derive(Clone, PartialEq, Eq, Debug, Default)]
122pub struct InferenceResult {
123 /// For each method call expr, records the function it resolves to.
124 method_resolutions: FxHashMap<ExprId, FunctionId>,
125 /// For each field access expr, records the field it resolves to.
126 field_resolutions: FxHashMap<ExprId, FieldId>,
127 /// For each field in record literal, records the field it resolves to.
128 record_field_resolutions: FxHashMap<ExprId, FieldId>,
129 record_field_pat_resolutions: FxHashMap<PatId, FieldId>,
130 /// For each struct literal, records the variant it resolves to.
131 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
132 /// For each associated item record what it resolves to
133 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
134 diagnostics: Vec<InferenceDiagnostic>,
135 pub type_of_expr: ArenaMap<ExprId, Ty>,
136 pub type_of_pat: ArenaMap<PatId, Ty>,
137 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
138}
139
140impl InferenceResult {
141 pub fn method_resolution(&self, expr: ExprId) -> Option<FunctionId> {
142 self.method_resolutions.get(&expr).copied()
143 }
144 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
145 self.field_resolutions.get(&expr).copied()
146 }
147 pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> {
148 self.record_field_resolutions.get(&expr).copied()
149 }
150 pub fn record_field_pat_resolution(&self, pat: PatId) -> Option<FieldId> {
151 self.record_field_pat_resolutions.get(&pat).copied()
152 }
153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
154 self.variant_resolutions.get(&id.into()).copied()
155 }
156 pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {
157 self.variant_resolutions.get(&id.into()).copied()
158 }
159 pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<AssocItemId> {
160 self.assoc_resolutions.get(&id.into()).copied()
161 }
162 pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<AssocItemId> {
163 self.assoc_resolutions.get(&id.into()).copied()
164 }
165 pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
166 self.type_mismatches.get(expr)
167 }
168 pub fn add_diagnostics(
169 &self,
170 db: &dyn HirDatabase,
171 owner: DefWithBodyId,
172 sink: &mut DiagnosticSink,
173 ) {
174 self.diagnostics.iter().for_each(|it| it.add_to(db, owner, sink))
175 }
176}
177
178impl Index<ExprId> for InferenceResult {
179 type Output = Ty;
180
181 fn index(&self, expr: ExprId) -> &Ty {
182 self.type_of_expr.get(expr).unwrap_or(&Ty::Unknown)
183 }
184}
185
186impl Index<PatId> for InferenceResult {
187 type Output = Ty;
188
189 fn index(&self, pat: PatId) -> &Ty {
190 self.type_of_pat.get(pat).unwrap_or(&Ty::Unknown)
191 }
192}
193
194/// The inference context contains all information needed during type inference.
195#[derive(Clone, Debug)]
196struct InferenceContext<'a> {
197 db: &'a dyn HirDatabase,
198 owner: DefWithBodyId,
199 body: Arc<Body>,
200 resolver: Resolver,
201 table: unify::InferenceTable,
202 trait_env: Arc<TraitEnvironment>,
203 obligations: Vec<Obligation>,
204 result: InferenceResult,
205 /// The return type of the function being inferred, or the closure if we're
206 /// currently within one.
207 ///
208 /// We might consider using a nested inference context for checking
209 /// closures, but currently this is the only field that will change there,
210 /// so it doesn't make sense.
211 return_ty: Ty,
212 diverges: Diverges,
213 breakables: Vec<BreakableContext>,
214}
215
216#[derive(Clone, Debug)]
217struct BreakableContext {
218 pub may_break: bool,
219 pub break_ty: Ty,
220 pub label: Option<name::Name>,
221}
222
223fn find_breakable<'c>(
224 ctxs: &'c mut [BreakableContext],
225 label: Option<&name::Name>,
226) -> Option<&'c mut BreakableContext> {
227 match label {
228 Some(_) => ctxs.iter_mut().rev().find(|ctx| ctx.label.as_ref() == label),
229 None => ctxs.last_mut(),
230 }
231}
232
233impl<'a> InferenceContext<'a> {
234 fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self {
235 InferenceContext {
236 result: InferenceResult::default(),
237 table: unify::InferenceTable::new(),
238 obligations: Vec::default(),
239 return_ty: Ty::Unknown, // set in collect_fn_signature
240 trait_env: TraitEnvironment::lower(db, &resolver),
241 db,
242 owner,
243 body: db.body(owner),
244 resolver,
245 diverges: Diverges::Maybe,
246 breakables: Vec::new(),
247 }
248 }
249
250 fn resolve_all(mut self) -> InferenceResult {
251 // FIXME resolve obligations as well (use Guidance if necessary)
252 let mut result = std::mem::take(&mut self.result);
253 for ty in result.type_of_expr.values_mut() {
254 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
255 *ty = resolved;
256 }
257 for ty in result.type_of_pat.values_mut() {
258 let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
259 *ty = resolved;
260 }
261 result
262 }
263
264 fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) {
265 self.result.type_of_expr.insert(expr, ty);
266 }
267
268 fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId) {
269 self.result.method_resolutions.insert(expr, func);
270 }
271
272 fn write_field_resolution(&mut self, expr: ExprId, field: FieldId) {
273 self.result.field_resolutions.insert(expr, field);
274 }
275
276 fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
277 self.result.variant_resolutions.insert(id, variant);
278 }
279
280 fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId) {
281 self.result.assoc_resolutions.insert(id, item);
282 }
283
284 fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
285 self.result.type_of_pat.insert(pat, ty);
286 }
287
288 fn push_diagnostic(&mut self, diagnostic: InferenceDiagnostic) {
289 self.result.diagnostics.push(diagnostic);
290 }
291
292 fn make_ty_with_mode(
293 &mut self,
294 type_ref: &TypeRef,
295 impl_trait_mode: ImplTraitLoweringMode,
296 ) -> Ty {
297 // FIXME use right resolver for block
298 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
299 .with_impl_trait_mode(impl_trait_mode);
300 let ty = Ty::from_hir(&ctx, type_ref);
301 let ty = self.insert_type_vars(ty);
302 self.normalize_associated_types_in(ty)
303 }
304
305 fn make_ty(&mut self, type_ref: &TypeRef) -> Ty {
306 self.make_ty_with_mode(type_ref, ImplTraitLoweringMode::Disallowed)
307 }
308
309 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
310 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
311 match ty {
312 Ty::Unknown => self.table.new_type_var(),
313 _ => ty,
314 }
315 }
316
317 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
318 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty))
319 }
320
321 fn resolve_obligations_as_possible(&mut self) {
322 let obligations = mem::replace(&mut self.obligations, Vec::new());
323 for obligation in obligations {
324 let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone());
325 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
326 let solution =
327 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
328
329 match solution {
330 Some(Solution::Unique(substs)) => {
331 canonicalized.apply_solution(self, substs.0);
332 }
333 Some(Solution::Ambig(Guidance::Definite(substs))) => {
334 canonicalized.apply_solution(self, substs.0);
335 self.obligations.push(obligation);
336 }
337 Some(_) => {
338 // FIXME use this when trying to resolve everything at the end
339 self.obligations.push(obligation);
340 }
341 None => {
342 // FIXME obligation cannot be fulfilled => diagnostic
343 }
344 };
345 }
346 }
347
348 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
349 self.table.unify(ty1, ty2)
350 }
351
352 /// Resolves the type as far as currently possible, replacing type variables
353 /// by their known types. All types returned by the infer_* functions should
354 /// be resolved as far as possible, i.e. contain no type variables with
355 /// known type.
356 fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
357 self.resolve_obligations_as_possible();
358
359 self.table.resolve_ty_as_possible(ty)
360 }
361
362 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
363 self.table.resolve_ty_shallow(ty)
364 }
365
366 fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
367 self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
368 }
369
370 fn resolve_associated_type_with_params(
371 &mut self,
372 inner_ty: Ty,
373 assoc_ty: Option<TypeAliasId>,
374 params: &[Ty],
375 ) -> Ty {
376 match assoc_ty {
377 Some(res_assoc_ty) => {
378 let trait_ = match res_assoc_ty.lookup(self.db.upcast()).container {
379 hir_def::AssocContainerId::TraitId(trait_) => trait_,
380 _ => panic!("resolve_associated_type called with non-associated type"),
381 };
382 let ty = self.table.new_type_var();
383 let substs = Substs::build_for_def(self.db, res_assoc_ty)
384 .push(inner_ty)
385 .fill(params.iter().cloned())
386 .build();
387 let trait_ref = TraitRef { trait_, substs: substs.clone() };
388 let projection = ProjectionPredicate {
389 ty: ty.clone(),
390 projection_ty: ProjectionTy { associated_ty: res_assoc_ty, parameters: substs },
391 };
392 self.obligations.push(Obligation::Trait(trait_ref));
393 self.obligations.push(Obligation::Projection(projection));
394 self.resolve_ty_as_possible(ty)
395 }
396 None => Ty::Unknown,
397 }
398 }
399
400 /// Recurses through the given type, normalizing associated types mentioned
401 /// in it by replacing them by type variables and registering obligations to
402 /// resolve later. This should be done once for every type we get from some
403 /// type annotation (e.g. from a let type annotation, field type or function
404 /// call). `make_ty` handles this already, but e.g. for field types we need
405 /// to do it as well.
406 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
407 let ty = self.resolve_ty_as_possible(ty);
408 ty.fold(&mut |ty| match ty {
409 Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
410 _ => ty,
411 })
412 }
413
414 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
415 let var = self.table.new_type_var();
416 let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() };
417 let obligation = Obligation::Projection(predicate);
418 self.obligations.push(obligation);
419 var
420 }
421
422 fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
423 let path = match path {
424 Some(path) => path,
425 None => return (Ty::Unknown, None),
426 };
427 let resolver = &self.resolver;
428 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
429 // FIXME: this should resolve assoc items as well, see this example:
430 // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521
431 let (resolution, unresolved) =
432 match resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
433 Some(it) => it,
434 None => return (Ty::Unknown, None),
435 };
436 return match resolution {
437 TypeNs::AdtId(AdtId::StructId(strukt)) => {
438 let substs = Ty::substs_from_path(&ctx, path, strukt.into(), true);
439 let ty = self.db.ty(strukt.into());
440 let ty = self.insert_type_vars(ty.subst(&substs));
441 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
442 }
443 TypeNs::AdtId(AdtId::UnionId(u)) => {
444 let substs = Ty::substs_from_path(&ctx, path, u.into(), true);
445 let ty = self.db.ty(u.into());
446 let ty = self.insert_type_vars(ty.subst(&substs));
447 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
448 }
449 TypeNs::EnumVariantId(var) => {
450 let substs = Ty::substs_from_path(&ctx, path, var.into(), true);
451 let ty = self.db.ty(var.parent.into());
452 let ty = self.insert_type_vars(ty.subst(&substs));
453 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
454 }
455 TypeNs::SelfType(impl_id) => {
456 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
457 let substs = Substs::type_params_for_generics(&generics);
458 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
459 match unresolved {
460 None => {
461 let variant = ty_variant(&ty);
462 (ty, variant)
463 }
464 Some(1) => {
465 let segment = path.mod_path().segments.last().unwrap();
466 // this could be an enum variant or associated type
467 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
468 let enum_data = self.db.enum_data(enum_id);
469 if let Some(local_id) = enum_data.variant(segment) {
470 let variant = EnumVariantId { parent: enum_id, local_id };
471 return (ty, Some(variant.into()));
472 }
473 }
474 // FIXME potentially resolve assoc type
475 (Ty::Unknown, None)
476 }
477 Some(_) => {
478 // FIXME diagnostic
479 (Ty::Unknown, None)
480 }
481 }
482 }
483 TypeNs::TypeAliasId(it) => {
484 let substs = Substs::build_for_def(self.db, it)
485 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
486 .build();
487 let ty = self.db.ty(it.into()).subst(&substs);
488 let variant = ty_variant(&ty);
489 forbid_unresolved_segments((ty, variant), unresolved)
490 }
491 TypeNs::AdtSelfType(_) => {
492 // FIXME this could happen in array size expressions, once we're checking them
493 (Ty::Unknown, None)
494 }
495 TypeNs::GenericParam(_) => {
496 // FIXME potentially resolve assoc type
497 (Ty::Unknown, None)
498 }
499 TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::TraitId(_) => {
500 // FIXME diagnostic
501 (Ty::Unknown, None)
502 }
503 };
504
505 fn forbid_unresolved_segments(
506 result: (Ty, Option<VariantId>),
507 unresolved: Option<usize>,
508 ) -> (Ty, Option<VariantId>) {
509 if unresolved.is_none() {
510 result
511 } else {
512 // FIXME diagnostic
513 (Ty::Unknown, None)
514 }
515 }
516
517 fn ty_variant(ty: &Ty) -> Option<VariantId> {
518 ty.as_adt().and_then(|(adt_id, _)| match adt_id {
519 AdtId::StructId(s) => Some(VariantId::StructId(s)),
520 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
521 AdtId::EnumId(_) => {
522 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
523 None
524 }
525 })
526 }
527 }
528
529 fn collect_const(&mut self, data: &ConstData) {
530 self.return_ty = self.make_ty(&data.type_ref);
531 }
532
533 fn collect_static(&mut self, data: &StaticData) {
534 self.return_ty = self.make_ty(&data.type_ref);
535 }
536
537 fn collect_fn(&mut self, data: &FunctionData) {
538 let body = Arc::clone(&self.body); // avoid borrow checker problem
539 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
540 .with_impl_trait_mode(ImplTraitLoweringMode::Param);
541 let param_tys =
542 data.params.iter().map(|type_ref| Ty::from_hir(&ctx, type_ref)).collect::<Vec<_>>();
543 for (ty, pat) in param_tys.into_iter().zip(body.params.iter()) {
544 let ty = self.insert_type_vars(ty);
545 let ty = self.normalize_associated_types_in(ty);
546
547 self.infer_pat(*pat, &ty, BindingMode::default());
548 }
549 let return_ty = self.make_ty_with_mode(&data.ret_type, ImplTraitLoweringMode::Disallowed); // FIXME implement RPIT
550 self.return_ty = return_ty;
551 }
552
553 fn infer_body(&mut self) {
554 self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone()));
555 }
556
557 fn resolve_lang_item(&self, name: &str) -> Option<LangItemTarget> {
558 let krate = self.resolver.krate()?;
559 let name = SmolStr::new_inline_from_ascii(name.len(), name.as_bytes());
560 self.db.lang_item(krate, name)
561 }
562
563 fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
564 let path = path![core::iter::IntoIterator];
565 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
566 self.db.trait_data(trait_).associated_type_by_name(&name![Item])
567 }
568
569 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
570 let path = path![core::ops::Try];
571 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
572 self.db.trait_data(trait_).associated_type_by_name(&name![Ok])
573 }
574
575 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
576 let trait_ = self.resolve_lang_item("neg")?.as_trait()?;
577 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
578 }
579
580 fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
581 let trait_ = self.resolve_lang_item("not")?.as_trait()?;
582 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
583 }
584
585 fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
586 let trait_ = self.resolve_lang_item("future_trait")?.as_trait()?;
587 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
588 }
589
590 fn resolve_boxed_box(&self) -> Option<AdtId> {
591 let struct_ = self.resolve_lang_item("owned_box")?.as_struct()?;
592 Some(struct_.into())
593 }
594
595 fn resolve_range_full(&self) -> Option<AdtId> {
596 let path = path![core::ops::RangeFull];
597 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
598 Some(struct_.into())
599 }
600
601 fn resolve_range(&self) -> Option<AdtId> {
602 let path = path![core::ops::Range];
603 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
604 Some(struct_.into())
605 }
606
607 fn resolve_range_inclusive(&self) -> Option<AdtId> {
608 let path = path![core::ops::RangeInclusive];
609 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
610 Some(struct_.into())
611 }
612
613 fn resolve_range_from(&self) -> Option<AdtId> {
614 let path = path![core::ops::RangeFrom];
615 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
616 Some(struct_.into())
617 }
618
619 fn resolve_range_to(&self) -> Option<AdtId> {
620 let path = path![core::ops::RangeTo];
621 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
622 Some(struct_.into())
623 }
624
625 fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
626 let path = path![core::ops::RangeToInclusive];
627 let struct_ = self.resolver.resolve_known_struct(self.db.upcast(), &path)?;
628 Some(struct_.into())
629 }
630
631 fn resolve_ops_index(&self) -> Option<TraitId> {
632 self.resolve_lang_item("index")?.as_trait()
633 }
634
635 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
636 let trait_ = self.resolve_ops_index()?;
637 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
638 }
639}
640
641/// The kinds of placeholders we need during type inference. There's separate
642/// values for general types, and for integer and float variables. The latter
643/// two are used for inference of literal values (e.g. `100` could be one of
644/// several integer types).
645#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
646pub enum InferTy {
647 TypeVar(unify::TypeVarId),
648 IntVar(unify::TypeVarId),
649 FloatVar(unify::TypeVarId),
650 MaybeNeverTypeVar(unify::TypeVarId),
651}
652
653impl InferTy {
654 fn to_inner(self) -> unify::TypeVarId {
655 match self {
656 InferTy::TypeVar(ty)
657 | InferTy::IntVar(ty)
658 | InferTy::FloatVar(ty)
659 | InferTy::MaybeNeverTypeVar(ty) => ty,
660 }
661 }
662
663 fn fallback_value(self) -> Ty {
664 match self {
665 InferTy::TypeVar(..) => Ty::Unknown,
666 InferTy::IntVar(..) => Ty::simple(TypeCtor::Int(IntTy::i32())),
667 InferTy::FloatVar(..) => Ty::simple(TypeCtor::Float(FloatTy::f64())),
668 InferTy::MaybeNeverTypeVar(..) => Ty::simple(TypeCtor::Never),
669 }
670 }
671}
672
673/// When inferring an expression, we propagate downward whatever type hint we
674/// are able in the form of an `Expectation`.
675#[derive(Clone, PartialEq, Eq, Debug)]
676struct Expectation {
677 ty: Ty,
678 /// See the `rvalue_hint` method.
679 rvalue_hint: bool,
680}
681
682impl Expectation {
683 /// The expectation that the type of the expression needs to equal the given
684 /// type.
685 fn has_type(ty: Ty) -> Self {
686 Expectation { ty, rvalue_hint: false }
687 }
688
689 /// The following explanation is copied straight from rustc:
690 /// Provides an expectation for an rvalue expression given an *optional*
691 /// hint, which is not required for type safety (the resulting type might
692 /// be checked higher up, as is the case with `&expr` and `box expr`), but
693 /// is useful in determining the concrete type.
694 ///
695 /// The primary use case is where the expected type is a fat pointer,
696 /// like `&[isize]`. For example, consider the following statement:
697 ///
698 /// let x: &[isize] = &[1, 2, 3];
699 ///
700 /// In this case, the expected type for the `&[1, 2, 3]` expression is
701 /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
702 /// expectation `ExpectHasType([isize])`, that would be too strong --
703 /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
704 /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
705 /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
706 /// which still is useful, because it informs integer literals and the like.
707 /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
708 /// for examples of where this comes up,.
709 fn rvalue_hint(ty: Ty) -> Self {
710 Expectation { ty, rvalue_hint: true }
711 }
712
713 /// This expresses no expectation on the type.
714 fn none() -> Self {
715 Expectation { ty: Ty::Unknown, rvalue_hint: false }
716 }
717
718 fn coercion_target(&self) -> &Ty {
719 if self.rvalue_hint {
720 &Ty::Unknown
721 } else {
722 &self.ty
723 }
724 }
725}
726
727#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
728enum Diverges {
729 Maybe,
730 Always,
731}
732
733impl Diverges {
734 fn is_always(self) -> bool {
735 self == Diverges::Always
736 }
737}
738
739impl std::ops::BitAnd for Diverges {
740 type Output = Self;
741 fn bitand(self, other: Self) -> Self {
742 std::cmp::min(self, other)
743 }
744}
745
746impl std::ops::BitOr for Diverges {
747 type Output = Self;
748 fn bitor(self, other: Self) -> Self {
749 std::cmp::max(self, other)
750 }
751}
752
753impl std::ops::BitAndAssign for Diverges {
754 fn bitand_assign(&mut self, other: Self) {
755 *self = *self & other;
756 }
757}
758
759impl std::ops::BitOrAssign for Diverges {
760 fn bitor_assign(&mut self, other: Self) {
761 *self = *self | other;
762 }
763}
764
765mod diagnostics {
766 use hir_def::{expr::ExprId, DefWithBodyId};
767 use hir_expand::diagnostics::DiagnosticSink;
768
769 use crate::{
770 db::HirDatabase,
771 diagnostics::{BreakOutsideOfLoop, NoSuchField},
772 };
773
774 #[derive(Debug, PartialEq, Eq, Clone)]
775 pub(super) enum InferenceDiagnostic {
776 NoSuchField { expr: ExprId, field: usize },
777 BreakOutsideOfLoop { expr: ExprId },
778 }
779
780 impl InferenceDiagnostic {
781 pub(super) fn add_to(
782 &self,
783 db: &dyn HirDatabase,
784 owner: DefWithBodyId,
785 sink: &mut DiagnosticSink,
786 ) {
787 match self {
788 InferenceDiagnostic::NoSuchField { expr, field } => {
789 let (_, source_map) = db.body_with_source_map(owner);
790 let field = source_map.field_syntax(*expr, *field);
791 sink.push(NoSuchField { file: field.file_id, field: field.value })
792 }
793 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
794 let (_, source_map) = db.body_with_source_map(owner);
795 let ptr = source_map
796 .expr_syntax(*expr)
797 .expect("break outside of loop in synthetic syntax");
798 sink.push(BreakOutsideOfLoop { file: ptr.file_id, expr: ptr.value })
799 }
800 }
801 }
802 }
803}