mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-24 12:54:00 +00:00
Replace Projection variant in GenericPredicate with AliasEq
This commit is contained in:
parent
86878443b1
commit
8996b1a235
@ -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]),
|
||||
};
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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, ")")
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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 => {}
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user