aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/autoderef.rs10
-rw-r--r--crates/hir_ty/src/infer.rs40
-rw-r--r--crates/hir_ty/src/infer/coerce.rs11
-rw-r--r--crates/hir_ty/src/infer/pat.rs6
-rw-r--r--crates/hir_ty/src/infer/unify.rs36
-rw-r--r--crates/hir_ty/src/lib.rs2
-rw-r--r--crates/hir_ty/src/method_resolution.rs54
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/traits.rs16
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs118
-rw-r--r--crates/hir_ty/src/types.rs35
11 files changed, 190 insertions, 160 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index c5890e24d..80e192a57 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -120,8 +120,8 @@ fn deref_by_trait(
120 // assumptions will be broken. We would need to properly introduce 120 // assumptions will be broken. We would need to properly introduce
121 // new variables in that case 121 // new variables in that case
122 122
123 for i in 1..vars.0.binders.len(&Interner) { 123 for i in 1..vars.binders.len(&Interner) {
124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) 124 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
126 { 126 {
127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -130,12 +130,12 @@ fn deref_by_trait(
130 } 130 }
131 Some(Canonical { 131 Some(Canonical {
132 value: vars 132 value: vars
133 .0
134 .value 133 .value
135 .at(&Interner, vars.0.value.len(&Interner) - 1) 134 .subst
135 .at(&Interner, vars.value.subst.len(&Interner) - 1)
136 .assert_ty_ref(&Interner) 136 .assert_ty_ref(&Interner)
137 .clone(), 137 .clone(),
138 binders: vars.0.binders.clone(), 138 binders: vars.binders.clone(),
139 }) 139 })
140 } 140 }
141 Solution::Ambig(_) => { 141 Solution::Ambig(_) => {
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 796f77ab0..6af0c59b8 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -42,7 +42,7 @@ use super::{
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -131,8 +131,7 @@ pub struct InferenceResult {
131 method_resolutions: FxHashMap<ExprId, FunctionId>, 131 method_resolutions: FxHashMap<ExprId, FunctionId>,
132 /// For each field access expr, records the field it resolves to. 132 /// For each field access expr, records the field it resolves to.
133 field_resolutions: FxHashMap<ExprId, FieldId>, 133 field_resolutions: FxHashMap<ExprId, FieldId>,
134 record_pat_field_resolutions: FxHashMap<PatId, FieldId>, 134 /// For each struct literal or pattern, records the variant it resolves to.
135 /// For each struct literal, records the variant it resolves to.
136 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, 135 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
137 /// For each associated item record what it resolves to 136 /// For each associated item record what it resolves to
138 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, 137 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
@@ -151,9 +150,6 @@ impl InferenceResult {
151 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { 150 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
152 self.field_resolutions.get(&expr).copied() 151 self.field_resolutions.get(&expr).copied()
153 } 152 }
154 pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> {
155 self.record_pat_field_resolutions.get(&pat).copied()
156 }
157 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { 153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
158 self.variant_resolutions.get(&id.into()).copied() 154 self.variant_resolutions.get(&id.into()).copied()
159 } 155 }
@@ -346,11 +342,18 @@ impl<'a> InferenceContext<'a> {
346 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
347 343
348 match solution { 344 match solution {
349 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
350 canonicalized.apply_solution(self, substs.0); 346 canonicalized.apply_solution(
347 self,
348 Canonical {
349 binders: canonical_subst.binders,
350 // FIXME: handle constraints
351 value: canonical_subst.value.subst,
352 },
353 );
351 } 354 }
352 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
353 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
354 self.obligations.push(obligation); 357 self.obligations.push(obligation);
355 } 358 }
356 Some(_) => { 359 Some(_) => {
@@ -691,25 +694,6 @@ impl<'a> InferenceContext<'a> {
691 } 694 }
692} 695}
693 696
694/// The kinds of placeholders we need during type inference. There's separate
695/// values for general types, and for integer and float variables. The latter
696/// two are used for inference of literal values (e.g. `100` could be one of
697/// several integer types).
698#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
699pub struct InferenceVar {
700 index: u32,
701}
702
703impl InferenceVar {
704 fn to_inner(self) -> unify::TypeVarId {
705 unify::TypeVarId(self.index)
706 }
707
708 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
709 InferenceVar { index }
710 }
711}
712
713/// When inferring an expression, we propagate downward whatever type hint we 697/// When inferring an expression, we propagate downward whatever type hint we
714/// are able in the form of an `Expectation`. 698/// are able in the form of an `Expectation`.
715#[derive(Clone, PartialEq, Eq, Debug)] 699#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 159a53a63..f1af2a0bd 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyExt, TyKind}; 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -148,7 +148,14 @@ impl<'a> InferenceContext<'a> {
148 148
149 match solution { 149 match solution {
150 Solution::Unique(v) => { 150 Solution::Unique(v) => {
151 canonicalized.apply_solution(self, v.0); 151 canonicalized.apply_solution(
152 self,
153 Canonical {
154 binders: v.binders,
155 // FIXME handle constraints
156 value: v.value.subst,
157 },
158 );
152 } 159 }
153 _ => return None, 160 _ => return None,
154 }; 161 };
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 942f70edf..e4813c87c 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,7 +7,6 @@ use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
9 path::Path, 9 path::Path,
10 FieldId,
11}; 10};
12use hir_expand::name::Name; 11use hir_expand::name::Name;
13 12
@@ -80,11 +79,6 @@ impl<'a> InferenceContext<'a> {
80 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();
81 for subpat in subpats { 80 for subpat in subpats {
82 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 81 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
83 if let Some(local_id) = matching_field {
84 let field_def = FieldId { parent: def.unwrap(), local_id };
85 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
86 }
87
88 let expected_ty = matching_field.map_or(self.err_ty(), |field| { 82 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
89 field_tys[field].clone().substitute(&Interner, &substs) 83 field_tys[field].clone().substitute(&Interner, &substs)
90 }); 84 });
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 7d76cda68..d717e3375 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -51,7 +51,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
51 t.fold_binders( 51 t.fold_binders(
52 &mut |ty, binders| match ty.kind(&Interner) { 52 &mut |ty, binders| match ty.kind(&Interner) {
53 &TyKind::InferenceVar(var, kind) => { 53 &TyKind::InferenceVar(var, kind) => {
54 let inner = var.to_inner(); 54 let inner = from_inference_var(var);
55 if self.var_stack.contains(&inner) { 55 if self.var_stack.contains(&inner) {
56 // recursive type 56 // recursive type
57 return self.ctx.table.type_variable_table.fallback_value(var, kind); 57 return self.ctx.table.type_variable_table.fallback_value(var, kind);
@@ -65,7 +65,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
65 result 65 result
66 } else { 66 } else {
67 let root = self.ctx.table.var_unification_table.find(inner); 67 let root = self.ctx.table.var_unification_table.find(inner);
68 let position = self.add(InferenceVar::from_inner(root), kind); 68 let position = self.add(to_inference_var(root), kind);
69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) 69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
70 } 70 }
71 } 71 }
@@ -207,16 +207,16 @@ impl TypeVariableTable {
207 } 207 }
208 208
209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { 209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
210 self.inner[iv.to_inner().0 as usize].diverging = diverging; 210 self.inner[from_inference_var(iv).0 as usize].diverging = diverging;
211 } 211 }
212 212
213 fn is_diverging(&mut self, iv: InferenceVar) -> bool { 213 fn is_diverging(&mut self, iv: InferenceVar) -> bool {
214 self.inner[iv.to_inner().0 as usize].diverging 214 self.inner[from_inference_var(iv).0 as usize].diverging
215 } 215 }
216 216
217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
218 match kind { 218 match kind {
219 _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, 219 _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never,
220 TyVariableKind::General => TyKind::Error, 220 TyVariableKind::General => TyKind::Error,
221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), 221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), 222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
@@ -250,7 +250,7 @@ impl InferenceTable {
250 self.type_variable_table.push(TypeVariableData { diverging }); 250 self.type_variable_table.push(TypeVariableData { diverging });
251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
253 TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) 253 TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner)
254 } 254 }
255 255
256 pub(crate) fn new_type_var(&mut self) -> Ty { 256 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -369,8 +369,12 @@ impl InferenceTable {
369 == self.type_variable_table.is_diverging(*tv2) => 369 == self.type_variable_table.is_diverging(*tv2) =>
370 { 370 {
371 // both type vars are unknown since we tried to resolve them 371 // both type vars are unknown since we tried to resolve them
372 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) { 372 if !self
373 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 373 .var_unification_table
374 .unioned(from_inference_var(*tv1), from_inference_var(*tv2))
375 {
376 self.var_unification_table
377 .union(from_inference_var(*tv1), from_inference_var(*tv2));
374 self.revision += 1; 378 self.revision += 1;
375 } 379 }
376 true 380 true
@@ -407,7 +411,7 @@ impl InferenceTable {
407 ) => { 411 ) => {
408 // the type var is unknown since we tried to resolve it 412 // the type var is unknown since we tried to resolve it
409 self.var_unification_table.union_value( 413 self.var_unification_table.union_value(
410 tv.to_inner(), 414 from_inference_var(*tv),
411 TypeVarValue::Known(other.clone().intern(&Interner)), 415 TypeVarValue::Known(other.clone().intern(&Interner)),
412 ); 416 );
413 self.revision += 1; 417 self.revision += 1;
@@ -462,7 +466,7 @@ impl InferenceTable {
462 } 466 }
463 match ty.kind(&Interner) { 467 match ty.kind(&Interner) {
464 TyKind::InferenceVar(tv, _) => { 468 TyKind::InferenceVar(tv, _) => {
465 let inner = tv.to_inner(); 469 let inner = from_inference_var(*tv);
466 match self.var_unification_table.inlined_probe_value(inner).known() { 470 match self.var_unification_table.inlined_probe_value(inner).known() {
467 Some(known_ty) => { 471 Some(known_ty) => {
468 // The known_ty can't be a type var itself 472 // The known_ty can't be a type var itself
@@ -485,7 +489,7 @@ impl InferenceTable {
485 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 489 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
486 ty.fold(&mut |ty| match ty.kind(&Interner) { 490 ty.fold(&mut |ty| match ty.kind(&Interner) {
487 &TyKind::InferenceVar(tv, kind) => { 491 &TyKind::InferenceVar(tv, kind) => {
488 let inner = tv.to_inner(); 492 let inner = from_inference_var(tv);
489 if tv_stack.contains(&inner) { 493 if tv_stack.contains(&inner) {
490 cov_mark::hit!(type_var_cycles_resolve_as_possible); 494 cov_mark::hit!(type_var_cycles_resolve_as_possible);
491 // recursive type 495 // recursive type
@@ -512,7 +516,7 @@ impl InferenceTable {
512 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 516 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
513 ty.fold(&mut |ty| match ty.kind(&Interner) { 517 ty.fold(&mut |ty| match ty.kind(&Interner) {
514 &TyKind::InferenceVar(tv, kind) => { 518 &TyKind::InferenceVar(tv, kind) => {
515 let inner = tv.to_inner(); 519 let inner = from_inference_var(tv);
516 if tv_stack.contains(&inner) { 520 if tv_stack.contains(&inner) {
517 cov_mark::hit!(type_var_cycles_resolve_completely); 521 cov_mark::hit!(type_var_cycles_resolve_completely);
518 // recursive type 522 // recursive type
@@ -555,6 +559,14 @@ impl UnifyKey for TypeVarId {
555 } 559 }
556} 560}
557 561
562fn from_inference_var(var: InferenceVar) -> TypeVarId {
563 TypeVarId(var.index())
564}
565
566fn to_inference_var(TypeVarId(index): TypeVarId) -> InferenceVar {
567 index.into()
568}
569
558/// The value of a type variable: either we already know the type, or we don't 570/// The value of a type variable: either we already know the type, or we don't
559/// know it yet. 571/// know it yet.
560#[derive(Clone, PartialEq, Eq, Debug)] 572#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index f5b658cba..5c83a508d 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -42,7 +42,7 @@ use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
42pub use autoderef::autoderef; 42pub use autoderef::autoderef;
43pub use builder::TyBuilder; 43pub use builder::TyBuilder;
44pub use chalk_ext::{ProjectionTyExt, TyExt}; 44pub use chalk_ext::{ProjectionTyExt, TyExt};
45pub use infer::{could_unify, InferenceResult, InferenceVar}; 45pub use infer::{could_unify, InferenceResult};
46pub use lower::{ 46pub use lower::{
47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
48 TyDefId, TyLoweringContext, ValueTyDefId, 48 TyDefId, TyLoweringContext, ValueTyDefId,
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index ee725fd46..f29319f20 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,8 +8,8 @@ use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId,
12 ImplId, Lookup, ModuleId, TraitId, 12 GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
@@ -100,25 +100,38 @@ impl TraitImpls {
100 let mut impls = Self { map: FxHashMap::default() }; 100 let mut impls = Self { map: FxHashMap::default() };
101 101
102 let crate_def_map = db.crate_def_map(krate); 102 let crate_def_map = db.crate_def_map(krate);
103 for (_module_id, module_data) in crate_def_map.modules() { 103 collect_def_map(db, &crate_def_map, &mut impls);
104 for impl_id in module_data.scope.impls() { 104
105 let target_trait = match db.impl_trait(impl_id) { 105 return Arc::new(impls);
106 Some(tr) => tr.skip_binders().hir_trait_id(), 106
107 None => continue, 107 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
108 }; 108 for (_module_id, module_data) in def_map.modules() {
109 let self_ty = db.impl_self_ty(impl_id); 109 for impl_id in module_data.scope.impls() {
110 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); 110 let target_trait = match db.impl_trait(impl_id) {
111 impls 111 Some(tr) => tr.skip_binders().hir_trait_id(),
112 .map 112 None => continue,
113 .entry(target_trait) 113 };
114 .or_default() 114 let self_ty = db.impl_self_ty(impl_id);
115 .entry(self_ty_fp) 115 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
116 .or_default() 116 impls
117 .push(impl_id); 117 .map
118 .entry(target_trait)
119 .or_default()
120 .entry(self_ty_fp)
121 .or_default()
122 .push(impl_id);
123 }
124
125 // To better support custom derives, collect impls in all unnamed const items.
126 // const _: () = { ... };
127 for konst in module_data.scope.unnamed_consts() {
128 let body = db.body(konst.into());
129 for (_, block_def_map) in body.blocks(db.upcast()) {
130 collect_def_map(db, &block_def_map, impls);
131 }
132 }
118 } 133 }
119 } 134 }
120
121 Arc::new(impls)
122 } 135 }
123 136
124 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { 137 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@@ -208,6 +221,9 @@ impl InherentImpls {
208 } 221 }
209 } 222 }
210 223
224 // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
225 // support trait impls there.
226
211 Arc::new(Self { map }) 227 Arc::new(Self { map })
212 } 228 }
213 229
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 61f18b0d2..4b2c82b41 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1292,3 +1292,25 @@ mod b {
1292 "#]], 1292 "#]],
1293 ) 1293 )
1294} 1294}
1295
1296#[test]
1297fn impl_in_unnamed_const() {
1298 check_types(
1299 r#"
1300struct S;
1301
1302trait Tr {
1303 fn method(&self) -> u16;
1304}
1305
1306const _: () = {
1307 impl Tr for S {}
1308};
1309
1310fn f() {
1311 S.method();
1312 //^^^^^^^^^^ u16
1313}
1314 "#,
1315 );
1316}
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index c8883485c..3374532c3 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -9,7 +9,7 @@ use stdx::panic_context;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, 11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 Solution, SolutionVariables, Ty, TyKind, WhereClause, 12 Solution, Ty, TyKind, WhereClause,
13}; 13};
14 14
15use self::chalk::{from_chalk, Interner, ToChalk}; 15use self::chalk::{from_chalk, Interner, ToChalk};
@@ -173,23 +173,15 @@ fn solution_from_chalk(
173 db: &dyn HirDatabase, 173 db: &dyn HirDatabase,
174 solution: chalk_solve::Solution<Interner>, 174 solution: chalk_solve::Solution<Interner>,
175) -> Solution { 175) -> Solution {
176 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
177 let result = from_chalk(db, subst);
178 SolutionVariables(result)
179 };
180 match solution { 176 match solution {
181 chalk_solve::Solution::Unique(constr_subst) => { 177 chalk_solve::Solution::Unique(constr_subst) => {
182 let subst = chalk_ir::Canonical { 178 Solution::Unique(from_chalk(db, constr_subst))
183 value: constr_subst.value.subst,
184 binders: constr_subst.binders,
185 };
186 Solution::Unique(convert_subst(subst))
187 } 179 }
188 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => { 180 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
189 Solution::Ambig(Guidance::Definite(convert_subst(subst))) 181 Solution::Ambig(Guidance::Definite(from_chalk(db, subst)))
190 } 182 }
191 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => { 183 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
192 Solution::Ambig(Guidance::Suggested(convert_subst(subst))) 184 Solution::Ambig(Guidance::Suggested(from_chalk(db, subst)))
193 } 185 }
194 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => { 186 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
195 Solution::Ambig(Guidance::Unknown) 187 Solution::Ambig(Guidance::Unknown)
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index cf73cb078..84abd99b2 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -10,10 +10,9 @@ use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 chalk_ext::ProjectionTyExt, db::HirDatabase, dummy_usize_const, static_lifetime, AliasTy, 13 chalk_ext::ProjectionTyExt, db::HirDatabase, static_lifetime, AliasTy, CallableDefId,
14 CallableDefId, Canonical, Const, DomainGoal, FnPointer, GenericArg, InEnvironment, Lifetime, 14 Canonical, ConstrainedSubst, DomainGoal, FnPointer, GenericArg, InEnvironment, OpaqueTy,
15 OpaqueTy, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, 15 ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
16 WhereClause,
17}; 16};
18 17
19use super::interner::*; 18use super::interner::*;
@@ -23,16 +22,16 @@ impl ToChalk for Ty {
23 type Chalk = chalk_ir::Ty<Interner>; 22 type Chalk = chalk_ir::Ty<Interner>;
24 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 23 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
25 match self.into_inner() { 24 match self.into_inner() {
26 TyKind::Ref(m, lt, ty) => ref_to_chalk(db, m, lt, ty), 25 TyKind::Ref(m, lt, ty) => {
27 TyKind::Array(ty, size) => array_to_chalk(db, ty, size), 26 chalk_ir::TyKind::Ref(m, lt, ty.to_chalk(db)).intern(&Interner)
28 TyKind::Function(FnPointer { sig, substitution: substs, .. }) => { 27 }
28 TyKind::Array(ty, size) => {
29 chalk_ir::TyKind::Array(ty.to_chalk(db), size).intern(&Interner)
30 }
31 TyKind::Function(FnPointer { sig, substitution: substs, num_binders }) => {
29 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db)); 32 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db));
30 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 33 chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders, sig, substitution })
31 num_binders: 0, 34 .intern(&Interner)
32 sig,
33 substitution,
34 })
35 .intern(&Interner)
36 } 35 }
37 TyKind::AssociatedType(assoc_type_id, substs) => { 36 TyKind::AssociatedType(assoc_type_id, substs) => {
38 let substitution = substs.to_chalk(db); 37 let substitution = substs.to_chalk(db);
@@ -74,22 +73,13 @@ impl ToChalk for Ty {
74 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) 73 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
75 } 74 }
76 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 75 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
77 let associated_ty_id = proj_ty.associated_ty_id; 76 chalk_ir::AliasTy::Projection(proj_ty.to_chalk(db))
78 let substitution = proj_ty.substitution.to_chalk(db);
79 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
80 associated_ty_id,
81 substitution,
82 })
83 .cast(&Interner)
84 .intern(&Interner)
85 }
86 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
87 let opaque_ty_id = opaque_ty.opaque_ty_id;
88 let substitution = opaque_ty.substitution.to_chalk(db);
89 chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution })
90 .cast(&Interner) 77 .cast(&Interner)
91 .intern(&Interner) 78 .intern(&Interner)
92 } 79 }
80 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
81 chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)).cast(&Interner).intern(&Interner)
82 }
93 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), 83 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
94 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 84 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
95 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), 85 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
@@ -101,7 +91,7 @@ impl ToChalk for Ty {
101 ); 91 );
102 let bounded_ty = chalk_ir::DynTy { 92 let bounded_ty = chalk_ir::DynTy {
103 bounds: chalk_ir::Binders::new(binders, where_clauses), 93 bounds: chalk_ir::Binders::new(binders, where_clauses),
104 lifetime: static_lifetime(), 94 lifetime: dyn_ty.lifetime,
105 }; 95 };
106 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) 96 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
107 } 97 }
@@ -114,17 +104,10 @@ impl ToChalk for Ty {
114 chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size), 104 chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size),
115 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), 105 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
116 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 106 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
117 let associated_ty = proj.associated_ty_id; 107 TyKind::Alias(AliasTy::Projection(from_chalk(db, proj)))
118 let parameters = from_chalk(db, proj.substitution);
119 TyKind::Alias(AliasTy::Projection(ProjectionTy {
120 associated_ty_id: associated_ty,
121 substitution: parameters,
122 }))
123 } 108 }
124 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { 109 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
125 let opaque_ty_id = opaque_ty.opaque_ty_id; 110 TyKind::Alias(AliasTy::Opaque(from_chalk(db, opaque_ty)))
126 let parameters = from_chalk(db, opaque_ty.substitution);
127 TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters }))
128 } 111 }
129 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 112 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
130 num_binders, 113 num_binders,
@@ -138,18 +121,19 @@ impl ToChalk for Ty {
138 } 121 }
139 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx), 122 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
140 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error, 123 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error,
141 chalk_ir::TyKind::Dyn(where_clauses) => { 124 chalk_ir::TyKind::Dyn(dyn_ty) => {
142 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 125 assert_eq!(dyn_ty.bounds.binders.len(&Interner), 1);
143 let bounds = where_clauses 126 let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
144 .bounds 127 let where_clauses = crate::QuantifiedWhereClauses::from_iter(
145 .skip_binders() 128 &Interner,
146 .iter(&Interner) 129 bounds.interned().iter().cloned().map(|p| from_chalk(db, p)),
147 .map(|c| from_chalk(db, c.clone())); 130 );
148 TyKind::Dyn(crate::DynTy { 131 TyKind::Dyn(crate::DynTy {
149 bounds: crate::Binders::new( 132 bounds: crate::Binders::new(binders, where_clauses),
150 where_clauses.bounds.binders.clone(), 133 // HACK: we sometimes get lifetime variables back in solutions
151 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), 134 // from Chalk, and don't have the infrastructure to substitute
152 ), 135 // them yet. So for now we just turn them into 'static right
136 // when we get them
153 lifetime: static_lifetime(), 137 lifetime: static_lifetime(),
154 }) 138 })
155 } 139 }
@@ -169,8 +153,12 @@ impl ToChalk for Ty {
169 } 153 }
170 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)), 154 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
171 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)), 155 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
172 chalk_ir::TyKind::Ref(mutability, lifetime, ty) => { 156 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
173 TyKind::Ref(mutability, lifetime, from_chalk(db, ty)) 157 // HACK: we sometimes get lifetime variables back in solutions
158 // from Chalk, and don't have the infrastructure to substitute
159 // them yet. So for now we just turn them into 'static right
160 // when we get them
161 TyKind::Ref(mutability, static_lifetime(), from_chalk(db, ty))
174 } 162 }
175 chalk_ir::TyKind::Str => TyKind::Str, 163 chalk_ir::TyKind::Str => TyKind::Str,
176 chalk_ir::TyKind::Never => TyKind::Never, 164 chalk_ir::TyKind::Never => TyKind::Never,
@@ -189,26 +177,6 @@ impl ToChalk for Ty {
189 } 177 }
190} 178}
191 179
192/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
193/// fake lifetime here, because Chalks built-in logic may expect it to be there.
194fn ref_to_chalk(
195 db: &dyn HirDatabase,
196 mutability: chalk_ir::Mutability,
197 _lifetime: Lifetime,
198 ty: Ty,
199) -> chalk_ir::Ty<Interner> {
200 let arg = ty.to_chalk(db);
201 let lifetime = static_lifetime();
202 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
203}
204
205/// We currently don't model constants, but Chalk does. So, we have to insert a
206/// fake constant here, because Chalks built-in logic may expect it to be there.
207fn array_to_chalk(db: &dyn HirDatabase, ty: Ty, _: Const) -> chalk_ir::Ty<Interner> {
208 let arg = ty.to_chalk(db);
209 chalk_ir::TyKind::Array(arg, dummy_usize_const()).intern(&Interner)
210}
211
212impl ToChalk for GenericArg { 180impl ToChalk for GenericArg {
213 type Chalk = chalk_ir::GenericArg<Interner>; 181 type Chalk = chalk_ir::GenericArg<Interner>;
214 182
@@ -491,6 +459,18 @@ where
491 } 459 }
492} 460}
493 461
462impl ToChalk for crate::ConstrainedSubst {
463 type Chalk = chalk_ir::ConstrainedSubst<Interner>;
464
465 fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk {
466 unimplemented!()
467 }
468
469 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
470 ConstrainedSubst { subst: from_chalk(db, chalk.subst) }
471 }
472}
473
494pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 474pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
495where 475where
496 T: HasInterner<Interner = Interner>, 476 T: HasInterner<Interner = Interner>,
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index 89c0ddd1a..c25bc2d6a 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -11,8 +11,7 @@ use smallvec::SmallVec;
11 11
12use crate::{ 12use crate::{
13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId, 13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId,
14 InferenceVar, Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, 14 Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, VariableKinds,
15 VariableKinds,
16}; 15};
17 16
18#[derive(Clone, PartialEq, Eq, Debug, Hash)] 17#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -491,14 +490,16 @@ pub struct AliasEq {
491} 490}
492 491
493#[derive(Clone, Debug, PartialEq, Eq)] 492#[derive(Clone, Debug, PartialEq, Eq)]
494pub struct SolutionVariables(pub Canonical<Substitution>); 493pub struct ConstrainedSubst {
494 pub subst: Substitution,
495}
495 496
496#[derive(Clone, Debug, PartialEq, Eq)] 497#[derive(Clone, Debug, PartialEq, Eq)]
497/// A (possible) solution for a proposed goal. 498/// A (possible) solution for a proposed goal.
498pub enum Solution { 499pub enum Solution {
499 /// The goal indeed holds, and there is a unique value for all existential 500 /// The goal indeed holds, and there is a unique value for all existential
500 /// variables. 501 /// variables.
501 Unique(SolutionVariables), 502 Unique(Canonical<ConstrainedSubst>),
502 503
503 /// The goal may be provable in multiple ways, but regardless we may have some guidance 504 /// The goal may be provable in multiple ways, but regardless we may have some guidance
504 /// for type inference. In this case, we don't return any lifetime 505 /// for type inference. In this case, we don't return any lifetime
@@ -514,13 +515,35 @@ pub enum Guidance {
514 /// The existential variables *must* have the given values if the goal is 515 /// The existential variables *must* have the given values if the goal is
515 /// ever to hold, but that alone isn't enough to guarantee the goal will 516 /// ever to hold, but that alone isn't enough to guarantee the goal will
516 /// actually hold. 517 /// actually hold.
517 Definite(SolutionVariables), 518 Definite(Canonical<Substitution>),
518 519
519 /// There are multiple plausible values for the existentials, but the ones 520 /// There are multiple plausible values for the existentials, but the ones
520 /// here are suggested as the preferred choice heuristically. These should 521 /// here are suggested as the preferred choice heuristically. These should
521 /// be used for inference fallback only. 522 /// be used for inference fallback only.
522 Suggested(SolutionVariables), 523 Suggested(Canonical<Substitution>),
523 524
524 /// There's no useful information to feed back to type inference 525 /// There's no useful information to feed back to type inference
525 Unknown, 526 Unknown,
526} 527}
528
529/// The kinds of placeholders we need during type inference. There's separate
530/// values for general types, and for integer and float variables. The latter
531/// two are used for inference of literal values (e.g. `100` could be one of
532/// several integer types).
533#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
534pub struct InferenceVar {
535 index: u32,
536}
537
538impl From<u32> for InferenceVar {
539 fn from(index: u32) -> InferenceVar {
540 InferenceVar { index }
541 }
542}
543
544impl InferenceVar {
545 /// Gets the underlying index value.
546 pub fn index(self) -> u32 {
547 self.index
548 }
549}