Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions chalk-integration/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ impl LowerProjectionTy for ProjectionTy {
} = *self;
let chalk_ir::TraitRef {
trait_id,
parameters: trait_parameters,
substitution: trait_substitution,
} = trait_ref.lower(env)?;
let lookup = match env.associated_ty_lookups.get(&(trait_id.into(), name.str)) {
Some(lookup) => lookup,
Expand Down Expand Up @@ -933,11 +933,11 @@ impl LowerProjectionTy for ProjectionTy {
}
}

args.extend(trait_parameters);
args.extend(trait_substitution.iter().cloned());

Ok(chalk_ir::ProjectionTy {
associated_ty_id: lookup.id,
parameters: args,
substitution: chalk_ir::Substitution::from(args),
})
}
}
Expand All @@ -961,7 +961,7 @@ impl LowerTy for Ty {
} else {
Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
name: chalk_ir::TypeName::Struct(id),
parameters: vec![],
substitution: chalk_ir::Substitution::empty(),
})
.intern())
}
Expand Down Expand Up @@ -1001,10 +1001,8 @@ impl LowerTy for Ty {
})?;
}

let parameters = args
.iter()
.map(|t| Ok(t.lower(env)?))
.collect::<LowerResult<Vec<_>>>()?;
let substitution =
chalk_ir::Substitution::from_fallible(args.iter().map(|t| Ok(t.lower(env)?)))?;

for (param, arg) in k.binders.binders.iter().zip(args.iter()) {
if param.kind() != arg.kind() {
Expand All @@ -1018,7 +1016,7 @@ impl LowerTy for Ty {

Ok(chalk_ir::TyData::Apply(chalk_ir::ApplicationTy {
name: chalk_ir::TypeName::Struct(id),
parameters: parameters,
substitution: substitution,
})
.intern())
}
Expand Down
9 changes: 6 additions & 3 deletions chalk-integration/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,11 @@ impl RustIrDatabase<ChalkIr> for Program {
.filter(|(_, impl_datum)| {
let trait_ref = &impl_datum.binders.value.trait_ref;
trait_id == trait_ref.trait_id && {
assert_eq!(trait_ref.parameters.len(), parameters.len());
<[_] as CouldMatch<[_]>>::could_match(&parameters, &trait_ref.parameters)
assert_eq!(trait_ref.substitution.len(), parameters.len());
<[_] as CouldMatch<[_]>>::could_match(
&parameters,
&trait_ref.substitution.parameters(),
)
}
})
.map(|(&impl_id, _)| impl_id)
Expand All @@ -191,7 +194,7 @@ impl RustIrDatabase<ChalkIr> for Program {
self.impl_data.values().any(|impl_datum| {
let impl_trait_ref = &impl_datum.binders.value.trait_ref;
impl_trait_ref.trait_id == auto_trait_id
&& match impl_trait_ref.parameters[0].assert_ty_ref().data() {
&& match impl_trait_ref.self_type_parameter().data() {
TyData::Apply(apply) => match apply.name {
TypeName::Struct(id) => id == struct_id,
_ => false,
Expand Down
6 changes: 6 additions & 0 deletions chalk-ir/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ impl<TF: TypeFamily> CastTo<Parameter<TF>> for Lifetime<TF> {
}
}

impl<TF: TypeFamily> CastTo<Parameter<TF>> for Parameter<TF> {
fn cast_to(self) -> Parameter<TF> {
self
}
}

impl<T, TF> CastTo<ProgramClause<TF>> for T
where
T: CastTo<DomainGoal<TF>>,
Expand Down
6 changes: 3 additions & 3 deletions chalk-ir/src/could_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ where
let names_could_match = a.name == b.name;

names_could_match
&& a.parameters
&& a.substitution
.iter()
.zip(&b.parameters)
.all(|(p_a, p_b)| p_a.could_match(p_b))
.zip(&b.substitution)
.all(|(p_a, p_b)| p_a.could_match(&p_b))
}

_ => true,
Expand Down
34 changes: 20 additions & 14 deletions chalk-ir/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ impl Debug for PlaceholderIndex {

impl<TF: TypeFamily> Debug for ApplicationTy<TF> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "{:?}{:?}", self.name, Angle(&self.parameters))
let ApplicationTy { name, substitution } = self;
write!(fmt, "{:?}{:?}", name, substitution.with_angle())
}
}

Expand Down Expand Up @@ -150,13 +151,14 @@ struct SeparatorTraitRef<'me, TF: TypeFamily> {

impl<TF: TypeFamily> Debug for SeparatorTraitRef<'_, TF> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
let parameters = self.trait_ref.substitution.parameters();
write!(
fmt,
"{:?}{}{:?}{:?}",
self.trait_ref.parameters[0],
parameters[0],
self.separator,
self.trait_ref.trait_id,
Angle(&self.trait_ref.parameters[1..])
Angle(&parameters[1..])
)
}
}
Expand All @@ -168,7 +170,7 @@ impl<TF: TypeFamily> Debug for ProjectionTy<TF> {
fmt,
"({:?}){:?}",
self.associated_ty_id,
Angle(&self.parameters)
self.substitution.with_angle()
)
})
}
Expand Down Expand Up @@ -242,13 +244,9 @@ impl<TF: TypeFamily> Debug for DomainGoal<TF> {
DomainGoal::IsLocal(n) => write!(fmt, "IsLocal({:?})", n),
DomainGoal::IsUpstream(n) => write!(fmt, "IsUpstream({:?})", n),
DomainGoal::IsFullyVisible(n) => write!(fmt, "IsFullyVisible({:?})", n),
DomainGoal::LocalImplAllowed(tr) => write!(
fmt,
"LocalImplAllowed({:?}: {:?}{:?})",
tr.parameters[0],
tr.trait_id,
Angle(&tr.parameters[1..])
),
DomainGoal::LocalImplAllowed(tr) => {
write!(fmt, "LocalImplAllowed({:?})", tr.with_colon(),)
}
DomainGoal::Compatible(_) => write!(fmt, "Compatible"),
DomainGoal::DownstreamType(n) => write!(fmt, "DownstreamType({:?})", n),
}
Expand Down Expand Up @@ -413,9 +411,17 @@ impl<TF: TypeFamily> Display for ConstrainedSubst<TF> {
}
}

impl<TF: TypeFamily> Substitution<TF> {
/// Displays the substitution in the form `< P0, .. Pn >`, or (if
/// the substitution is empty) as an empty string.
pub fn with_angle(&self) -> Angle<'_, Parameter<TF>> {
Angle(self.parameters())
}
}

impl<TF: TypeFamily> Debug for Substitution<TF> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
Display::fmt(self, f)
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
Display::fmt(self, fmt)
}
}

Expand All @@ -425,7 +431,7 @@ impl<TF: TypeFamily> Display for Substitution<TF> {

write!(f, "[")?;

for (index, value) in self.parameters.iter().enumerate() {
for (index, value) in self.iter().enumerate() {
if first {
first = false;
} else {
Expand Down
33 changes: 32 additions & 1 deletion chalk-ir/src/family.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::tls;
use crate::AssocTypeId;
use crate::GoalData;
use crate::LifetimeData;
use crate::Parameter;
use crate::ParameterData;
use crate::ProjectionTy;
use crate::RawId;
Expand Down Expand Up @@ -68,6 +69,14 @@ pub trait TypeFamily: Debug + Copy + Eq + Ord + Hash {
/// converted back to its underlying data via `goal_data`.
type InternedGoal: Debug + Clone + Eq + Ord + Hash;

/// "Interned" representation of a "substitution". In normal user code,
/// `Self::InternedSubstitution` is not referenced. Instead, we refer to
/// `Substitution<Self>`, which wraps this type.
///
/// An `InternedSubstitution` is created by `intern_substitution` and can be
/// converted back to its underlying data via `substitution_data`.
type InternedSubstitution: Debug + Clone + Eq + Ord + Hash;

/// The core "id" type used for struct-ids and the like.
type DefId: Debug + Copy + Eq + Ord + Hash;

Expand Down Expand Up @@ -147,7 +156,18 @@ pub trait TypeFamily: Debug + Copy + Eq + Ord + Hash {
fn intern_goal(data: GoalData<Self>) -> Self::InternedGoal;

/// Lookup the `GoalData` that was interned to create a `InternedGoal`.
fn goal_data(lifetime: &Self::InternedGoal) -> &GoalData<Self>;
fn goal_data(goal: &Self::InternedGoal) -> &GoalData<Self>;

/// Create an "interned" substitution from `data`. This is not
/// normally invoked directly; instead, you invoke
/// `SubstitutionData::intern` (which will ultimately call this
/// method).
fn intern_substitution<E>(
data: impl IntoIterator<Item = Result<Parameter<Self>, E>>,
) -> Result<Self::InternedSubstitution, E>;

/// Lookup the `SubstitutionData` that was interned to create a `InternedSubstitution`.
fn substitution_data(substitution: &Self::InternedSubstitution) -> &[Parameter<Self>];
}

pub trait TargetTypeFamily<TF: TypeFamily>: TypeFamily {
Expand Down Expand Up @@ -181,6 +201,7 @@ impl TypeFamily for ChalkIr {
type InternedLifetime = LifetimeData<ChalkIr>;
type InternedParameter = ParameterData<ChalkIr>;
type InternedGoal = Arc<GoalData<ChalkIr>>;
type InternedSubstitution = Vec<Parameter<ChalkIr>>;
type DefId = RawId;

fn debug_struct_id(
Expand Down Expand Up @@ -242,6 +263,16 @@ impl TypeFamily for ChalkIr {
fn goal_data(goal: &Arc<GoalData<ChalkIr>>) -> &GoalData<ChalkIr> {
goal
}

fn intern_substitution<E>(
data: impl IntoIterator<Item = Result<Parameter<ChalkIr>, E>>,
) -> Result<Vec<Parameter<ChalkIr>>, E> {
data.into_iter().collect()
}

fn substitution_data(substitution: &Vec<Parameter<ChalkIr>>) -> &[Parameter<ChalkIr>] {
substitution
}
}

impl HasTypeFamily for ChalkIr {
Expand Down
14 changes: 14 additions & 0 deletions chalk-ir/src/fold/boring_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ impl<T: Fold<TF, TTF>, TF: TypeFamily, TTF: TargetTypeFamily<TF>> Fold<TF, TTF>
}
}
}

impl<TF: TypeFamily, TTF: TargetTypeFamily<TF>> Fold<TF, TTF> for Parameter<TF> {
type Result = Parameter<TTF>;
fn fold_with(
Expand All @@ -110,6 +111,19 @@ impl<TF: TypeFamily, TTF: TargetTypeFamily<TF>> Fold<TF, TTF> for Goal<TF> {
}
}

impl<TF: TypeFamily, TTF: TargetTypeFamily<TF>> Fold<TF, TTF> for Substitution<TF> {
type Result = Substitution<TTF>;
fn fold_with(
&self,
folder: &mut dyn Folder<TF, TTF>,
binders: usize,
) -> Fallible<Self::Result> {
Ok(Substitution::from_fallible(
self.iter().map(|p| p.fold_with(folder, binders)),
)?)
}
}

#[macro_export]
macro_rules! copy_fold {
($t:ty) => {
Expand Down
Loading