Turn Obligation into something similar to chalk_ir::DomainGoal

This includes starting to make use of Chalk's `Cast` trait.
This commit is contained in:
Florian Diebold 2021-03-20 11:23:59 +01:00
parent 8e7e405f6a
commit 7ec3b66f7a
14 changed files with 130 additions and 91 deletions

View file

@ -56,8 +56,8 @@ use hir_ty::{
primitive::UintTy, primitive::UintTy,
to_assoc_type_id, to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables}, traits::{FnTrait, Solution, SolutionVariables},
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex,
InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind, InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind,
TyVariableKind, WhereClause, TyVariableKind, WhereClause,
}; };
use itertools::Itertools; use itertools::Itertools;
@ -1767,7 +1767,7 @@ impl Type {
let goal = Canonical { let goal = Canonical {
value: hir_ty::InEnvironment::new( value: hir_ty::InEnvironment::new(
self.ty.environment.clone(), self.ty.environment.clone(),
hir_ty::Obligation::Trait(trait_ref), trait_ref.cast(&Interner),
), ),
kinds: Arc::new([]), kinds: Arc::new([]),
}; };
@ -1789,14 +1789,15 @@ impl Type {
let goal = Canonical { let goal = Canonical {
value: InEnvironment::new( value: InEnvironment::new(
self.ty.environment.clone(), self.ty.environment.clone(),
Obligation::AliasEq(AliasEq { AliasEq {
alias: AliasTy::Projection(ProjectionTy { alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(alias.id), associated_ty_id: to_assoc_type_id(alias.id),
substitution: subst, substitution: subst,
}), }),
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner), .intern(&Interner),
}), }
.cast(&Interner),
), ),
kinds: Arc::new([TyVariableKind::General]), kinds: Arc::new([TyVariableKind::General]),
}; };

View file

@ -6,6 +6,7 @@
use std::iter::successors; use std::iter::successors;
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::cast::Cast;
use hir_def::lang_item::LangItemTarget; use hir_def::lang_item::LangItemTarget;
use hir_expand::name::name; use hir_expand::name::name;
use log::{info, warn}; use log::{info, warn};
@ -15,8 +16,8 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id, to_assoc_type_id, to_chalk_trait_id,
traits::{InEnvironment, Solution}, traits::{InEnvironment, Solution},
utils::generics, utils::generics,
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy, AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution,
Substitution, TraitRef, Ty, TyKind, TraitRef, Ty, TyKind,
}; };
const AUTODEREF_RECURSION_LIMIT: usize = 10; const AUTODEREF_RECURSION_LIMIT: usize = 10;
@ -74,7 +75,7 @@ fn deref_by_trait(
let implements_goal = Canonical { let implements_goal = Canonical {
kinds: ty.value.kinds.clone(), kinds: ty.value.kinds.clone(),
value: InEnvironment { value: InEnvironment {
value: Obligation::Trait(trait_ref), value: trait_ref.cast(&Interner),
environment: ty.environment.clone(), environment: ty.environment.clone(),
}, },
}; };
@ -92,7 +93,7 @@ fn deref_by_trait(
.intern(&Interner), .intern(&Interner),
}; };
let obligation = super::Obligation::AliasEq(projection); let obligation = projection.cast(&Interner);
let in_env = InEnvironment { value: obligation, environment: ty.environment }; let in_env = InEnvironment { value: obligation, environment: ty.environment };

View file

@ -0,0 +1,53 @@
//! Implementations of the Chalk `Cast` trait for our types.
use chalk_ir::{
cast::{Cast, CastTo},
interner::HasInterner,
};
use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
macro_rules! has_interner {
($t:ty) => {
impl HasInterner for $t {
type Interner = crate::Interner;
}
};
}
has_interner!(WhereClause);
has_interner!(DomainGoal);
impl CastTo<WhereClause> for TraitRef {
fn cast_to(self, _interner: &Interner) -> WhereClause {
WhereClause::Implemented(self)
}
}
impl CastTo<WhereClause> for AliasEq {
fn cast_to(self, _interner: &Interner) -> WhereClause {
WhereClause::AliasEq(self)
}
}
impl CastTo<DomainGoal> for WhereClause {
fn cast_to(self, _interner: &Interner) -> DomainGoal {
DomainGoal::Holds(self)
}
}
macro_rules! transitive_impl {
($a:ty, $b:ty, $c:ty) => {
impl CastTo<$c> for $a {
fn cast_to(self, interner: &Interner) -> $c {
self.cast::<$b>(interner).cast(interner)
}
}
};
}
// In Chalk, these can be done as blanket impls, but that doesn't work here
// because of coherence
transitive_impl!(TraitRef, WhereClause, DomainGoal);
transitive_impl!(AliasEq, WhereClause, DomainGoal);

View file

@ -119,7 +119,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
fn trait_solve( fn trait_solve(
&self, &self,
krate: CrateId, krate: CrateId,
goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
) -> Option<crate::traits::Solution>; ) -> Option<crate::traits::Solution>;
#[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]

View file

@ -19,7 +19,7 @@ use hir_expand::name::Name;
use crate::{ use crate::{
db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
CallableDefId, CallableSig, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
}; };
@ -805,22 +805,12 @@ impl HirDisplay for Lifetime {
} }
} }
impl HirDisplay for Obligation { impl HirDisplay for DomainGoal {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
match self { match self {
Obligation::Trait(tr) => { DomainGoal::Holds(wc) => {
write!(f, "Implements(")?; write!(f, "Holds(")?;
tr.hir_fmt(f)?; wc.hir_fmt(f)?;
write!(f, ")")
}
Obligation::AliasEq(AliasEq { alias, ty }) => {
write!(f, "Normalize(")?;
match alias {
AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
}
write!(f, " => ")?;
ty.hir_fmt(f)?;
write!(f, ")") write!(f, ")")
} }
} }

View file

@ -18,7 +18,7 @@ use std::mem;
use std::ops::Index; use std::ops::Index;
use std::sync::Arc; use std::sync::Arc;
use chalk_ir::Mutability; use chalk_ir::{cast::Cast, Mutability};
use hir_def::{ use hir_def::{
body::Body, body::Body,
data::{ConstData, FunctionData, StaticData}, data::{ConstData, FunctionData, StaticData},
@ -37,7 +37,7 @@ use stdx::impl_from;
use syntax::SmolStr; use syntax::SmolStr;
use super::{ use super::{
traits::{Guidance, Obligation, Solution}, traits::{DomainGoal, Guidance, Solution},
InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
}; };
use crate::{ use crate::{
@ -204,7 +204,7 @@ struct InferenceContext<'a> {
resolver: Resolver, resolver: Resolver,
table: unify::InferenceTable, table: unify::InferenceTable,
trait_env: Arc<TraitEnvironment>, trait_env: Arc<TraitEnvironment>,
obligations: Vec<Obligation>, obligations: Vec<DomainGoal>,
result: InferenceResult, result: InferenceResult,
/// The return type of the function being inferred, or the closure if we're /// The return type of the function being inferred, or the closure if we're
/// currently within one. /// currently within one.
@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> {
}), }),
ty: ty.clone(), ty: ty.clone(),
}; };
self.obligations.push(Obligation::Trait(trait_ref)); self.obligations.push(trait_ref.cast(&Interner));
self.obligations.push(Obligation::AliasEq(alias_eq)); self.obligations.push(alias_eq.cast(&Interner));
self.resolve_ty_as_possible(ty) self.resolve_ty_as_possible(ty)
} }
None => self.err_ty(), None => self.err_ty(),
@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> {
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
let var = self.table.new_type_var(); let var = self.table.new_type_var();
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
let obligation = Obligation::AliasEq(alias_eq); let obligation = alias_eq.cast(&Interner);
self.obligations.push(obligation); self.obligations.push(obligation);
var var
} }

View file

@ -4,12 +4,11 @@
//! //!
//! See: https://doc.rust-lang.org/nomicon/coercions.html //! See: https://doc.rust-lang.org/nomicon/coercions.html
use chalk_ir::{Mutability, TyVariableKind}; use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
use hir_def::lang_item::LangItemTarget; use hir_def::lang_item::LangItemTarget;
use crate::{ use crate::{
autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef, autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
Ty, TyKind,
}; };
use super::{InEnvironment, InferenceContext}; use super::{InEnvironment, InferenceContext};
@ -143,7 +142,7 @@ impl<'a> InferenceContext<'a> {
.build(); .build();
let trait_ref = let trait_ref =
TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref)); let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner));
let canonicalizer = self.canonicalizer(); let canonicalizer = self.canonicalizer();
let canonicalized = canonicalizer.canonicalize_obligation(goal); let canonicalized = canonicalizer.canonicalize_obligation(goal);

View file

@ -3,7 +3,7 @@
use std::iter::{repeat, repeat_with}; use std::iter::{repeat, repeat_with};
use std::{mem, sync::Arc}; use std::{mem, sync::Arc};
use chalk_ir::{Mutability, TyVariableKind}; use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
use hir_def::{ use hir_def::{
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
path::{GenericArg, GenericArgs}, path::{GenericArg, GenericArgs},
@ -21,7 +21,7 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id, to_assoc_type_id, to_chalk_trait_id,
traits::{chalk::from_chalk, FnTrait, InEnvironment}, traits::{chalk::from_chalk, FnTrait, InEnvironment},
utils::{generics, variant_data, Generics}, utils::{generics, variant_data, Generics},
AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar,
Substitution, TraitRef, Ty, TyKind, Substitution, TraitRef, Ty, TyKind,
}; };
@ -90,10 +90,9 @@ impl<'a> InferenceContext<'a> {
Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build();
let trait_env = Arc::clone(&self.trait_env); let trait_env = Arc::clone(&self.trait_env);
let implements_fn_trait = Obligation::Trait(TraitRef { let implements_fn_trait: DomainGoal =
trait_id: to_chalk_trait_id(fn_once_trait), TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() }
substitution: substs.clone(), .cast(&Interner);
});
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
value: implements_fn_trait.clone(), value: implements_fn_trait.clone(),
environment: trait_env, environment: trait_env,
@ -938,22 +937,20 @@ impl<'a> InferenceContext<'a> {
let generic_predicates = self.db.generic_predicates(def.into()); let generic_predicates = self.db.generic_predicates(def.into());
for predicate in generic_predicates.iter() { for predicate in generic_predicates.iter() {
let predicate = predicate.clone().subst(parameters); let predicate = predicate.clone().subst(parameters);
if let Some(obligation) = Obligation::from_predicate(predicate) { self.obligations.push(predicate.cast(&Interner));
self.obligations.push(obligation);
}
} }
// add obligation for trait implementation, if this is a trait method // add obligation for trait implementation, if this is a trait method
match def { match def {
CallableDefId::FunctionId(f) => { CallableDefId::FunctionId(f) => {
if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
{ {
// construct a TraitDef // construct a TraitRef
let substs = let substs =
parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); parameters.prefix(generics(self.db.upcast(), trait_.into()).len());
self.obligations.push(Obligation::Trait(TraitRef { self.obligations.push(
trait_id: to_chalk_trait_id(trait_), TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
substitution: substs, .cast(&Interner),
})); );
} }
} }
CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {}

View file

@ -2,6 +2,7 @@
use std::iter; use std::iter;
use chalk_ir::cast::Cast;
use hir_def::{ use hir_def::{
path::{Path, PathSegment}, path::{Path, PathSegment},
resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs},
@ -256,10 +257,13 @@ impl<'a> InferenceContext<'a> {
.push(ty.clone()) .push(ty.clone())
.fill(std::iter::repeat_with(|| self.table.new_type_var())) .fill(std::iter::repeat_with(|| self.table.new_type_var()))
.build(); .build();
self.obligations.push(super::Obligation::Trait(TraitRef { self.obligations.push(
trait_id: to_chalk_trait_id(trait_), TraitRef {
substitution: trait_substs.clone(), trait_id: to_chalk_trait_id(trait_),
})); substitution: trait_substs.clone(),
}
.cast(&Interner),
);
Some(trait_substs) Some(trait_substs)
} }
AssocContainerId::ModuleId(_) => None, AssocContainerId::ModuleId(_) => None,

View file

@ -5,7 +5,7 @@ use std::borrow::Cow;
use chalk_ir::{FloatTy, IntTy, TyVariableKind}; use chalk_ir::{FloatTy, IntTy, TyVariableKind};
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
use super::{InferenceContext, Obligation}; use super::{DomainGoal, InferenceContext};
use crate::{ use crate::{
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar,
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause,
@ -87,14 +87,11 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
pub(crate) fn canonicalize_obligation( pub(crate) fn canonicalize_obligation(
mut self, mut self,
obligation: InEnvironment<Obligation>, obligation: InEnvironment<DomainGoal>,
) -> Canonicalized<InEnvironment<Obligation>> { ) -> Canonicalized<InEnvironment<DomainGoal>> {
let result = match obligation.value { let result = match obligation.value {
Obligation::Trait(tr) => { DomainGoal::Holds(wc) => {
Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
}
Obligation::AliasEq(alias_eq) => {
Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
} }
}; };
self.into_canonicalized(InEnvironment { self.into_canonicalized(InEnvironment {

View file

@ -13,6 +13,7 @@ mod op;
mod lower; mod lower;
pub(crate) mod infer; pub(crate) mod infer;
pub(crate) mod utils; pub(crate) mod utils;
mod chalk_cast;
pub mod display; pub mod display;
pub mod db; pub mod db;
@ -45,9 +46,11 @@ pub use lower::{
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
TyDefId, TyLoweringContext, ValueTyDefId, TyDefId, TyLoweringContext, ValueTyDefId,
}; };
pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment}; pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; pub use chalk_ir::{
cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
};
pub use crate::traits::chalk::Interner; pub use crate::traits::chalk::Interner;

View file

@ -6,7 +6,7 @@ use std::{iter, sync::Arc};
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::Mutability; use chalk_ir::{cast::Cast, Mutability};
use hir_def::{ use hir_def::{
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
ImplId, Lookup, ModuleId, TraitId, ImplId, Lookup, ModuleId, TraitId,
@ -767,7 +767,7 @@ fn generic_implements_goal(
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
trait_: TraitId, trait_: TraitId,
self_ty: Canonical<Ty>, self_ty: Canonical<Ty>,
) -> Canonical<InEnvironment<super::Obligation>> { ) -> Canonical<InEnvironment<super::DomainGoal>> {
let mut kinds = self_ty.kinds.to_vec(); let mut kinds = self_ty.kinds.to_vec();
let substs = super::Substitution::build_for_def(db, trait_) let substs = super::Substitution::build_for_def(db, trait_)
.push(self_ty.value) .push(self_ty.value)
@ -775,7 +775,7 @@ fn generic_implements_goal(
.build(); .build();
kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1));
let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
let obligation = super::Obligation::Trait(trait_ref); let obligation = trait_ref.cast(&Interner);
Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
} }

View file

@ -9,8 +9,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId};
use stdx::panic_context; use stdx::panic_context;
use crate::{ use crate::{
db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, TraitRef, Ty, db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind,
TyKind, TypeWalk, WhereClause, TypeWalk, WhereClause,
}; };
use self::chalk::{from_chalk, Interner, ToChalk}; use self::chalk::{from_chalk, Interner, ToChalk};
@ -88,20 +88,8 @@ impl<T> InEnvironment<T> {
/// a certain type implements a certain trait. Proving the Obligation might /// a certain type implements a certain trait. Proving the Obligation might
/// result in additional information about inference variables. /// result in additional information about inference variables.
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Obligation { pub enum DomainGoal {
/// Prove that a certain type implements a trait (the type is the `Self` type Holds(WhereClause),
/// parameter to the `TraitRef`).
Trait(TraitRef),
AliasEq(AliasEq),
}
impl Obligation {
pub fn from_predicate(predicate: WhereClause) -> Option<Obligation> {
match predicate {
WhereClause::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
WhereClause::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
}
}
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
@ -136,16 +124,20 @@ impl TypeWalk for AliasEq {
pub(crate) fn trait_solve_query( pub(crate) fn trait_solve_query(
db: &dyn HirDatabase, db: &dyn HirDatabase,
krate: CrateId, krate: CrateId,
goal: Canonical<InEnvironment<Obligation>>, goal: Canonical<InEnvironment<DomainGoal>>,
) -> Option<Solution> { ) -> Option<Solution> {
let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value {
Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), DomainGoal::Holds(WhereClause::Implemented(it)) => {
Obligation::AliasEq(_) => "alias_eq".to_string(), db.trait_data(it.hir_trait_id()).name.to_string()
}
DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
}); });
log::info!("trait_solve_query({})", goal.value.value.display(db)); log::info!("trait_solve_query({})", goal.value.value.display(db));
if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) = if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
&goal.value.value alias: AliasTy::Projection(projection_ty),
..
})) = &goal.value.value
{ {
if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) {
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible

View file

@ -13,7 +13,7 @@ use crate::{
db::HirDatabase, db::HirDatabase,
from_assoc_type_id, from_assoc_type_id,
primitive::UintTy, primitive::UintTy,
traits::{Canonical, Obligation}, traits::{Canonical, DomainGoal},
AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution,
TraitRef, Ty, WhereClause, TraitRef, Ty, WhereClause,
}; };
@ -422,13 +422,15 @@ impl ToChalk for AliasEq {
} }
} }
impl ToChalk for Obligation { impl ToChalk for DomainGoal {
type Chalk = chalk_ir::DomainGoal<Interner>; type Chalk = chalk_ir::DomainGoal<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
match self { match self {
Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner), DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
alias_eq.to_chalk(db).cast(&Interner)
}
} }
} }