aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/autoderef.rs9
-rw-r--r--crates/hir_ty/src/chalk_cast.rs53
-rw-r--r--crates/hir_ty/src/db.rs2
-rw-r--r--crates/hir_ty/src/display.rs20
-rw-r--r--crates/hir_ty/src/infer.rs12
-rw-r--r--crates/hir_ty/src/infer/coerce.rs7
-rw-r--r--crates/hir_ty/src/infer/expr.rs25
-rw-r--r--crates/hir_ty/src/infer/path.rs12
-rw-r--r--crates/hir_ty/src/infer/unify.rs13
-rw-r--r--crates/hir_ty/src/lib.rs7
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/traits.rs34
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs10
13 files changed, 124 insertions, 86 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 33b966026..23ab042c1 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,6 +6,7 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast;
9use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
10use hir_expand::name::name; 11use hir_expand::name::name;
11use log::{info, warn}; 12use log::{info, warn};
@@ -15,8 +16,8 @@ use crate::{
15 to_assoc_type_id, to_chalk_trait_id, 16 to_assoc_type_id, to_chalk_trait_id,
16 traits::{InEnvironment, Solution}, 17 traits::{InEnvironment, Solution},
17 utils::generics, 18 utils::generics,
18 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy, 19 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
19 Substitution, TraitRef, Ty, TyKind, 20 TraitRef, Ty, TyKind,
20}; 21};
21 22
22const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -74,7 +75,7 @@ fn deref_by_trait(
74 let implements_goal = Canonical { 75 let implements_goal = Canonical {
75 kinds: ty.value.kinds.clone(), 76 kinds: ty.value.kinds.clone(),
76 value: InEnvironment { 77 value: InEnvironment {
77 value: Obligation::Trait(trait_ref), 78 value: trait_ref.cast(&Interner),
78 environment: ty.environment.clone(), 79 environment: ty.environment.clone(),
79 }, 80 },
80 }; 81 };
@@ -92,7 +93,7 @@ fn deref_by_trait(
92 .intern(&Interner), 93 .intern(&Interner),
93 }; 94 };
94 95
95 let obligation = super::Obligation::AliasEq(projection); 96 let obligation = projection.cast(&Interner);
96 97
97 let in_env = InEnvironment { value: obligation, environment: ty.environment }; 98 let in_env = InEnvironment { value: obligation, environment: ty.environment };
98 99
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
new file mode 100644
index 000000000..bf884ae15
--- /dev/null
+++ b/crates/hir_ty/src/chalk_cast.rs
@@ -0,0 +1,53 @@
1//! Implementations of the Chalk `Cast` trait for our types.
2
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20
21impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause {
23 WhereClause::Implemented(self)
24 }
25}
26
27impl CastTo<WhereClause> for AliasEq {
28 fn cast_to(self, _interner: &Interner) -> WhereClause {
29 WhereClause::AliasEq(self)
30 }
31}
32
33impl CastTo<DomainGoal> for WhereClause {
34 fn cast_to(self, _interner: &Interner) -> DomainGoal {
35 DomainGoal::Holds(self)
36 }
37}
38
39macro_rules! transitive_impl {
40 ($a:ty, $b:ty, $c:ty) => {
41 impl CastTo<$c> for $a {
42 fn cast_to(self, interner: &Interner) -> $c {
43 self.cast::<$b>(interner).cast(interner)
44 }
45 }
46 };
47}
48
49// In Chalk, these can be done as blanket impls, but that doesn't work here
50// because of coherence
51
52transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_impl!(AliasEq, WhereClause, DomainGoal);
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 300da0f38..91a2e0b5b 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -119,7 +119,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
119 fn trait_solve( 119 fn trait_solve(
120 &self, 120 &self,
121 krate: CrateId, 121 krate: CrateId,
122 goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, 122 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
123 ) -> Option<crate::traits::Solution>; 123 ) -> Option<crate::traits::Solution>;
124 124
125 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 125 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 4765c99a4..3845009ae 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -19,7 +19,7 @@ use hir_expand::name::Name;
19use crate::{ 19use crate::{
20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, 21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
22 CallableDefId, CallableSig, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, 22 CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
23 ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, 23 ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
24}; 24};
25 25
@@ -805,22 +805,12 @@ impl HirDisplay for Lifetime {
805 } 805 }
806} 806}
807 807
808impl HirDisplay for Obligation { 808impl HirDisplay for DomainGoal {
809 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 809 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
810 match self { 810 match self {
811 Obligation::Trait(tr) => { 811 DomainGoal::Holds(wc) => {
812 write!(f, "Implements(")?; 812 write!(f, "Holds(")?;
813 tr.hir_fmt(f)?; 813 wc.hir_fmt(f)?;
814 write!(f, ")")
815 }
816 Obligation::AliasEq(AliasEq { alias, ty }) => {
817 write!(f, "Normalize(")?;
818 match alias {
819 AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
820 AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
821 }
822 write!(f, " => ")?;
823 ty.hir_fmt(f)?;
824 write!(f, ")") 814 write!(f, ")")
825 } 815 }
826 } 816 }
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 82186979a..b9e434c78 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -18,7 +18,7 @@ use std::mem;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::Mutability; 21use chalk_ir::{cast::Cast, Mutability};
22use hir_def::{ 22use hir_def::{
23 body::Body, 23 body::Body,
24 data::{ConstData, FunctionData, StaticData}, 24 data::{ConstData, FunctionData, StaticData},
@@ -37,7 +37,7 @@ use stdx::impl_from;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{Guidance, Obligation, Solution}, 40 traits::{DomainGoal, Guidance, Solution},
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
@@ -204,7 +204,7 @@ struct InferenceContext<'a> {
204 resolver: Resolver, 204 resolver: Resolver,
205 table: unify::InferenceTable, 205 table: unify::InferenceTable,
206 trait_env: Arc<TraitEnvironment>, 206 trait_env: Arc<TraitEnvironment>,
207 obligations: Vec<Obligation>, 207 obligations: Vec<DomainGoal>,
208 result: InferenceResult, 208 result: InferenceResult,
209 /// The return type of the function being inferred, or the closure if we're 209 /// The return type of the function being inferred, or the closure if we're
210 /// currently within one. 210 /// currently within one.
@@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> {
403 }), 403 }),
404 ty: ty.clone(), 404 ty: ty.clone(),
405 }; 405 };
406 self.obligations.push(Obligation::Trait(trait_ref)); 406 self.obligations.push(trait_ref.cast(&Interner));
407 self.obligations.push(Obligation::AliasEq(alias_eq)); 407 self.obligations.push(alias_eq.cast(&Interner));
408 self.resolve_ty_as_possible(ty) 408 self.resolve_ty_as_possible(ty)
409 } 409 }
410 None => self.err_ty(), 410 None => self.err_ty(),
@@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> {
430 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 430 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
431 let var = self.table.new_type_var(); 431 let var = self.table.new_type_var();
432 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; 432 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
433 let obligation = Obligation::AliasEq(alias_eq); 433 let obligation = alias_eq.cast(&Interner);
434 self.obligations.push(obligation); 434 self.obligations.push(obligation);
435 var 435 var
436 } 436 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index b86474ed4..07eb96573 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -4,12 +4,11 @@
4//! 4//!
5//! See: https://doc.rust-lang.org/nomicon/coercions.html 5//! See: https://doc.rust-lang.org/nomicon/coercions.html
6 6
7use chalk_ir::{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::{ 10use crate::{
11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef, 11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
12 Ty, TyKind,
13}; 12};
14 13
15use super::{InEnvironment, InferenceContext}; 14use super::{InEnvironment, InferenceContext};
@@ -143,7 +142,7 @@ impl<'a> InferenceContext<'a> {
143 .build(); 142 .build();
144 let trait_ref = 143 let trait_ref =
145 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; 144 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
146 let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref)); 145 let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner));
147 146
148 let canonicalizer = self.canonicalizer(); 147 let canonicalizer = self.canonicalizer();
149 let canonicalized = canonicalizer.canonicalize_obligation(goal); 148 let canonicalized = canonicalizer.canonicalize_obligation(goal);
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 93548b6c0..79bbc5dab 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,7 +3,7 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
7use hir_def::{ 7use hir_def::{
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
@@ -21,7 +21,7 @@ use crate::{
21 to_assoc_type_id, to_chalk_trait_id, 21 to_assoc_type_id, to_chalk_trait_id,
22 traits::{chalk::from_chalk, FnTrait, InEnvironment}, 22 traits::{chalk::from_chalk, FnTrait, InEnvironment},
23 utils::{generics, variant_data, Generics}, 23 utils::{generics, variant_data, Generics},
24 AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, 24 AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar,
25 Substitution, TraitRef, Ty, TyKind, 25 Substitution, TraitRef, Ty, TyKind,
26}; 26};
27 27
@@ -90,10 +90,9 @@ impl<'a> InferenceContext<'a> {
90 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 90 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
91 91
92 let trait_env = Arc::clone(&self.trait_env); 92 let trait_env = Arc::clone(&self.trait_env);
93 let implements_fn_trait = Obligation::Trait(TraitRef { 93 let implements_fn_trait: DomainGoal =
94 trait_id: to_chalk_trait_id(fn_once_trait), 94 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
95 substitution: substs.clone(), 95 .cast(&Interner);
96 });
97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { 96 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
98 value: implements_fn_trait.clone(), 97 value: implements_fn_trait.clone(),
99 environment: trait_env, 98 environment: trait_env,
@@ -938,22 +937,20 @@ impl<'a> InferenceContext<'a> {
938 let generic_predicates = self.db.generic_predicates(def.into()); 937 let generic_predicates = self.db.generic_predicates(def.into());
939 for predicate in generic_predicates.iter() { 938 for predicate in generic_predicates.iter() {
940 let predicate = predicate.clone().subst(parameters); 939 let predicate = predicate.clone().subst(parameters);
941 if let Some(obligation) = Obligation::from_predicate(predicate) { 940 self.obligations.push(predicate.cast(&Interner));
942 self.obligations.push(obligation);
943 }
944 } 941 }
945 // add obligation for trait implementation, if this is a trait method 942 // add obligation for trait implementation, if this is a trait method
946 match def { 943 match def {
947 CallableDefId::FunctionId(f) => { 944 CallableDefId::FunctionId(f) => {
948 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container 945 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
949 { 946 {
950 // construct a TraitDef 947 // construct a TraitRef
951 let substs = 948 let substs =
952 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 949 parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
953 self.obligations.push(Obligation::Trait(TraitRef { 950 self.obligations.push(
954 trait_id: to_chalk_trait_id(trait_), 951 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
955 substitution: substs, 952 .cast(&Interner),
956 })); 953 );
957 } 954 }
958 } 955 }
959 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} 956 CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index e15135fc1..58cce56ab 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -2,6 +2,7 @@
2 2
3use std::iter; 3use std::iter;
4 4
5use chalk_ir::cast::Cast;
5use hir_def::{ 6use hir_def::{
6 path::{Path, PathSegment}, 7 path::{Path, PathSegment},
7 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, 8 resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@@ -256,10 +257,13 @@ impl<'a> InferenceContext<'a> {
256 .push(ty.clone()) 257 .push(ty.clone())
257 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 258 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
258 .build(); 259 .build();
259 self.obligations.push(super::Obligation::Trait(TraitRef { 260 self.obligations.push(
260 trait_id: to_chalk_trait_id(trait_), 261 TraitRef {
261 substitution: trait_substs.clone(), 262 trait_id: to_chalk_trait_id(trait_),
262 })); 263 substitution: trait_substs.clone(),
264 }
265 .cast(&Interner),
266 );
263 Some(trait_substs) 267 Some(trait_substs)
264 } 268 }
265 AssocContainerId::ModuleId(_) => None, 269 AssocContainerId::ModuleId(_) => None,
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 5b7b423fa..1fc03c8f4 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -5,7 +5,7 @@ use std::borrow::Cow;
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use crate::{
10 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, 10 AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
11 Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, 11 Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
@@ -87,14 +87,11 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
87 87
88 pub(crate) fn canonicalize_obligation( 88 pub(crate) fn canonicalize_obligation(
89 mut self, 89 mut self,
90 obligation: InEnvironment<Obligation>, 90 obligation: InEnvironment<DomainGoal>,
91 ) -> Canonicalized<InEnvironment<Obligation>> { 91 ) -> Canonicalized<InEnvironment<DomainGoal>> {
92 let result = match obligation.value { 92 let result = match obligation.value {
93 Obligation::Trait(tr) => { 93 DomainGoal::Holds(wc) => {
94 Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) 94 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
95 }
96 Obligation::AliasEq(alias_eq) => {
97 Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
98 } 95 }
99 }; 96 };
100 self.into_canonicalized(InEnvironment { 97 self.into_canonicalized(InEnvironment {
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 8de2d422f..c46529879 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -13,6 +13,7 @@ mod op;
13mod lower; 13mod lower;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast;
16 17
17pub mod display; 18pub mod display;
18pub mod db; 19pub mod db;
@@ -45,9 +46,11 @@ pub use lower::{
45 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 46 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
46 TyDefId, TyLoweringContext, ValueTyDefId, 47 TyDefId, TyLoweringContext, ValueTyDefId,
47}; 48};
48pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment}; 49pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
49 50
50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; 51pub use chalk_ir::{
52 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
53};
51 54
52pub use crate::traits::chalk::Interner; 55pub use crate::traits::chalk::Interner;
53 56
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 01b78fb44..da6bc2a4a 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::Mutability; 9use chalk_ir::{cast::Cast, Mutability};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, 11 lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
12 ImplId, Lookup, ModuleId, TraitId, 12 ImplId, Lookup, ModuleId, TraitId,
@@ -767,7 +767,7 @@ fn generic_implements_goal(
767 env: Arc<TraitEnvironment>, 767 env: Arc<TraitEnvironment>,
768 trait_: TraitId, 768 trait_: TraitId,
769 self_ty: Canonical<Ty>, 769 self_ty: Canonical<Ty>,
770) -> Canonical<InEnvironment<super::Obligation>> { 770) -> Canonical<InEnvironment<super::DomainGoal>> {
771 let mut kinds = self_ty.kinds.to_vec(); 771 let mut kinds = self_ty.kinds.to_vec();
772 let substs = super::Substitution::build_for_def(db, trait_) 772 let substs = super::Substitution::build_for_def(db, trait_)
773 .push(self_ty.value) 773 .push(self_ty.value)
@@ -775,7 +775,7 @@ fn generic_implements_goal(
775 .build(); 775 .build();
776 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); 776 kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
777 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; 777 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
778 let obligation = super::Obligation::Trait(trait_ref); 778 let obligation = trait_ref.cast(&Interner);
779 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } 779 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
780} 780}
781 781
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index 87c92bd12..7dadd1ffb 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -9,8 +9,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId};
9use stdx::panic_context; 9use stdx::panic_context;
10 10
11use crate::{ 11use crate::{
12 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, TraitRef, Ty, 12 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind,
13 TyKind, TypeWalk, WhereClause, 13 TypeWalk, WhereClause,
14}; 14};
15 15
16use self::chalk::{from_chalk, Interner, ToChalk}; 16use self::chalk::{from_chalk, Interner, ToChalk};
@@ -88,20 +88,8 @@ impl<T> InEnvironment<T> {
88/// a certain type implements a certain trait. Proving the Obligation might 88/// a certain type implements a certain trait. Proving the Obligation might
89/// result in additional information about inference variables. 89/// result in additional information about inference variables.
90#[derive(Clone, Debug, PartialEq, Eq, Hash)] 90#[derive(Clone, Debug, PartialEq, Eq, Hash)]
91pub enum Obligation { 91pub enum DomainGoal {
92 /// Prove that a certain type implements a trait (the type is the `Self` type 92 Holds(WhereClause),
93 /// parameter to the `TraitRef`).
94 Trait(TraitRef),
95 AliasEq(AliasEq),
96}
97
98impl Obligation {
99 pub fn from_predicate(predicate: WhereClause) -> Option<Obligation> {
100 match predicate {
101 WhereClause::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
102 WhereClause::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
103 }
104 }
105} 93}
106 94
107#[derive(Clone, Debug, PartialEq, Eq, Hash)] 95#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -136,16 +124,20 @@ impl TypeWalk for AliasEq {
136pub(crate) fn trait_solve_query( 124pub(crate) fn trait_solve_query(
137 db: &dyn HirDatabase, 125 db: &dyn HirDatabase,
138 krate: CrateId, 126 krate: CrateId,
139 goal: Canonical<InEnvironment<Obligation>>, 127 goal: Canonical<InEnvironment<DomainGoal>>,
140) -> Option<Solution> { 128) -> Option<Solution> {
141 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { 129 let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
142 Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), 130 DomainGoal::Holds(WhereClause::Implemented(it)) => {
143 Obligation::AliasEq(_) => "alias_eq".to_string(), 131 db.trait_data(it.hir_trait_id()).name.to_string()
132 }
133 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
144 }); 134 });
145 log::info!("trait_solve_query({})", goal.value.value.display(db)); 135 log::info!("trait_solve_query({})", goal.value.value.display(db));
146 136
147 if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) = 137 if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
148 &goal.value.value 138 alias: AliasTy::Projection(projection_ty),
139 ..
140 })) = &goal.value.value
149 { 141 {
150 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { 142 if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
151 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible 143 // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 7841c216c..65feb82e5 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -13,7 +13,7 @@ use crate::{
13 db::HirDatabase, 13 db::HirDatabase,
14 from_assoc_type_id, 14 from_assoc_type_id,
15 primitive::UintTy, 15 primitive::UintTy,
16 traits::{Canonical, Obligation}, 16 traits::{Canonical, DomainGoal},
17 AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, 17 AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution,
18 TraitRef, Ty, WhereClause, 18 TraitRef, Ty, WhereClause,
19}; 19};
@@ -422,13 +422,15 @@ impl ToChalk for AliasEq {
422 } 422 }
423} 423}
424 424
425impl ToChalk for Obligation { 425impl ToChalk for DomainGoal {
426 type Chalk = chalk_ir::DomainGoal<Interner>; 426 type Chalk = chalk_ir::DomainGoal<Interner>;
427 427
428 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { 428 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
429 match self { 429 match self {
430 Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), 430 DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
431 Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner), 431 DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
432 alias_eq.to_chalk(db).cast(&Interner)
433 }
432 } 434 }
433 } 435 }
434 436