diff options
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 12 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 166 |
5 files changed, 107 insertions, 87 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index fd679f444..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` |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 9841988c5..50497eecb 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}, |
@@ -17,14 +17,14 @@ use syntax::ast::RangeOp; | |||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, dummy_usize_const, | 18 | autoderef, dummy_usize_const, |
19 | lower::lower_to_chalk_mutability, | 19 | lower::lower_to_chalk_mutability, |
20 | mapping::from_chalk, | ||
20 | method_resolution, op, | 21 | method_resolution, op, |
21 | primitive::{self, UintTy}, | 22 | primitive::{self, UintTy}, |
22 | static_lifetime, to_chalk_trait_id, | 23 | static_lifetime, to_chalk_trait_id, |
23 | traits::{chalk::from_chalk, FnTrait}, | 24 | traits::FnTrait, |
24 | utils::{generics, Generics}, | 25 | utils::{generics, Generics}, |
25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, | 26 | AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, |
26 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, | 27 | ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind, |
27 | TypeWalk, | ||
28 | }; | 28 | }; |
29 | 29 | ||
30 | use super::{ | 30 | use super::{ |
@@ -463,7 +463,11 @@ impl<'a> InferenceContext<'a> { | |||
463 | }; | 463 | }; |
464 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { | 464 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { |
465 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { | 465 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { |
466 | substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() | 466 | substs |
467 | .as_slice(&Interner) | ||
468 | .get(idx) | ||
469 | .map(|a| a.assert_ty_ref(&Interner)) | ||
470 | .cloned() | ||
467 | }), | 471 | }), |
468 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { | 472 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
469 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; | 473 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a41e8e116..aea354cde 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().as_slice(), | 125 | Some(parameters) => &*parameters.as_slice(&Interner), |
126 | _ => &[], | 126 | _ => &[], |
127 | }; | 127 | }; |
128 | 128 | ||
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> { | |||
242 | let (inner_ty, alloc_ty) = match expected.as_adt() { | 242 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
243 | Some((adt, subst)) if adt == box_adt => ( | 243 | Some((adt, subst)) if adt == box_adt => ( |
244 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), | 244 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), |
245 | subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), | 245 | subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), |
246 | ), | 246 | ), |
247 | _ => (self.result.standard_types.unknown.clone(), None), | 247 | _ => (self.result.standard_types.unknown.clone(), None), |
248 | }; | 248 | }; |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index f8955aa32..495282eba 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> { | |||
101 | let substs = ctx.substs_from_path(path, typable, true); | 101 | let substs = ctx.substs_from_path(path, typable, true); |
102 | let ty = TyBuilder::value_ty(self.db, typable) | 102 | let ty = TyBuilder::value_ty(self.db, typable) |
103 | .use_parent_substs(&parent_substs) | 103 | .use_parent_substs(&parent_substs) |
104 | .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) | 104 | .fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) |
105 | .build(); | 105 | .build(); |
106 | Some(ty) | 106 | Some(ty) |
107 | } | 107 | } |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 2ea9dd920..a887e20b0 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,14 +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, TyExt, TyKind, TypeWalk, | 14 | DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution, |
12 | WhereClause, | 15 | Ty, TyExt, TyKind, WhereClause, |
13 | }; | 16 | }; |
14 | 17 | ||
15 | impl<'a> InferenceContext<'a> { | 18 | impl<'a> InferenceContext<'a> { |
@@ -34,7 +37,10 @@ where | |||
34 | } | 37 | } |
35 | 38 | ||
36 | #[derive(Debug)] | 39 | #[derive(Debug)] |
37 | pub(super) struct Canonicalized<T> { | 40 | pub(super) struct Canonicalized<T> |
41 | where | ||
42 | T: HasInterner<Interner = Interner>, | ||
43 | { | ||
38 | pub(super) value: Canonical<T>, | 44 | pub(super) value: Canonical<T>, |
39 | free_vars: Vec<(InferenceVar, TyVariableKind)>, | 45 | free_vars: Vec<(InferenceVar, TyVariableKind)>, |
40 | } | 46 | } |
@@ -48,9 +54,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
48 | }) | 54 | }) |
49 | } | 55 | } |
50 | 56 | ||
51 | fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { | 57 | fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>( |
52 | t.fold_binders( | 58 | &mut self, |
53 | &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) { | ||
54 | &TyKind::InferenceVar(var, kind) => { | 65 | &TyKind::InferenceVar(var, kind) => { |
55 | let inner = from_inference_var(var); | 66 | let inner = from_inference_var(var); |
56 | if self.var_stack.contains(&inner) { | 67 | if self.var_stack.contains(&inner) { |
@@ -76,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | ) | 87 | ) |
77 | } | 88 | } |
78 | 89 | ||
79 | 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> { | ||
80 | let kinds = self | 94 | let kinds = self |
81 | .free_vars | 95 | .free_vars |
82 | .iter() | 96 | .iter() |
@@ -103,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
103 | DomainGoal::Holds(wc) => { | 117 | DomainGoal::Holds(wc) => { |
104 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) | 118 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
105 | } | 119 | } |
120 | _ => unimplemented!(), | ||
106 | }; | 121 | }; |
107 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) | 122 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
108 | } | 123 | } |
109 | } | 124 | } |
110 | 125 | ||
111 | impl<T> Canonicalized<T> { | 126 | impl<T: HasInterner<Interner = Interner>> Canonicalized<T> { |
112 | pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { | 127 | pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { |
113 | ty.fold_binders( | 128 | crate::fold_free_vars(ty, |bound, _binders| { |
114 | &mut |ty, binders| { | 129 | let (v, k) = self.free_vars[bound.index]; |
115 | if let TyKind::BoundVar(bound) = ty.kind(&Interner) { | 130 | TyKind::InferenceVar(v, k).intern(&Interner) |
116 | if bound.debruijn >= binders { | 131 | }) |
117 | let (v, k) = self.free_vars[bound.index]; | ||
118 | TyKind::InferenceVar(v, k).intern(&Interner) | ||
119 | } else { | ||
120 | ty | ||
121 | } | ||
122 | } else { | ||
123 | ty | ||
124 | } | ||
125 | }, | ||
126 | DebruijnIndex::INNERMOST, | ||
127 | ) | ||
128 | } | 132 | } |
129 | 133 | ||
130 | pub(super) fn apply_solution( | 134 | pub(super) fn apply_solution( |
@@ -136,15 +140,17 @@ impl<T> Canonicalized<T> { | |||
136 | let new_vars = Substitution::from_iter( | 140 | let new_vars = Substitution::from_iter( |
137 | &Interner, | 141 | &Interner, |
138 | solution.binders.iter(&Interner).map(|k| match k.kind { | 142 | solution.binders.iter(&Interner).map(|k| match k.kind { |
139 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), | 143 | VariableKind::Ty(TyVariableKind::General) => { |
140 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), | 144 | ctx.table.new_type_var().cast(&Interner) |
141 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), | 145 | } |
142 | // HACK: Chalk can sometimes return new lifetime variables. We | 146 | VariableKind::Ty(TyVariableKind::Integer) => { |
143 | // want to just skip them, but to not mess up the indices of | 147 | ctx.table.new_integer_var().cast(&Interner) |
144 | // other variables, we'll just create a new type variable in | 148 | } |
145 | // their place instead. This should not matter (we never see the | 149 | VariableKind::Ty(TyVariableKind::Float) => { |
146 | // actual *uses* of the lifetime variable). | 150 | ctx.table.new_float_var().cast(&Interner) |
147 | 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), | ||
148 | _ => panic!("const variable in solution"), | 154 | _ => panic!("const variable in solution"), |
149 | }), | 155 | }), |
150 | ); | 156 | ); |
@@ -488,55 +494,63 @@ impl InferenceTable { | |||
488 | /// 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 |
489 | /// known type. | 495 | /// known type. |
490 | 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 { |
491 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 497 | fold_tys( |
492 | &TyKind::InferenceVar(tv, kind) => { | 498 | ty, |
493 | let inner = from_inference_var(tv); | 499 | |ty, _| match ty.kind(&Interner) { |
494 | if tv_stack.contains(&inner) { | 500 | &TyKind::InferenceVar(tv, kind) => { |
495 | cov_mark::hit!(type_var_cycles_resolve_as_possible); | 501 | let inner = from_inference_var(tv); |
496 | // recursive type | 502 | if tv_stack.contains(&inner) { |
497 | return self.type_variable_table.fallback_value(tv, kind); | 503 | cov_mark::hit!(type_var_cycles_resolve_as_possible); |
498 | } | 504 | // recursive type |
499 | if let Some(known_ty) = | 505 | return self.type_variable_table.fallback_value(tv, kind); |
500 | self.var_unification_table.inlined_probe_value(inner).known() | 506 | } |
501 | { | 507 | if let Some(known_ty) = |
502 | // known_ty may contain other variables that are known by now | 508 | self.var_unification_table.inlined_probe_value(inner).known() |
503 | tv_stack.push(inner); | 509 | { |
504 | 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 |
505 | tv_stack.pop(); | 511 | tv_stack.push(inner); |
506 | result | 512 | let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); |
507 | } else { | 513 | tv_stack.pop(); |
508 | ty | 514 | result |
515 | } else { | ||
516 | ty | ||
517 | } | ||
509 | } | 518 | } |
510 | } | 519 | _ => ty, |
511 | _ => ty, | 520 | }, |
512 | }) | 521 | DebruijnIndex::INNERMOST, |
522 | ) | ||
513 | } | 523 | } |
514 | 524 | ||
515 | /// Resolves the type completely; type variables without known type are | 525 | /// Resolves the type completely; type variables without known type are |
516 | /// replaced by TyKind::Unknown. | 526 | /// replaced by TyKind::Unknown. |
517 | 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 { |
518 | ty.fold(&mut |ty| match ty.kind(&Interner) { | 528 | fold_tys( |
519 | &TyKind::InferenceVar(tv, kind) => { | 529 | ty, |
520 | let inner = from_inference_var(tv); | 530 | |ty, _| match ty.kind(&Interner) { |
521 | if tv_stack.contains(&inner) { | 531 | &TyKind::InferenceVar(tv, kind) => { |
522 | cov_mark::hit!(type_var_cycles_resolve_completely); | 532 | let inner = from_inference_var(tv); |
523 | // recursive type | 533 | if tv_stack.contains(&inner) { |
524 | return self.type_variable_table.fallback_value(tv, kind); | 534 | cov_mark::hit!(type_var_cycles_resolve_completely); |
525 | } | 535 | // recursive type |
526 | if let Some(known_ty) = | 536 | return self.type_variable_table.fallback_value(tv, kind); |
527 | self.var_unification_table.inlined_probe_value(inner).known() | 537 | } |
528 | { | 538 | if let Some(known_ty) = |
529 | // known_ty may contain other variables that are known by now | 539 | self.var_unification_table.inlined_probe_value(inner).known() |
530 | tv_stack.push(inner); | 540 | { |
531 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); | 541 | // known_ty may contain other variables that are known by now |
532 | tv_stack.pop(); | 542 | tv_stack.push(inner); |
533 | result | 543 | let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); |
534 | } else { | 544 | tv_stack.pop(); |
535 | self.type_variable_table.fallback_value(tv, kind) | 545 | result |
546 | } else { | ||
547 | self.type_variable_table.fallback_value(tv, kind) | ||
548 | } | ||
536 | } | 549 | } |
537 | } | 550 | _ => ty, |
538 | _ => ty, | 551 | }, |
539 | }) | 552 | DebruijnIndex::INNERMOST, |
553 | ) | ||
540 | } | 554 | } |
541 | } | 555 | } |
542 | 556 | ||