aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/infer
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r--crates/hir_ty/src/infer/coerce.rs10
-rw-r--r--crates/hir_ty/src/infer/expr.rs12
-rw-r--r--crates/hir_ty/src/infer/pat.rs4
-rw-r--r--crates/hir_ty/src/infer/path.rs2
-rw-r--r--crates/hir_ty/src/infer/unify.rs166
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 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
7use hir_def::{ 7use 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;
17use crate::{ 17use 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
30use super::{ 30use 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
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; 5use chalk_ir::{
6 cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex,
7 VariableKind,
8};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 9use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 10
8use super::{DomainGoal, InferenceContext}; 11use super::{DomainGoal, InferenceContext};
9use crate::{ 12use 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
15impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
@@ -34,7 +37,10 @@ where
34} 37}
35 38
36#[derive(Debug)] 39#[derive(Debug)]
37pub(super) struct Canonicalized<T> { 40pub(super) struct Canonicalized<T>
41where
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
111impl<T> Canonicalized<T> { 126impl<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