diff options
author | Florian Diebold <[email protected]> | 2021-04-01 20:04:02 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-04-03 10:17:13 +0100 |
commit | e480d81988fc0c0e4f80f1c54058b95b9aaf1ebf (patch) | |
tree | 079dabc4e0de72e30d2bd04bd50427ff6950b348 /crates/hir_ty/src/infer | |
parent | 327f3a0a3017e047be58b8312f8bf3ac690db3fd (diff) |
Introduce `GenericArg` like in Chalk
Plus some more adaptations to Substitution.
Lots of `assert_ty_ref` that we should revisit when introducing
lifetime/const parameters.
Diffstat (limited to 'crates/hir_ty/src/infer')
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 24 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 17 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 55 |
5 files changed, 58 insertions, 46 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 9c62932b1..8f7322b36 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -100,7 +100,7 @@ impl<'a> InferenceContext<'a> { | |||
100 | }, | 100 | }, |
101 | 101 | ||
102 | (TyKind::Closure(.., substs), TyKind::Function { .. }) => { | 102 | (TyKind::Closure(.., substs), TyKind::Function { .. }) => { |
103 | from_ty = substs[0].clone(); | 103 | from_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone(); |
104 | } | 104 | } |
105 | 105 | ||
106 | _ => {} | 106 | _ => {} |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 25ab3ea4c..b99b6cd21 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -266,7 +266,7 @@ impl<'a> InferenceContext<'a> { | |||
266 | let sig_ty = TyKind::Function(FnPointer { | 266 | let sig_ty = TyKind::Function(FnPointer { |
267 | num_args: sig_tys.len() - 1, | 267 | num_args: sig_tys.len() - 1, |
268 | sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, | 268 | sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, |
269 | substs: Substitution(sig_tys.clone().into()), | 269 | substs: Substitution::from_iter(&Interner, sig_tys.clone()), |
270 | }) | 270 | }) |
271 | .intern(&Interner); | 271 | .intern(&Interner); |
272 | let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); | 272 | let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); |
@@ -406,7 +406,7 @@ impl<'a> InferenceContext<'a> { | |||
406 | 406 | ||
407 | self.unify(&ty, &expected.ty); | 407 | self.unify(&ty, &expected.ty); |
408 | 408 | ||
409 | let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); | 409 | let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); |
410 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); | 410 | let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); |
411 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); | 411 | let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); |
412 | for field in fields.iter() { | 412 | for field in fields.iter() { |
@@ -456,9 +456,13 @@ impl<'a> InferenceContext<'a> { | |||
456 | .unwrap_or(true) | 456 | .unwrap_or(true) |
457 | }; | 457 | }; |
458 | match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { | 458 | match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { |
459 | TyKind::Tuple(_, substs) => { | 459 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { |
460 | name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) | 460 | substs |
461 | } | 461 | .interned(&Interner) |
462 | .get(idx) | ||
463 | .map(|a| a.assert_ty_ref(&Interner)) | ||
464 | .cloned() | ||
465 | }), | ||
462 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { | 466 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
463 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; | 467 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; |
464 | let field = FieldId { parent: (*s).into(), local_id }; | 468 | let field = FieldId { parent: (*s).into(), local_id }; |
@@ -635,7 +639,7 @@ impl<'a> InferenceContext<'a> { | |||
635 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 639 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
636 | match (range_type, lhs_ty, rhs_ty) { | 640 | match (range_type, lhs_ty, rhs_ty) { |
637 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 641 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
638 | Some(adt) => Ty::adt_ty(adt, Substitution::empty()), | 642 | Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), |
639 | None => self.err_ty(), | 643 | None => self.err_ty(), |
640 | }, | 644 | }, |
641 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 645 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
@@ -694,8 +698,8 @@ impl<'a> InferenceContext<'a> { | |||
694 | Expr::Tuple { exprs } => { | 698 | Expr::Tuple { exprs } => { |
695 | let mut tys = match expected.ty.interned(&Interner) { | 699 | let mut tys = match expected.ty.interned(&Interner) { |
696 | TyKind::Tuple(_, substs) => substs | 700 | TyKind::Tuple(_, substs) => substs |
697 | .iter() | 701 | .iter(&Interner) |
698 | .cloned() | 702 | .map(|a| a.assert_ty_ref(&Interner).clone()) |
699 | .chain(repeat_with(|| self.table.new_type_var())) | 703 | .chain(repeat_with(|| self.table.new_type_var())) |
700 | .take(exprs.len()) | 704 | .take(exprs.len()) |
701 | .collect::<Vec<_>>(), | 705 | .collect::<Vec<_>>(), |
@@ -706,7 +710,7 @@ impl<'a> InferenceContext<'a> { | |||
706 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); | 710 | self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); |
707 | } | 711 | } |
708 | 712 | ||
709 | TyKind::Tuple(tys.len(), Substitution(tys.into())).intern(&Interner) | 713 | TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner) |
710 | } | 714 | } |
711 | Expr::Array(array) => { | 715 | Expr::Array(array) => { |
712 | let elem_ty = match expected.ty.interned(&Interner) { | 716 | let elem_ty = match expected.ty.interned(&Interner) { |
@@ -953,7 +957,7 @@ impl<'a> InferenceContext<'a> { | |||
953 | substs.push(self.err_ty()); | 957 | substs.push(self.err_ty()); |
954 | } | 958 | } |
955 | assert_eq!(substs.len(), total_len); | 959 | assert_eq!(substs.len(), total_len); |
956 | Substitution(substs.into()) | 960 | Substitution::from_iter(&Interner, substs) |
957 | } | 961 | } |
958 | 962 | ||
959 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | 963 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 474363709..f1316415f 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -35,7 +35,7 @@ impl<'a> InferenceContext<'a> { | |||
35 | } | 35 | } |
36 | self.unify(&ty, expected); | 36 | self.unify(&ty, expected); |
37 | 37 | ||
38 | let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); | 38 | let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); |
39 | 39 | ||
40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
41 | let (pre, post) = match ellipsis { | 41 | let (pre, post) = match ellipsis { |
@@ -74,7 +74,7 @@ impl<'a> InferenceContext<'a> { | |||
74 | 74 | ||
75 | self.unify(&ty, expected); | 75 | self.unify(&ty, expected); |
76 | 76 | ||
77 | let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); | 77 | let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); |
78 | 78 | ||
79 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 79 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
80 | for subpat in subpats { | 80 | for subpat in subpats { |
@@ -134,7 +134,8 @@ impl<'a> InferenceContext<'a> { | |||
134 | }; | 134 | }; |
135 | let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); | 135 | let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); |
136 | let err_ty = self.err_ty(); | 136 | let err_ty = self.err_ty(); |
137 | let mut expectations_iter = expectations.iter().chain(repeat(&err_ty)); | 137 | let mut expectations_iter = |
138 | expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty)); | ||
138 | let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); | 139 | let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); |
139 | 140 | ||
140 | let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); | 141 | let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); |
@@ -142,7 +143,8 @@ impl<'a> InferenceContext<'a> { | |||
142 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); | 143 | inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); |
143 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); | 144 | inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); |
144 | 145 | ||
145 | TyKind::Tuple(inner_tys.len(), Substitution(inner_tys.into())).intern(&Interner) | 146 | TyKind::Tuple(inner_tys.len(), Substitution::from_iter(&Interner, inner_tys)) |
147 | .intern(&Interner) | ||
146 | } | 148 | } |
147 | Pat::Or(ref pats) => { | 149 | Pat::Or(ref pats) => { |
148 | if let Some((first_pat, rest)) = pats.split_first() { | 150 | if let Some((first_pat, rest)) = pats.split_first() { |
@@ -236,9 +238,10 @@ impl<'a> InferenceContext<'a> { | |||
236 | Pat::Box { inner } => match self.resolve_boxed_box() { | 238 | Pat::Box { inner } => match self.resolve_boxed_box() { |
237 | Some(box_adt) => { | 239 | Some(box_adt) => { |
238 | let (inner_ty, alloc_ty) = match expected.as_adt() { | 240 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
239 | Some((adt, subst)) if adt == box_adt => { | 241 | Some((adt, subst)) if adt == box_adt => ( |
240 | (subst[0].clone(), subst.get(1).cloned()) | 242 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), |
241 | } | 243 | subst.interned(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), |
244 | ), | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | 245 | _ => (self.result.standard_types.unknown.clone(), None), |
243 | }; | 246 | }; |
244 | 247 | ||
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 717738789..b96391776 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -97,12 +97,12 @@ impl<'a> InferenceContext<'a> { | |||
97 | 97 | ||
98 | let ty = self.db.value_ty(typable); | 98 | let ty = self.db.value_ty(typable); |
99 | // self_subst is just for the parent | 99 | // self_subst is just for the parent |
100 | let parent_substs = self_subst.unwrap_or_else(Substitution::empty); | 100 | let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); |
101 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | 101 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
102 | let substs = ctx.substs_from_path(path, typable, true); | 102 | let substs = ctx.substs_from_path(path, typable, true); |
103 | let full_substs = Substitution::builder(substs.len()) | 103 | let full_substs = Substitution::builder(substs.len(&Interner)) |
104 | .use_parent_substs(&parent_substs) | 104 | .use_parent_substs(&parent_substs) |
105 | .fill(substs.0[parent_substs.len()..].iter().cloned()) | 105 | .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) |
106 | .build(); | 106 | .build(); |
107 | let ty = ty.subst(&full_substs); | 107 | let ty = ty.subst(&full_substs); |
108 | Some(ty) | 108 | Some(ty) |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 5ea4b7481..0efc62e53 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -129,29 +129,28 @@ impl<T> Canonicalized<T> { | |||
129 | solution: Canonical<Substitution>, | 129 | solution: Canonical<Substitution>, |
130 | ) { | 130 | ) { |
131 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
132 | let new_vars = Substitution( | 132 | let new_vars = Substitution::from_iter( |
133 | solution | 133 | &Interner, |
134 | .binders | 134 | solution.binders.iter(&Interner).map(|k| match k.kind { |
135 | .iter(&Interner) | 135 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
136 | .map(|k| match k.kind { | 136 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), | 138 | // HACK: Chalk can sometimes return new lifetime variables. We |
139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), | 139 | // want to just skip them, but to not mess up the indices of |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | 140 | // other variables, we'll just create a new type variable in |
141 | // want to just skip them, but to not mess up the indices of | 141 | // their place instead. This should not matter (we never see the |
142 | // other variables, we'll just create a new type variable in | 142 | // actual *uses* of the lifetime variable). |
143 | // their place instead. This should not matter (we never see the | 143 | VariableKind::Lifetime => ctx.table.new_type_var(), |
144 | // actual *uses* of the lifetime variable). | 144 | _ => panic!("const variable in solution"), |
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | 145 | }), |
146 | _ => panic!("const variable in solution"), | ||
147 | }) | ||
148 | .collect(), | ||
149 | ); | 146 | ); |
150 | for (i, ty) in solution.value.into_iter().enumerate() { | 147 | for (i, ty) in solution.value.iter(&Interner).enumerate() { |
151 | let (v, k) = self.free_vars[i]; | 148 | let (v, k) = self.free_vars[i]; |
152 | // eagerly replace projections in the type; we may be getting types | 149 | // eagerly replace projections in the type; we may be getting types |
153 | // e.g. from where clauses where this hasn't happened yet | 150 | // e.g. from where clauses where this hasn't happened yet |
154 | let ty = ctx.normalize_associated_types_in(ty.clone().subst_bound_vars(&new_vars)); | 151 | let ty = ctx.normalize_associated_types_in( |
152 | ty.assert_ty_ref(&Interner).clone().subst_bound_vars(&new_vars), | ||
153 | ); | ||
155 | ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); | 154 | ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); |
156 | } | 155 | } |
157 | } | 156 | } |
@@ -163,13 +162,13 @@ pub fn could_unify(t1: &Ty, t2: &Ty) -> bool { | |||
163 | 162 | ||
164 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 163 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
165 | let mut table = InferenceTable::new(); | 164 | let mut table = InferenceTable::new(); |
166 | let vars = Substitution( | 165 | let vars = Substitution::from_iter( |
166 | &Interner, | ||
167 | tys.binders | 167 | tys.binders |
168 | .iter(&Interner) | 168 | .iter(&Interner) |
169 | // we always use type vars here because we want everything to | 169 | // we always use type vars here because we want everything to |
170 | // fallback to Unknown in the end (kind of hacky, as below) | 170 | // fallback to Unknown in the end (kind of hacky, as below) |
171 | .map(|_| table.new_type_var()) | 171 | .map(|_| table.new_type_var()), |
172 | .collect(), | ||
173 | ); | 172 | ); |
174 | let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); | 173 | let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); |
175 | let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); | 174 | let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); |
@@ -178,7 +177,8 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
178 | } | 177 | } |
179 | // default any type vars that weren't unified back to their original bound vars | 178 | // default any type vars that weren't unified back to their original bound vars |
180 | // (kind of hacky) | 179 | // (kind of hacky) |
181 | for (i, var) in vars.iter().enumerate() { | 180 | for (i, var) in vars.iter(&Interner).enumerate() { |
181 | let var = var.assert_ty_ref(&Interner); | ||
182 | if &*table.resolve_ty_shallow(var) == var { | 182 | if &*table.resolve_ty_shallow(var) == var { |
183 | table.unify( | 183 | table.unify( |
184 | var, | 184 | var, |
@@ -188,7 +188,10 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
188 | } | 188 | } |
189 | Some( | 189 | Some( |
190 | Substitution::builder(tys.binders.len(&Interner)) | 190 | Substitution::builder(tys.binders.len(&Interner)) |
191 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 191 | .fill( |
192 | vars.iter(&Interner) | ||
193 | .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), | ||
194 | ) | ||
192 | .build(), | 195 | .build(), |
193 | ) | 196 | ) |
194 | } | 197 | } |
@@ -284,7 +287,9 @@ impl InferenceTable { | |||
284 | substs2: &Substitution, | 287 | substs2: &Substitution, |
285 | depth: usize, | 288 | depth: usize, |
286 | ) -> bool { | 289 | ) -> bool { |
287 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) | 290 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { |
291 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) | ||
292 | }) | ||
288 | } | 293 | } |
289 | 294 | ||
290 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | 295 | fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { |