aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/lib.rs8
-rw-r--r--crates/hir_def/src/attr.rs57
-rw-r--r--crates/hir_def/src/db.rs15
-rw-r--r--crates/hir_def/src/lib.rs8
-rw-r--r--crates/hir_ty/src/autoderef.rs10
-rw-r--r--crates/hir_ty/src/infer.rs34
-rw-r--r--crates/hir_ty/src/infer/coerce.rs11
-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/traits.rs16
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs118
-rw-r--r--crates/hir_ty/src/types.rs35
-rw-r--r--crates/ide_db/src/apply_change.rs4
13 files changed, 210 insertions, 144 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 8d00f7401..caa22dace 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -58,9 +58,8 @@ use hir_ty::{
58 subst_prefix, 58 subst_prefix,
59 traits::FnTrait, 59 traits::FnTrait,
60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution,
62 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyExt, TyKind, 62 TraitEnvironment, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
63 TyVariableKind, WhereClause,
64}; 63};
65use itertools::Itertools; 64use itertools::Itertools;
66use rustc_hash::FxHashSet; 65use rustc_hash::FxHashSet;
@@ -1822,8 +1821,9 @@ impl Type {
1822 ); 1821 );
1823 1822
1824 match db.trait_solve(self.krate, goal)? { 1823 match db.trait_solve(self.krate, goal)? {
1825 Solution::Unique(SolutionVariables(subst)) => subst 1824 Solution::Unique(s) => s
1826 .value 1825 .value
1826 .subst
1827 .interned() 1827 .interned()
1828 .first() 1828 .first()
1829 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), 1829 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 8a25b8731..d9df7564d 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -16,7 +16,7 @@ use mbe::ast_to_token_tree;
16use smallvec::{smallvec, SmallVec}; 16use smallvec::{smallvec, SmallVec};
17use syntax::{ 17use syntax::{
18 ast::{self, AstNode, AttrsOwner}, 18 ast::{self, AstNode, AttrsOwner},
19 match_ast, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, 19 match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
20}; 20};
21use tt::Subtree; 21use tt::Subtree;
22 22
@@ -403,10 +403,14 @@ impl AttrsWithOwner {
403 return AttrSourceMap { attrs }; 403 return AttrSourceMap { attrs };
404 } 404 }
405 AttrDefId::FieldId(id) => { 405 AttrDefId::FieldId(id) => {
406 id.parent.child_source(db).map(|source| match &source[id.local_id] { 406 let map = db.fields_attrs_source_map(id.parent);
407 Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), 407 let file_id = id.parent.file_id(db);
408 Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), 408 let root = db.parse_or_expand(file_id).unwrap();
409 }) 409 let owner = match &map[id.local_id] {
410 Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
411 Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)),
412 };
413 InFile::new(file_id, owner)
410 } 414 }
411 AttrDefId::AdtId(adt) => match adt { 415 AttrDefId::AdtId(adt) => match adt {
412 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 416 AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -414,10 +418,12 @@ impl AttrsWithOwner {
414 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 418 AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
415 }, 419 },
416 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 420 AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
417 AttrDefId::EnumVariantId(id) => id 421 AttrDefId::EnumVariantId(id) => {
418 .parent 422 let map = db.variants_attrs_source_map(id.parent);
419 .child_source(db) 423 let file_id = id.parent.lookup(db).id.file_id();
420 .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), 424 let root = db.parse_or_expand(file_id).unwrap();
425 InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root)))
426 }
421 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 427 AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
422 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 428 AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
423 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), 429 AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new),
@@ -746,3 +752,36 @@ fn collect_attrs(
746 752
747 attrs.into_iter().map(|(_, attr)| attr) 753 attrs.into_iter().map(|(_, attr)| attr)
748} 754}
755
756pub(crate) fn variants_attrs_source_map(
757 db: &dyn DefDatabase,
758 def: EnumId,
759) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
760 let mut res = ArenaMap::default();
761 let child_source = def.child_source(db);
762
763 for (idx, variant) in child_source.value.iter() {
764 res.insert(idx, AstPtr::new(variant));
765 }
766
767 Arc::new(res)
768}
769
770pub(crate) fn fields_attrs_source_map(
771 db: &dyn DefDatabase,
772 def: VariantId,
773) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
774 let mut res = ArenaMap::default();
775 let child_source = def.child_source(db);
776
777 for (idx, variant) in child_source.value.iter() {
778 res.insert(
779 idx,
780 variant
781 .as_ref()
782 .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
783 );
784 }
785
786 Arc::new(res)
787}
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs
index 9b7a213a1..7eadc8e0d 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -2,9 +2,10 @@
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use base_db::{salsa, CrateId, SourceDatabase, Upcast}; 4use base_db::{salsa, CrateId, SourceDatabase, Upcast};
5use either::Either;
5use hir_expand::{db::AstDatabase, HirFileId}; 6use hir_expand::{db::AstDatabase, HirFileId};
6use la_arena::ArenaMap; 7use la_arena::ArenaMap;
7use syntax::SmolStr; 8use syntax::{ast, AstPtr, SmolStr};
8 9
9use crate::{ 10use crate::{
10 adt::{EnumData, StructData}, 11 adt::{EnumData, StructData},
@@ -122,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
122 #[salsa::invoke(Attrs::fields_attrs_query)] 123 #[salsa::invoke(Attrs::fields_attrs_query)]
123 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; 124 fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
124 125
126 #[salsa::invoke(crate::attr::variants_attrs_source_map)]
127 fn variants_attrs_source_map(
128 &self,
129 def: EnumId,
130 ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>;
131
132 #[salsa::invoke(crate::attr::fields_attrs_source_map)]
133 fn fields_attrs_source_map(
134 &self,
135 def: VariantId,
136 ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>;
137
125 #[salsa::invoke(AttrsWithOwner::attrs_query)] 138 #[salsa::invoke(AttrsWithOwner::attrs_query)]
126 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; 139 fn attrs(&self, def: AttrDefId) -> AttrsWithOwner;
127 140
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index abd6c553f..e2af0e514 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -453,6 +453,14 @@ impl VariantId {
453 } 453 }
454 } 454 }
455 } 455 }
456
457 pub fn file_id(self, db: &dyn db::DefDatabase) -> HirFileId {
458 match self {
459 VariantId::EnumVariantId(it) => it.parent.lookup(db).id.file_id(),
460 VariantId::StructId(it) => it.lookup(db).id.file_id(),
461 VariantId::UnionId(it) => it.lookup(db).id.file_id(),
462 }
463 }
456} 464}
457 465
458trait Intern { 466trait Intern {
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 efe9198cc..7c6c3600b 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.
@@ -342,11 +342,18 @@ impl<'a> InferenceContext<'a> {
342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
343 343
344 match solution { 344 match solution {
345 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
346 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 );
347 } 354 }
348 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
349 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
350 self.obligations.push(obligation); 357 self.obligations.push(obligation);
351 } 358 }
352 Some(_) => { 359 Some(_) => {
@@ -683,25 +690,6 @@ impl<'a> InferenceContext<'a> {
683 } 690 }
684} 691}
685 692
686/// The kinds of placeholders we need during type inference. There's separate
687/// values for general types, and for integer and float variables. The latter
688/// two are used for inference of literal values (e.g. `100` could be one of
689/// several integer types).
690#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
691pub struct InferenceVar {
692 index: u32,
693}
694
695impl InferenceVar {
696 fn to_inner(self) -> unify::TypeVarId {
697 unify::TypeVarId(self.index)
698 }
699
700 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
701 InferenceVar { index }
702 }
703}
704
705/// When inferring an expression, we propagate downward whatever type hint we 693/// When inferring an expression, we propagate downward whatever type hint we
706/// are able in the form of an `Expectation`. 694/// are able in the form of an `Expectation`.
707#[derive(Clone, PartialEq, Eq, Debug)] 695#[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/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/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}
diff --git a/crates/ide_db/src/apply_change.rs b/crates/ide_db/src/apply_change.rs
index 111e9325a..6c67425d7 100644
--- a/crates/ide_db/src/apply_change.rs
+++ b/crates/ide_db/src/apply_change.rs
@@ -152,6 +152,10 @@ impl RootDatabase {
152 hir::db::FileItemTreeQuery 152 hir::db::FileItemTreeQuery
153 hir::db::BlockDefMapQuery 153 hir::db::BlockDefMapQuery
154 hir::db::CrateDefMapQueryQuery 154 hir::db::CrateDefMapQueryQuery
155 hir::db::FieldsAttrsQuery
156 hir::db::VariantsAttrsQuery
157 hir::db::FieldsAttrsSourceMapQuery
158 hir::db::VariantsAttrsSourceMapQuery
155 hir::db::StructDataQuery 159 hir::db::StructDataQuery
156 hir::db::UnionDataQuery 160 hir::db::UnionDataQuery
157 hir::db::EnumDataQuery 161 hir::db::EnumDataQuery