diff options
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 192 |
1 files changed, 83 insertions, 109 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 0ee851a74..f1cebbdb9 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -13,8 +13,6 @@ | |||
13 | //! to certain types. To record this, we use the union-find implementation from | 13 | //! to certain types. To record this, we use the union-find implementation from |
14 | //! the `ena` crate, which is extracted from rustc. | 14 | //! the `ena` crate, which is extracted from rustc. |
15 | 15 | ||
16 | use std::borrow::Cow; | ||
17 | use std::mem; | ||
18 | use std::ops::Index; | 16 | use std::ops::Index; |
19 | use std::sync::Arc; | 17 | use std::sync::Arc; |
20 | 18 | ||
@@ -27,8 +25,8 @@ use hir_def::{ | |||
27 | path::{path, Path}, | 25 | path::{path, Path}, |
28 | resolver::{HasResolver, Resolver, TypeNs}, | 26 | resolver::{HasResolver, Resolver, TypeNs}, |
29 | type_ref::TypeRef, | 27 | type_ref::TypeRef, |
30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, | 28 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup, |
31 | TypeAliasId, VariantId, | 29 | TraitId, TypeAliasId, VariantId, |
32 | }; | 30 | }; |
33 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; | 31 | use hir_expand::{diagnostics::DiagnosticSink, name::name}; |
34 | use la_arena::ArenaMap; | 32 | use la_arena::ArenaMap; |
@@ -36,13 +34,11 @@ use rustc_hash::FxHashMap; | |||
36 | use stdx::impl_from; | 34 | use stdx::impl_from; |
37 | use syntax::SmolStr; | 35 | use syntax::SmolStr; |
38 | 36 | ||
39 | use super::{ | 37 | use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; |
40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, | ||
41 | }; | ||
42 | use crate::{ | 38 | use crate::{ |
43 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, | 39 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
44 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, | 40 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder, |
45 | TyBuilder, TyExt, TyKind, | 41 | TyExt, TyKind, |
46 | }; | 42 | }; |
47 | 43 | ||
48 | // This lint has a false positive here. See the link below for details. | 44 | // This lint has a false positive here. See the link below for details. |
@@ -106,6 +102,14 @@ impl Default for BindingMode { | |||
106 | } | 102 | } |
107 | } | 103 | } |
108 | 104 | ||
105 | #[derive(Debug)] | ||
106 | pub(crate) struct InferOk { | ||
107 | goals: Vec<InEnvironment<Goal>>, | ||
108 | } | ||
109 | #[derive(Debug)] | ||
110 | pub(crate) struct TypeError; | ||
111 | pub(crate) type InferResult = Result<InferOk, TypeError>; | ||
112 | |||
109 | /// A mismatch between an expected and an inferred type. | 113 | /// A mismatch between an expected and an inferred type. |
110 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 114 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
111 | pub struct TypeMismatch { | 115 | pub struct TypeMismatch { |
@@ -217,10 +221,8 @@ struct InferenceContext<'a> { | |||
217 | owner: DefWithBodyId, | 221 | owner: DefWithBodyId, |
218 | body: Arc<Body>, | 222 | body: Arc<Body>, |
219 | resolver: Resolver, | 223 | resolver: Resolver, |
220 | table: unify::InferenceTable, | 224 | table: unify::InferenceTable<'a>, |
221 | trait_env: Arc<TraitEnvironment>, | 225 | trait_env: Arc<TraitEnvironment>, |
222 | obligations: Vec<DomainGoal>, | ||
223 | last_obligations_check: Option<u32>, | ||
224 | result: InferenceResult, | 226 | result: InferenceResult, |
225 | /// The return type of the function being inferred, or the closure if we're | 227 | /// The return type of the function being inferred, or the closure if we're |
226 | /// currently within one. | 228 | /// currently within one. |
@@ -252,15 +254,15 @@ fn find_breakable<'c>( | |||
252 | 254 | ||
253 | impl<'a> InferenceContext<'a> { | 255 | impl<'a> InferenceContext<'a> { |
254 | fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self { | 256 | fn new(db: &'a dyn HirDatabase, owner: DefWithBodyId, resolver: Resolver) -> Self { |
257 | let krate = owner.module(db.upcast()).krate(); | ||
258 | let trait_env = owner | ||
259 | .as_generic_def_id() | ||
260 | .map_or_else(|| Arc::new(TraitEnvironment::empty(krate)), |d| db.trait_environment(d)); | ||
255 | InferenceContext { | 261 | InferenceContext { |
256 | result: InferenceResult::default(), | 262 | result: InferenceResult::default(), |
257 | table: unify::InferenceTable::new(), | 263 | table: unify::InferenceTable::new(db, trait_env.clone()), |
258 | obligations: Vec::default(), | 264 | trait_env, |
259 | last_obligations_check: None, | ||
260 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature | 265 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature |
261 | trait_env: owner | ||
262 | .as_generic_def_id() | ||
263 | .map_or_else(Default::default, |d| db.trait_environment(d)), | ||
264 | db, | 266 | db, |
265 | owner, | 267 | owner, |
266 | body: db.body(owner), | 268 | body: db.body(owner), |
@@ -271,19 +273,25 @@ impl<'a> InferenceContext<'a> { | |||
271 | } | 273 | } |
272 | 274 | ||
273 | fn err_ty(&self) -> Ty { | 275 | fn err_ty(&self) -> Ty { |
274 | TyKind::Error.intern(&Interner) | 276 | self.result.standard_types.unknown.clone() |
275 | } | 277 | } |
276 | 278 | ||
277 | fn resolve_all(mut self) -> InferenceResult { | 279 | fn resolve_all(mut self) -> InferenceResult { |
278 | // FIXME resolve obligations as well (use Guidance if necessary) | 280 | // FIXME resolve obligations as well (use Guidance if necessary) |
281 | self.table.resolve_obligations_as_possible(); | ||
282 | |||
283 | // make sure diverging type variables are marked as such | ||
284 | self.table.propagate_diverging_flag(); | ||
279 | let mut result = std::mem::take(&mut self.result); | 285 | let mut result = std::mem::take(&mut self.result); |
280 | for ty in result.type_of_expr.values_mut() { | 286 | for ty in result.type_of_expr.values_mut() { |
281 | let resolved = self.table.resolve_ty_completely(ty.clone()); | 287 | *ty = self.table.resolve_ty_completely(ty.clone()); |
282 | *ty = resolved; | ||
283 | } | 288 | } |
284 | for ty in result.type_of_pat.values_mut() { | 289 | for ty in result.type_of_pat.values_mut() { |
285 | let resolved = self.table.resolve_ty_completely(ty.clone()); | 290 | *ty = self.table.resolve_ty_completely(ty.clone()); |
286 | *ty = resolved; | 291 | } |
292 | for mismatch in result.type_mismatches.values_mut() { | ||
293 | mismatch.expected = self.table.resolve_ty_completely(mismatch.expected.clone()); | ||
294 | mismatch.actual = self.table.resolve_ty_completely(mismatch.actual.clone()); | ||
287 | } | 295 | } |
288 | result | 296 | result |
289 | } | 297 | } |
@@ -337,6 +345,14 @@ impl<'a> InferenceContext<'a> { | |||
337 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 345 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
338 | match ty.kind(&Interner) { | 346 | match ty.kind(&Interner) { |
339 | TyKind::Error => self.table.new_type_var(), | 347 | TyKind::Error => self.table.new_type_var(), |
348 | TyKind::InferenceVar(..) => { | ||
349 | let ty_resolved = self.resolve_ty_shallow(&ty); | ||
350 | if ty_resolved.is_unknown() { | ||
351 | self.table.new_type_var() | ||
352 | } else { | ||
353 | ty | ||
354 | } | ||
355 | } | ||
340 | _ => ty, | 356 | _ => ty, |
341 | } | 357 | } |
342 | } | 358 | } |
@@ -346,66 +362,19 @@ impl<'a> InferenceContext<'a> { | |||
346 | } | 362 | } |
347 | 363 | ||
348 | fn resolve_obligations_as_possible(&mut self) { | 364 | fn resolve_obligations_as_possible(&mut self) { |
349 | if self.last_obligations_check == Some(self.table.revision) { | 365 | self.table.resolve_obligations_as_possible(); |
350 | // no change | ||
351 | return; | ||
352 | } | ||
353 | let _span = profile::span("resolve_obligations_as_possible"); | ||
354 | |||
355 | self.last_obligations_check = Some(self.table.revision); | ||
356 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | ||
357 | for obligation in obligations { | ||
358 | let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone()); | ||
359 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | ||
360 | let solution = | ||
361 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | ||
362 | |||
363 | match solution { | ||
364 | Some(Solution::Unique(canonical_subst)) => { | ||
365 | canonicalized.apply_solution( | ||
366 | self, | ||
367 | Canonical { | ||
368 | binders: canonical_subst.binders, | ||
369 | // FIXME: handle constraints | ||
370 | value: canonical_subst.value.subst, | ||
371 | }, | ||
372 | ); | ||
373 | } | ||
374 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
375 | canonicalized.apply_solution(self, substs); | ||
376 | self.obligations.push(obligation); | ||
377 | } | ||
378 | Some(_) => { | ||
379 | // FIXME use this when trying to resolve everything at the end | ||
380 | self.obligations.push(obligation); | ||
381 | } | ||
382 | None => { | ||
383 | // FIXME obligation cannot be fulfilled => diagnostic | ||
384 | } | ||
385 | }; | ||
386 | } | ||
387 | } | 366 | } |
388 | 367 | ||
389 | fn push_obligation(&mut self, o: DomainGoal) { | 368 | fn push_obligation(&mut self, o: DomainGoal) { |
390 | self.obligations.push(o); | 369 | self.table.register_obligation(o.cast(&Interner)); |
391 | self.last_obligations_check = None; | ||
392 | } | 370 | } |
393 | 371 | ||
394 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 372 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
395 | self.table.unify(ty1, ty2) | 373 | self.table.unify(ty1, ty2) |
396 | } | 374 | } |
397 | 375 | ||
398 | /// Resolves the type as far as currently possible, replacing type variables | 376 | fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty { |
399 | /// by their known types. All types returned by the infer_* functions should | ||
400 | /// be resolved as far as possible, i.e. contain no type variables with | ||
401 | /// known type. | ||
402 | fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { | ||
403 | self.resolve_obligations_as_possible(); | 377 | self.resolve_obligations_as_possible(); |
404 | |||
405 | self.table.resolve_ty_as_possible(ty) | ||
406 | } | ||
407 | |||
408 | fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { | ||
409 | self.table.resolve_ty_shallow(ty) | 378 | self.table.resolve_ty_shallow(ty) |
410 | } | 379 | } |
411 | 380 | ||
@@ -439,7 +408,7 @@ impl<'a> InferenceContext<'a> { | |||
439 | }; | 408 | }; |
440 | self.push_obligation(trait_ref.cast(&Interner)); | 409 | self.push_obligation(trait_ref.cast(&Interner)); |
441 | self.push_obligation(alias_eq.cast(&Interner)); | 410 | self.push_obligation(alias_eq.cast(&Interner)); |
442 | self.resolve_ty_as_possible(ty) | 411 | ty |
443 | } | 412 | } |
444 | None => self.err_ty(), | 413 | None => self.err_ty(), |
445 | } | 414 | } |
@@ -452,25 +421,7 @@ impl<'a> InferenceContext<'a> { | |||
452 | /// call). `make_ty` handles this already, but e.g. for field types we need | 421 | /// call). `make_ty` handles this already, but e.g. for field types we need |
453 | /// to do it as well. | 422 | /// to do it as well. |
454 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 423 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
455 | let ty = self.resolve_ty_as_possible(ty); | 424 | self.table.normalize_associated_types_in(ty) |
456 | fold_tys( | ||
457 | ty, | ||
458 | |ty, _| match ty.kind(&Interner) { | ||
459 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | ||
460 | self.normalize_projection_ty(proj_ty.clone()) | ||
461 | } | ||
462 | _ => ty, | ||
463 | }, | ||
464 | DebruijnIndex::INNERMOST, | ||
465 | ) | ||
466 | } | ||
467 | |||
468 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | ||
469 | let var = self.table.new_type_var(); | ||
470 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; | ||
471 | let obligation = alias_eq.cast(&Interner); | ||
472 | self.push_obligation(obligation); | ||
473 | var | ||
474 | } | 425 | } |
475 | 426 | ||
476 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { | 427 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) { |
@@ -720,17 +671,23 @@ impl<'a> InferenceContext<'a> { | |||
720 | /// When inferring an expression, we propagate downward whatever type hint we | 671 | /// When inferring an expression, we propagate downward whatever type hint we |
721 | /// are able in the form of an `Expectation`. | 672 | /// are able in the form of an `Expectation`. |
722 | #[derive(Clone, PartialEq, Eq, Debug)] | 673 | #[derive(Clone, PartialEq, Eq, Debug)] |
723 | struct Expectation { | 674 | enum Expectation { |
724 | ty: Ty, | 675 | None, |
725 | /// See the `rvalue_hint` method. | 676 | HasType(Ty), |
726 | rvalue_hint: bool, | 677 | // Castable(Ty), // rustc has this, we currently just don't propagate an expectation for casts |
678 | RValueLikeUnsized(Ty), | ||
727 | } | 679 | } |
728 | 680 | ||
729 | impl Expectation { | 681 | impl Expectation { |
730 | /// The expectation that the type of the expression needs to equal the given | 682 | /// The expectation that the type of the expression needs to equal the given |
731 | /// type. | 683 | /// type. |
732 | fn has_type(ty: Ty) -> Self { | 684 | fn has_type(ty: Ty) -> Self { |
733 | Expectation { ty, rvalue_hint: false } | 685 | if ty.is_unknown() { |
686 | // FIXME: get rid of this? | ||
687 | Expectation::None | ||
688 | } else { | ||
689 | Expectation::HasType(ty) | ||
690 | } | ||
734 | } | 691 | } |
735 | 692 | ||
736 | /// The following explanation is copied straight from rustc: | 693 | /// The following explanation is copied straight from rustc: |
@@ -754,24 +711,41 @@ impl Expectation { | |||
754 | /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 | 711 | /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 |
755 | /// for examples of where this comes up,. | 712 | /// for examples of where this comes up,. |
756 | fn rvalue_hint(ty: Ty) -> Self { | 713 | fn rvalue_hint(ty: Ty) -> Self { |
757 | Expectation { ty, rvalue_hint: true } | 714 | match ty.strip_references().kind(&Interner) { |
715 | TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty), | ||
716 | _ => Expectation::has_type(ty), | ||
717 | } | ||
758 | } | 718 | } |
759 | 719 | ||
760 | /// This expresses no expectation on the type. | 720 | /// This expresses no expectation on the type. |
761 | fn none() -> Self { | 721 | fn none() -> Self { |
762 | Expectation { | 722 | Expectation::None |
763 | // FIXME | 723 | } |
764 | ty: TyKind::Error.intern(&Interner), | 724 | |
765 | rvalue_hint: false, | 725 | fn resolve(&self, table: &mut unify::InferenceTable) -> Expectation { |
726 | match self { | ||
727 | Expectation::None => Expectation::None, | ||
728 | Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)), | ||
729 | Expectation::RValueLikeUnsized(t) => { | ||
730 | Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t)) | ||
731 | } | ||
766 | } | 732 | } |
767 | } | 733 | } |
768 | 734 | ||
769 | fn coercion_target(&self) -> Ty { | 735 | fn to_option(&self, table: &mut unify::InferenceTable) -> Option<Ty> { |
770 | if self.rvalue_hint { | 736 | match self.resolve(table) { |
771 | // FIXME | 737 | Expectation::None => None, |
772 | TyKind::Error.intern(&Interner) | 738 | Expectation::HasType(t) | |
773 | } else { | 739 | // Expectation::Castable(t) | |
774 | self.ty.clone() | 740 | Expectation::RValueLikeUnsized(t) => Some(t), |
741 | } | ||
742 | } | ||
743 | |||
744 | fn only_has_type(&self, table: &mut unify::InferenceTable) -> Option<Ty> { | ||
745 | match self { | ||
746 | Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)), | ||
747 | // Expectation::Castable(_) | | ||
748 | Expectation::RValueLikeUnsized(_) | Expectation::None => None, | ||
775 | } | 749 | } |
776 | } | 750 | } |
777 | } | 751 | } |