diff options
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 165 |
5 files changed, 101 insertions, 84 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index f1af2a0bd..1f463a425 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -71,12 +71,14 @@ impl<'a> InferenceContext<'a> { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | // Pointer weakening and function to pointer | 73 | // Pointer weakening and function to pointer |
74 | match (from_ty.interned_mut(), to_ty.kind(&Interner)) { | 74 | match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { |
75 | // `*mut T` -> `*const T` | 75 | // `*mut T` -> `*const T` |
76 | (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => { | ||
77 | from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner); | ||
78 | } | ||
76 | // `&mut T` -> `&T` | 79 | // `&mut T` -> `&T` |
77 | (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) | 80 | (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => { |
78 | | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { | 81 | from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner); |
79 | *m1 = *m2; | ||
80 | } | 82 | } |
81 | // `&T` -> `*const T` | 83 | // `&T` -> `*const T` |
82 | // `&mut T` -> `*mut T`/`*const T` | 84 | // `&mut T` -> `*mut T`/`*const T` |
@@ -139,7 +141,7 @@ impl<'a> InferenceContext<'a> { | |||
139 | b.push(from_ty.clone()).push(to_ty.clone()).build() | 141 | b.push(from_ty.clone()).push(to_ty.clone()).build() |
140 | }; | 142 | }; |
141 | 143 | ||
142 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); | 144 | let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner)); |
143 | 145 | ||
144 | let canonicalizer = self.canonicalizer(); | 146 | let canonicalizer = self.canonicalizer(); |
145 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 147 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 9841988c5..cbbfa8b5c 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 6 | use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
@@ -24,7 +24,6 @@ use crate::{ | |||
24 | utils::{generics, Generics}, | 24 | utils::{generics, Generics}, |
25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, | 25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, |
26 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, | 26 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, |
27 | TypeWalk, | ||
28 | }; | 27 | }; |
29 | 28 | ||
30 | use super::{ | 29 | use super::{ |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index f88d5c5d3..a41e8e116 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -122,7 +122,7 @@ impl<'a> InferenceContext<'a> { | |||
122 | let ty = match &body[pat] { | 122 | let ty = match &body[pat] { |
123 | &Pat::Tuple { ref args, ellipsis } => { | 123 | &Pat::Tuple { ref args, ellipsis } => { |
124 | let expectations = match expected.as_tuple() { | 124 | let expectations = match expected.as_tuple() { |
125 | Some(parameters) => &*parameters.interned(), | 125 | Some(parameters) => &*parameters.interned().as_slice(), |
126 | _ => &[], | 126 | _ => &[], |
127 | }; | 127 | }; |
128 | 128 | ||
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index b19d67bb1..f8955aa32 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -11,7 +11,8 @@ use hir_def::{ | |||
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | method_resolution, Interner, Substitution, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId, | 14 | method_resolution, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, |
15 | ValueTyDefId, | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 18 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index d717e3375..a887e20b0 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,17 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; | 5 | use chalk_ir::{ |
6 | cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex, | ||
7 | VariableKind, | ||
8 | }; | ||
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 9 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 10 | ||
8 | use super::{DomainGoal, InferenceContext}; | 11 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 12 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSubst, | 13 | fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, |
11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, | 14 | DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution, |
15 | Ty, TyExt, TyKind, WhereClause, | ||
12 | }; | 16 | }; |
13 | 17 | ||
14 | impl<'a> InferenceContext<'a> { | 18 | impl<'a> InferenceContext<'a> { |
@@ -33,7 +37,10 @@ where | |||
33 | } | 37 | } |
34 | 38 | ||
35 | #[derive(Debug)] | 39 | #[derive(Debug)] |
36 | pub(super) struct Canonicalized<T> { | 40 | pub(super) struct Canonicalized<T> |
41 | where | ||
42 | T: HasInterner<Interner = Interner>, | ||
43 | { | ||
37 | pub(super) value: Canonical<T>, | 44 | pub(super) value: Canonical<T>, |
38 | free_vars: Vec<(InferenceVar, TyVariableKind)>, | 45 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
39 | } | 46 | } |
@@ -47,9 +54,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
47 | }) | 54 | }) |
48 | } | 55 | } |
49 | 56 | ||
50 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 57 | fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>( |
51 | t.fold_binders( | 58 | &mut self, |
52 | &mut |ty, binders| match ty.kind(&Interner) { | 59 | t: T, |
60 | binders: DebruijnIndex, | ||
61 | ) -> T { | ||
62 | fold_tys( | ||
63 | t, | ||
64 | |ty, binders| match ty.kind(&Interner) { | ||
53 | &TyKind::InferenceVar(var, kind) => { | 65 | &TyKind::InferenceVar(var, kind) => { |
54 | let inner = from_inference_var(var); | 66 | let inner = from_inference_var(var); |
55 | if self.var_stack.contains(&inner) { | 67 | if self.var_stack.contains(&inner) { |
@@ -75,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
75 | ) | 87 | ) |
76 | } | 88 | } |
77 | 89 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 90 | fn into_canonicalized<T: HasInterner<Interner = Interner>>( |
91 | self, | ||
92 | result: T, | ||
93 | ) -> Canonicalized<T> { | ||
79 | let kinds = self | 94 | let kinds = self |
80 | .free_vars | 95 | .free_vars |
81 | .iter() | 96 | .iter() |
@@ -102,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
102 | DomainGoal::Holds(wc) => { | 117 | DomainGoal::Holds(wc) => { |
103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 118 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
104 | } | 119 | } |
120 | _ => unimplemented!(), | ||
105 | }; | 121 | }; |
106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) | 122 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
107 | } | 123 | } |
108 | } | 124 | } |
109 | 125 | ||
110 | impl<T> Canonicalized<T> { | 126 | impl<T: HasInterner<Interner = Interner>> Canonicalized<T> { |
111 | pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { | 127 | pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { |
112 | ty.fold_binders( | 128 | crate::fold_free_vars(ty, |bound, _binders| { |
113 | &mut |ty, binders| { | 129 | let (v, k) = self.free_vars[bound.index]; |
114 | if let TyKind::BoundVar(bound) = ty.kind(&Interner) { | 130 | TyKind::InferenceVar(v, k).intern(&Interner) |
115 | if bound.debruijn >= binders { | 131 | }) |
116 | let (v, k) = self.free_vars[bound.index]; | ||
117 | TyKind::InferenceVar(v, k).intern(&Interner) | ||
118 | } else { | ||
119 | ty | ||
120 | } | ||
121 | } else { | ||
122 | ty | ||
123 | } | ||
124 | }, | ||
125 | DebruijnIndex::INNERMOST, | ||
126 | ) | ||
127 | } | 132 | } |
128 | 133 | ||
129 | pub(super) fn apply_solution( | 134 | pub(super) fn apply_solution( |
@@ -135,15 +140,17 @@ impl<T> Canonicalized<T> { | |||
135 | let new_vars = Substitution::from_iter( | 140 | let new_vars = Substitution::from_iter( |
136 | &Interner, | 141 | &Interner, |
137 | solution.binders.iter(&Interner).map(|k| match k.kind { | 142 | solution.binders.iter(&Interner).map(|k| match k.kind { |
138 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), | 143 | VariableKind::Ty(TyVariableKind::General) => { |
139 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), | 144 | ctx.table.new_type_var().cast(&Interner) |
140 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), | 145 | } |
141 | // HACK: Chalk can sometimes return new lifetime variables. We | 146 | VariableKind::Ty(TyVariableKind::Integer) => { |
142 | // want to just skip them, but to not mess up the indices of | 147 | ctx.table.new_integer_var().cast(&Interner) |
143 | // other variables, we'll just create a new type variable in | 148 | } |
144 | // their place instead. This should not matter (we never see the | 149 | VariableKind::Ty(TyVariableKind::Float) => { |
145 | // actual *uses* of the lifetime variable). | 150 | ctx.table.new_float_var().cast(&Interner) |
146 | VariableKind::Lifetime => ctx.table.new_type_var(), | 151 | } |
152 | // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere | ||
153 | VariableKind::Lifetime => static_lifetime().cast(&Interner), | ||
147 | _ => panic!("const variable in solution"), | 154 | _ => panic!("const variable in solution"), |
148 | }), | 155 | }), |
149 | ); | 156 | ); |
@@ -487,55 +494,63 @@ impl InferenceTable { | |||
487 | /// be resolved as far as possible, i.e. contain no type variables with | 494 | /// be resolved as far as possible, i.e. contain no type variables with |
488 | /// known type. | 495 | /// known type. |
489 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 496 | fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
490 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 497 | fold_tys( |
491 | &TyKind::InferenceVar(tv, kind) => { | 498 | ty, |
492 | let inner = from_inference_var(tv); | 499 | |ty, _| match ty.kind(&Interner) { |
493 | if tv_stack.contains(&inner) { | 500 | &TyKind::InferenceVar(tv, kind) => { |
494 | cov_mark::hit!(type_var_cycles_resolve_as_possible); | 501 | let inner = from_inference_var(tv); |
495 | // recursive type | 502 | if tv_stack.contains(&inner) { |
496 | return self.type_variable_table.fallback_value(tv, kind); | 503 | cov_mark::hit!(type_var_cycles_resolve_as_possible); |
497 | } | 504 | // recursive type |
498 | if let Some(known_ty) = | 505 | return self.type_variable_table.fallback_value(tv, kind); |
499 | self.var_unification_table.inlined_probe_value(inner).known() | 506 | } |
500 | { | 507 | if let Some(known_ty) = |
501 | // known_ty may contain other variables that are known by now | 508 | self.var_unification_table.inlined_probe_value(inner).known() |
502 | tv_stack.push(inner); | 509 | { |
503 | let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); | 510 | // known_ty may contain other variables that are known by now |
504 | tv_stack.pop(); | 511 | tv_stack.push(inner); |
505 | result | 512 | let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); |
506 | } else { | 513 | tv_stack.pop(); |
507 | ty | 514 | result |
515 | } else { | ||
516 | ty | ||
517 | } | ||
508 | } | 518 | } |
509 | } | 519 | _ => ty, |
510 | _ => ty, | 520 | }, |
511 | }) | 521 | DebruijnIndex::INNERMOST, |
522 | ) | ||
512 | } | 523 | } |
513 | 524 | ||
514 | /// Resolves the type completely; type variables without known type are | 525 | /// Resolves the type completely; type variables without known type are |
515 | /// replaced by TyKind::Unknown. | 526 | /// replaced by TyKind::Unknown. |
516 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 527 | fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
517 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 528 | fold_tys( |
518 | &TyKind::InferenceVar(tv, kind) => { | 529 | ty, |
519 | let inner = from_inference_var(tv); | 530 | |ty, _| match ty.kind(&Interner) { |
520 | if tv_stack.contains(&inner) { | 531 | &TyKind::InferenceVar(tv, kind) => { |
521 | cov_mark::hit!(type_var_cycles_resolve_completely); | 532 | let inner = from_inference_var(tv); |
522 | // recursive type | 533 | if tv_stack.contains(&inner) { |
523 | return self.type_variable_table.fallback_value(tv, kind); | 534 | cov_mark::hit!(type_var_cycles_resolve_completely); |
524 | } | 535 | // recursive type |
525 | if let Some(known_ty) = | 536 | return self.type_variable_table.fallback_value(tv, kind); |
526 | self.var_unification_table.inlined_probe_value(inner).known() | 537 | } |
527 | { | 538 | if let Some(known_ty) = |
528 | // known_ty may contain other variables that are known by now | 539 | self.var_unification_table.inlined_probe_value(inner).known() |
529 | tv_stack.push(inner); | 540 | { |
530 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); | 541 | // known_ty may contain other variables that are known by now |
531 | tv_stack.pop(); | 542 | tv_stack.push(inner); |
532 | result | 543 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); |
533 | } else { | 544 | tv_stack.pop(); |
534 | self.type_variable_table.fallback_value(tv, kind) | 545 | result |
546 | } else { | ||
547 | self.type_variable_table.fallback_value(tv, kind) | ||
548 | } | ||
535 | } | 549 | } |
536 | } | 550 | _ => ty, |
537 | _ => ty, | 551 | }, |
538 | }) | 552 | DebruijnIndex::INNERMOST, |
553 | ) | ||
539 | } | 554 | } |
540 | } | 555 | } |
541 | 556 | ||