Replace Projection variant in GenericPredicate with AliasEq

This commit is contained in:
Lukas Wirth 2021-03-19 02:07:15 +01:00
parent 86878443b1
commit 8996b1a235
10 changed files with 223 additions and 133 deletions

View File

@ -56,9 +56,9 @@ use hir_ty::{
primitive::UintTy,
to_assoc_type_id,
traits::{FnTrait, Solution, SolutionVariables},
AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate,
InEnvironment, Interner, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substitution,
Ty, TyDefId, TyKind, TyVariableKind,
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex,
GenericPredicate, InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty,
TyDefId, TyKind, TyVariableKind,
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
@ -1786,17 +1786,17 @@ impl Type {
.push(self.ty.value.clone())
.fill(args.iter().map(|t| t.ty.value.clone()))
.build();
let predicate = ProjectionPredicate {
projection_ty: ProjectionTy {
associated_ty_id: to_assoc_type_id(alias.id),
substitution: subst,
},
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner),
};
let goal = Canonical {
value: InEnvironment::new(
self.ty.environment.clone(),
Obligation::Projection(predicate),
Obligation::AliasEq(AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(alias.id),
substitution: subst,
}),
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner),
}),
),
kinds: Arc::new([TyVariableKind::General]),
};

View File

@ -15,7 +15,8 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id,
traits::{InEnvironment, Solution},
utils::generics,
BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind,
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy,
Substitution, TraitRef, Ty, TyKind,
};
const AUTODEREF_RECURSION_LIMIT: usize = 10;
@ -82,16 +83,16 @@ fn deref_by_trait(
}
// Now do the assoc type projection
let projection = super::traits::ProjectionPredicate {
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
.intern(&Interner),
projection_ty: super::ProjectionTy {
let projection = AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(target),
substitution: parameters,
},
}),
ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len()))
.intern(&Interner),
};
let obligation = super::Obligation::Projection(projection);
let obligation = super::Obligation::AliasEq(projection);
let in_env = InEnvironment { value: obligation, environment: ty.environment };

View File

@ -18,9 +18,9 @@ use hir_expand::name::Name;
use crate::{
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, AliasTy, CallableDefId,
CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy,
ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind,
to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
CallableDefId, CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation,
OpaqueTy, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind,
};
pub struct HirFormatter<'a> {
@ -268,6 +268,16 @@ impl HirDisplay for ProjectionTy {
}
}
impl HirDisplay for OpaqueTy {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
if f.should_truncate() {
return write!(f, "{}", TYPE_HINT_TRUNCATION);
}
self.substitution[0].hir_fmt(f)
}
}
impl HirDisplay for Ty {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
if f.should_truncate() {
@ -700,12 +710,12 @@ fn write_bounds_like_dyn_trait(
}
}
}
GenericPredicate::Projection(projection_pred) if is_fn_trait => {
GenericPredicate::AliasEq(alias_eq) if is_fn_trait => {
is_fn_trait = false;
write!(f, " -> ")?;
projection_pred.ty.hir_fmt(f)?;
alias_eq.ty.hir_fmt(f)?;
}
GenericPredicate::Projection(projection_pred) => {
GenericPredicate::AliasEq(AliasEq { ty, alias }) => {
// in types in actual Rust, these will always come
// after the corresponding Implemented predicate
if angle_open {
@ -714,11 +724,12 @@ fn write_bounds_like_dyn_trait(
write!(f, "<")?;
angle_open = true;
}
let type_alias = f.db.type_alias_data(from_assoc_type_id(
projection_pred.projection_ty.associated_ty_id,
));
write!(f, "{} = ", type_alias.name)?;
projection_pred.ty.hir_fmt(f)?;
if let AliasTy::Projection(proj) = alias {
let type_alias =
f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id));
write!(f, "{} = ", type_alias.name)?;
}
ty.hir_fmt(f)?;
}
GenericPredicate::Error => {
if angle_open {
@ -775,20 +786,20 @@ impl HirDisplay for GenericPredicate {
match self {
GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
GenericPredicate::Projection(projection_pred) => {
GenericPredicate::AliasEq(AliasEq {
alias: AliasTy::Projection(projection_ty),
ty,
}) => {
write!(f, "<")?;
projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
write!(
f,
">::{} = ",
f.db.type_alias_data(from_assoc_type_id(
projection_pred.projection_ty.associated_ty_id
))
.name,
f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name,
)?;
projection_pred.ty.hir_fmt(f)?;
ty.hir_fmt(f)?;
}
GenericPredicate::Error => write!(f, "{{error}}")?,
GenericPredicate::AliasEq(_) | GenericPredicate::Error => write!(f, "{{error}}")?,
}
Ok(())
}
@ -815,11 +826,14 @@ impl HirDisplay for Obligation {
tr.hir_fmt(f)?;
write!(f, ")")
}
Obligation::Projection(proj) => {
Obligation::AliasEq(AliasEq { alias, ty }) => {
write!(f, "Normalize(")?;
proj.projection_ty.hir_fmt(f)?;
match alias {
AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?,
AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?,
}
write!(f, " => ")?;
proj.ty.hir_fmt(f)?;
ty.hir_fmt(f)?;
write!(f, ")")
}
}

View File

@ -37,12 +37,12 @@ use stdx::impl_from;
use syntax::SmolStr;
use super::{
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
traits::{Guidance, Obligation, Solution},
InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk,
};
use crate::{
db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
to_assoc_type_id, to_chalk_trait_id, AliasTy, Interner, TyKind,
to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind,
};
pub(crate) use unify::unify;
@ -396,15 +396,15 @@ impl<'a> InferenceContext<'a> {
.build();
let trait_ref =
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
let projection = ProjectionPredicate {
ty: ty.clone(),
projection_ty: ProjectionTy {
let alias_eq = AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(res_assoc_ty),
substitution: substs,
},
}),
ty: ty.clone(),
};
self.obligations.push(Obligation::Trait(trait_ref));
self.obligations.push(Obligation::Projection(projection));
self.obligations.push(Obligation::AliasEq(alias_eq));
self.resolve_ty_as_possible(ty)
}
None => self.err_ty(),
@ -429,8 +429,8 @@ impl<'a> InferenceContext<'a> {
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
let var = self.table.new_type_var();
let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() };
let obligation = Obligation::Projection(predicate);
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
let obligation = Obligation::AliasEq(alias_eq);
self.obligations.push(obligation);
var
}

View File

@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
use super::{InferenceContext, Obligation};
use crate::{
BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar,
Interner, Scalar, Substitution, Ty, TyKind, TypeWalk,
AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate,
InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk,
};
impl<'a> InferenceContext<'a> {
@ -93,8 +93,8 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
Obligation::Trait(tr) => {
Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST))
}
Obligation::Projection(pr) => {
Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST))
Obligation::AliasEq(alias_eq) => {
Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST))
}
};
self.into_canonicalized(InEnvironment {
@ -394,14 +394,25 @@ impl InferenceTable {
{
self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1)
}
(GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2))
if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id =>
{
self.unify_substs(
&proj1.projection_ty.substitution,
&proj2.projection_ty.substitution,
depth + 1,
) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1)
(
GenericPredicate::AliasEq(AliasEq { alias: alias1, ty: ty1 }),
GenericPredicate::AliasEq(AliasEq { alias: alias2, ty: ty2 }),
) => {
let (substitution1, substitution2) = match (alias1, alias2) {
(AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2))
if projection_ty1.associated_ty_id == projection_ty2.associated_ty_id =>
{
(&projection_ty1.substitution, &projection_ty2.substitution)
}
(AliasTy::Opaque(opaque1), AliasTy::Opaque(opaque2))
if opaque1.opaque_ty_id == opaque2.opaque_ty_id =>
{
(&opaque1.substitution, &opaque2.substitution)
}
_ => return false,
};
self.unify_substs(&substitution1, &substitution2, depth + 1)
&& self.unify_inner(&ty1, &ty2, depth + 1)
}
_ => false,
}

View File

@ -45,7 +45,7 @@ pub use lower::{
associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
TyDefId, TyLoweringContext, ValueTyDefId,
};
pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment};
pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind};
@ -72,6 +72,20 @@ pub struct OpaqueTy {
pub substitution: Substitution,
}
impl TypeWalk for OpaqueTy {
fn walk(&self, f: &mut impl FnMut(&Ty)) {
self.substitution.walk(f);
}
fn walk_mut_binders(
&mut self,
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
binders: DebruijnIndex,
) {
self.substitution.walk_mut_binders(f, binders);
}
}
/// A "projection" type corresponds to an (unnormalized)
/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
/// trait and all its parameters are fully known.
@ -133,6 +147,25 @@ pub enum AliasTy {
Opaque(OpaqueTy),
}
impl TypeWalk for AliasTy {
fn walk(&self, f: &mut impl FnMut(&Ty)) {
match self {
AliasTy::Projection(it) => it.walk(f),
AliasTy::Opaque(it) => it.walk(f),
}
}
fn walk_mut_binders(
&mut self,
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
binders: DebruijnIndex,
) {
match self {
AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
}
}
}
/// A type.
///
/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
@ -535,7 +568,7 @@ pub enum GenericPredicate {
/// The given trait needs to be implemented for its type parameters.
Implemented(TraitRef),
/// An associated type bindings like in `Iterator<Item = T>`.
Projection(ProjectionPredicate),
AliasEq(AliasEq),
/// We couldn't resolve the trait reference. (If some type parameters can't
/// be resolved, they will just be Unknown).
Error,
@ -553,8 +586,10 @@ impl GenericPredicate {
pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
match self {
GenericPredicate::Implemented(tr) => Some(tr.clone()),
GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)),
GenericPredicate::Error => None,
GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
Some(proj.trait_ref(db))
}
GenericPredicate::AliasEq(_) | GenericPredicate::Error => None,
}
}
}
@ -563,7 +598,7 @@ impl TypeWalk for GenericPredicate {
fn walk(&self, f: &mut impl FnMut(&Ty)) {
match self {
GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
GenericPredicate::Projection(projection_pred) => projection_pred.walk(f),
GenericPredicate::AliasEq(alias_eq) => alias_eq.walk(f),
GenericPredicate::Error => {}
}
}
@ -575,9 +610,7 @@ impl TypeWalk for GenericPredicate {
) {
match self {
GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
GenericPredicate::Projection(projection_pred) => {
projection_pred.walk_mut_binders(f, binders)
}
GenericPredicate::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
GenericPredicate::Error => {}
}
}

View File

@ -33,8 +33,8 @@ use crate::{
all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
variant_data,
},
AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate,
ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait,
AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig,
GenericPredicate, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait,
ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk,
};
@ -750,9 +750,9 @@ impl<'a> TyLoweringContext<'a> {
);
if let Some(type_ref) = &binding.type_ref {
let ty = self.lower_ty(type_ref);
let projection_predicate =
ProjectionPredicate { projection_ty: projection_ty.clone(), ty };
preds.push(GenericPredicate::Projection(projection_predicate));
let alias_eq =
AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
preds.push(GenericPredicate::AliasEq(alias_eq));
}
for bound in &binding.bounds {
preds.extend(self.lower_type_bound(

View File

@ -8,10 +8,9 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
use hir_def::{lang_item::LangItemTarget, TraitId};
use stdx::panic_context;
use crate::{db::HirDatabase, DebruijnIndex, Substitution};
use super::{
Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
use crate::{
db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution,
TraitRef, Ty, TyKind, TypeWalk,
};
use self::chalk::{from_chalk, Interner, ToChalk};
@ -93,31 +92,32 @@ pub enum Obligation {
/// Prove that a certain type implements a trait (the type is the `Self` type
/// parameter to the `TraitRef`).
Trait(TraitRef),
Projection(ProjectionPredicate),
AliasEq(AliasEq),
}
impl Obligation {
pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> {
match predicate {
GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
GenericPredicate::Projection(projection_pred) => {
Some(Obligation::Projection(projection_pred))
}
GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)),
GenericPredicate::Error => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ProjectionPredicate {
pub projection_ty: ProjectionTy,
pub struct AliasEq {
pub alias: AliasTy,
pub ty: Ty,
}
impl TypeWalk for ProjectionPredicate {
impl TypeWalk for AliasEq {
fn walk(&self, f: &mut impl FnMut(&Ty)) {
self.projection_ty.walk(f);
self.ty.walk(f);
match &self.alias {
AliasTy::Projection(projection_ty) => projection_ty.walk(f),
AliasTy::Opaque(opaque) => opaque.walk(f),
}
}
fn walk_mut_binders(
@ -125,8 +125,11 @@ impl TypeWalk for ProjectionPredicate {
f: &mut impl FnMut(&mut Ty, DebruijnIndex),
binders: DebruijnIndex,
) {
self.projection_ty.walk_mut_binders(f, binders);
self.ty.walk_mut_binders(f, binders);
match &mut self.alias {
AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
}
}
}
@ -138,12 +141,14 @@ pub(crate) fn trait_solve_query(
) -> Option<Solution> {
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(),
Obligation::Projection(_) => "projection".to_string(),
Obligation::AliasEq(_) => "alias_eq".to_string(),
});
log::info!("trait_solve_query({})", goal.value.value.display(db));
if let Obligation::Projection(pred) = &goal.value.value {
if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) {
if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) =
&goal.value.value
{
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
return Some(Solution::Ambig(Guidance::Unknown));
}

View File

@ -21,8 +21,8 @@ use crate::{
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
to_assoc_type_id, to_chalk_trait_id,
utils::generics,
BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate,
ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId,
GenericPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind,
};
use mapping::{
convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@ -229,18 +229,18 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
.intern(&Interner),
),
});
let proj_bound = GenericPredicate::Projection(ProjectionPredicate {
// The parameter of the opaque type.
ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
.intern(&Interner),
projection_ty: ProjectionTy {
let proj_bound = GenericPredicate::AliasEq(AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: to_assoc_type_id(future_output),
// Self type as the first parameter.
substitution: Substitution::single(
TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
.intern(&Interner),
),
},
}),
// The parameter of the opaque type.
ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 })
.intern(&Interner),
});
let bound = OpaqueTyDatumBound {
bounds: make_binders(

View File

@ -14,8 +14,8 @@ use crate::{
from_assoc_type_id,
primitive::UintTy,
traits::{Canonical, Obligation},
AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy,
ProjectionPredicate, ProjectionTy, Scalar, Substitution, TraitRef, Ty,
AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, ProjectionTy,
Scalar, Substitution, TraitRef, Ty,
};
use super::interner::*;
@ -314,12 +314,10 @@ impl ToChalk for GenericPredicate {
let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
}
GenericPredicate::Projection(projection_pred) => {
let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner);
let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner);
let alias = chalk_ir::AliasTy::Projection(projection);
make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0)
}
GenericPredicate::AliasEq(alias_eq) => make_binders(
chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)),
0,
),
GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"),
}
}
@ -338,16 +336,8 @@ impl ToChalk for GenericPredicate {
chalk_ir::WhereClause::Implemented(tr) => {
GenericPredicate::Implemented(from_chalk(db, tr))
}
chalk_ir::WhereClause::AliasEq(projection_eq) => {
let projection_ty = from_chalk(
db,
match projection_eq.alias {
chalk_ir::AliasTy::Projection(p) => p,
_ => unimplemented!(),
},
);
let ty = from_chalk(db, projection_eq.ty);
GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty })
chalk_ir::WhereClause::AliasEq(alias_eq) => {
GenericPredicate::AliasEq(from_chalk(db, alias_eq))
}
chalk_ir::WhereClause::LifetimeOutlives(_) => {
@ -383,19 +373,55 @@ impl ToChalk for ProjectionTy {
}
}
}
impl ToChalk for OpaqueTy {
type Chalk = chalk_ir::OpaqueTy<Interner>;
impl ToChalk for ProjectionPredicate {
type Chalk = chalk_ir::AliasEq<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
chalk_ir::AliasEq {
alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)),
ty: self.ty.to_chalk(db),
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
chalk_ir::OpaqueTy {
opaque_ty_id: self.opaque_ty_id,
substitution: self.substitution.to_chalk(db),
}
}
fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self {
unimplemented!()
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
OpaqueTy {
opaque_ty_id: chalk.opaque_ty_id,
substitution: from_chalk(db, chalk.substitution),
}
}
}
impl ToChalk for AliasTy {
type Chalk = chalk_ir::AliasTy<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
match self {
AliasTy::Projection(projection_ty) => {
chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
}
AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
}
}
fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
match chalk {
chalk_ir::AliasTy::Projection(projection_ty) => {
AliasTy::Projection(from_chalk(db, projection_ty))
}
chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
}
}
}
impl ToChalk for AliasEq {
type Chalk = chalk_ir::AliasEq<Interner>;
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
}
fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
}
}
@ -405,7 +431,7 @@ impl ToChalk for Obligation {
fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
match self {
Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner),
Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner),
Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner),
}
}
@ -527,29 +553,29 @@ pub(super) fn generic_predicate_to_inline_bound(
let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
Some(rust_ir::InlineBound::TraitBound(trait_bound))
}
GenericPredicate::Projection(proj) => {
if &proj.projection_ty.substitution[0] != self_ty {
GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
if &projection_ty.substitution[0] != self_ty {
return None;
}
let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id)
let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id)
.lookup(db.upcast())
.container
{
AssocContainerId::TraitId(t) => t,
_ => panic!("associated type not in trait"),
};
let args_no_self = proj.projection_ty.substitution[1..]
let args_no_self = projection_ty.substitution[1..]
.iter()
.map(|ty| ty.clone().to_chalk(db).cast(&Interner))
.collect();
let alias_eq_bound = rust_ir::AliasEqBound {
value: proj.ty.clone().to_chalk(db),
value: ty.clone().to_chalk(db),
trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
associated_ty_id: proj.projection_ty.associated_ty_id,
associated_ty_id: projection_ty.associated_ty_id,
parameters: Vec::new(), // FIXME we don't support generic associated types yet
};
Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound))
}
GenericPredicate::Error => None,
_ => None,
}
}