Skip to content

Add NormalizeFn domain goal that associates projections of functions on traits with the matching implementation #726

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
489 changes: 182 additions & 307 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions chalk-engine/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
//! Defines traits used to embed the chalk-engine in another crate.
//!
//! chalk and rustc both define types which implement the traits in this
//! module. This allows each user of chalk-engine to define their own
//! `DomainGoal` type, add arena lifetime parameters, and more. See
//! [`Context`] trait for a list of types.

use crate::CompleteAnswer;
use chalk_ir::interner::Interner;
use chalk_ir::Substitution;
Expand Down
13 changes: 10 additions & 3 deletions chalk-engine/src/slg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,16 @@ impl<I: Interner> MayInvalidate<'_, I> {
TyKind::OpaqueType(id_b, substitution_b),
) => self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b),
(TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => self.aggregate_tys(ty_a, ty_b),
(TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
}
(
TyKind::FnDef(FnDefTy {
fn_def_id: id_a,
substitution: substitution_a,
}),
TyKind::FnDef(FnDefTy {
fn_def_id: id_b,
substitution: substitution_b,
}),
) => self.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b),
(TyKind::Ref(id_a, lifetime_a, ty_a), TyKind::Ref(id_b, lifetime_b, ty_b)) => {
id_a != id_b
|| self.aggregate_lifetimes(lifetime_a, lifetime_b)
Expand Down
19 changes: 17 additions & 2 deletions chalk-engine/src/slg/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,9 +305,24 @@ impl<I: Interner> AntiUnifier<'_, '_, I> {
(TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => {
TyKind::Slice(self.aggregate_tys(ty_a, ty_b)).intern(interner)
}
(TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => self
(
TyKind::FnDef(FnDefTy {
fn_def_id: id_a,
substitution: substitution_a,
}),
TyKind::FnDef(FnDefTy {
fn_def_id: id_b,
substitution: substitution_b,
}),
) => self
.aggregate_name_and_substs(id_a, substitution_a, id_b, substitution_b)
.map(|(&name, substitution)| TyKind::FnDef(name, substitution).intern(interner))
.map(|(&name, substitution)| {
TyKind::FnDef(FnDefTy {
fn_def_id: name,
substitution,
})
.intern(interner)
})
.unwrap_or_else(|| self.new_ty_variable()),
(TyKind::Ref(id_a, lifetime_a, ty_a), TyKind::Ref(id_b, lifetime_b, ty_b)) => {
if id_a == id_b {
Expand Down
11 changes: 10 additions & 1 deletion chalk-engine/src/slg/resolvent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,16 @@ impl<'i, I: Interner> Zipper<'i, I> for AnswerSubstitutor<'i, I> {
)
}
(TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => Zip::zip_with(self, variance, ty_a, ty_b),
(TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
(
TyKind::FnDef(FnDefTy {
fn_def_id: id_a,
substitution: substitution_a,
}),
TyKind::FnDef(FnDefTy {
fn_def_id: id_b,
substitution: substitution_b,
}),
) => {
if id_a != id_b {
return Err(NoSolution);
}
Expand Down
20 changes: 17 additions & 3 deletions chalk-integration/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use chalk_ir::{
UnificationDatabase, Variances,
};
use chalk_solve::rust_ir::{
AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind,
FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum,
OpaqueTyDatum, TraitDatum, WellKnownTrait,
AdtDatum, AdtRepr, AssociatedFnValue, AssociatedFnValueId, AssociatedTyDatum,
AssociatedTyValue, AssociatedTyValueId, ClosureKind, FnDefDatum, FnDefInputsAndOutputDatum,
GeneratorDatum, GeneratorWitnessDatum, ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait,
};
use chalk_solve::{RustIrDatabase, Solution, SubstitutionResult};
use salsa::Database;
Expand Down Expand Up @@ -91,6 +91,13 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
self.program_ir().unwrap().associated_ty_data(ty)
}

fn associated_fn_data(
&self,
f: chalk_ir::AssocFnDefId<ChalkIr>,
) -> Arc<chalk_solve::rust_ir::AssociatedFnDatum<ChalkIr>> {
self.program_ir().unwrap().associated_fn_data(f)
}

fn trait_datum(&self, id: TraitId<ChalkIr>) -> Arc<TraitDatum<ChalkIr>> {
self.program_ir().unwrap().trait_datum(id)
}
Expand All @@ -106,6 +113,13 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
self.program_ir().unwrap().associated_ty_values[&id].clone()
}

fn associated_fn_value(
&self,
id: AssociatedFnValueId<ChalkIr>,
) -> Arc<AssociatedFnValue<ChalkIr>> {
self.program_ir().unwrap().associated_fn_values[&id].clone()
}

fn opaque_ty_data(&self, id: OpaqueTyId<ChalkIr>) -> Arc<OpaqueTyDatum<ChalkIr>> {
self.program_ir().unwrap().opaque_ty_data(id)
}
Expand Down
59 changes: 59 additions & 0 deletions chalk-integration/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,21 @@ impl std::error::Error for ChalkError {}
pub enum RustIrError {
InvalidParameterName(Identifier),
InvalidTraitName(Identifier),
InvalidImplName(Identifier),
InvalidImplMemberName(Identifier, Identifier),
NotTrait(Identifier),
NotStruct(Identifier),
NotAssociatedType(Identifier),
NotAssociatedFn(Identifier),
AmbiguousProjection(Identifier),
DuplicateOrShadowedParameters,
AutoTraitAssociatedTypes(Identifier),
AutoTraitParameters(Identifier),
AutoTraitWhereClauses(Identifier),
InvalidFundamentalTypesParameters(Identifier),
NegativeImplAssociatedValues(Identifier),
MissingAssociatedType(Identifier),
MissingAssociatedFn(Identifier),
IncorrectNumberOfVarianceParameters {
identifier: Identifier,
expected: usize,
Expand All @@ -81,6 +87,11 @@ pub enum RustIrError {
expected: usize,
actual: usize,
},
IncorrectNumberOfAssociatedFnParameters {
identifier: Identifier,
expected: usize,
actual: usize,
},
IncorrectParameterKind {
identifier: Identifier,
expected: Kind,
Expand All @@ -96,6 +107,11 @@ pub enum RustIrError {
expected: Kind,
actual: Kind,
},
IncorrectAssociatedFnParameterKind {
identifier: Identifier,
expected: Kind,
actual: Kind,
},
CannotApplyTypeParameter(Identifier),
InvalidExternAbi(Atom),
}
Expand All @@ -107,6 +123,12 @@ impl std::fmt::Display for RustIrError {
write!(f, "invalid parameter name `{}`", name)
}
RustIrError::InvalidTraitName(name) => write!(f, "invalid trait name `{}`", name),
RustIrError::InvalidImplName(name) => write!(f, "invalid impl name `{}`", name),
RustIrError::InvalidImplMemberName(impl_name, member_name) => write!(
f,
"invalid impl member name `{}::{}`",
impl_name, member_name
),
RustIrError::NotTrait(name) => write!(
f,
"expected a trait, found `{}`, which is not a trait",
Expand All @@ -117,6 +139,22 @@ impl std::fmt::Display for RustIrError {
"expected a struct, found `{}`, which is not a struct",
name
),
RustIrError::NotAssociatedType(name) => write!(
f,
"expected an associated type, found `{}`, which is not",
name
),
RustIrError::NotAssociatedFn(name) => write!(
f,
"expected an associated fn, found `{}`, which is not",
name
),
RustIrError::AmbiguousProjection(name) => write!(
f,
"projection refers to `{}` which is both a fn and a type",
name
),

RustIrError::DuplicateOrShadowedParameters => {
write!(f, "duplicate or shadowed parameters")
}
Expand All @@ -142,6 +180,9 @@ impl std::fmt::Display for RustIrError {
RustIrError::MissingAssociatedType(name) => {
write!(f, "no associated type `{}` defined in trait", name)
}
RustIrError::MissingAssociatedFn(name) => {
write!(f, "no associated fn `{}` defined in trait", name)
}
RustIrError::IncorrectNumberOfVarianceParameters {
identifier,
expected,
Expand Down Expand Up @@ -169,6 +210,15 @@ impl std::fmt::Display for RustIrError {
"wrong number of parameters for associated type `{}` (expected {}, got {})",
identifier, expected, actual
),
RustIrError::IncorrectNumberOfAssociatedFnParameters {
identifier,
expected,
actual,
} => write!(
f,
"wrong number of parameters for associated fn `{}` (expected {}, got {})",
identifier, expected, actual
),
RustIrError::IncorrectParameterKind {
identifier,
expected,
Expand Down Expand Up @@ -196,6 +246,15 @@ impl std::fmt::Display for RustIrError {
"incorrect associated type parameter kind for `{}`: expected {}, found {}",
identifier, expected, actual
),
RustIrError::IncorrectAssociatedFnParameterKind {
identifier,
expected,
actual,
} => write!(
f,
"incorrect associated fn parameter kind for `{}`: expected {}, found {}",
identifier, expected, actual
),
RustIrError::CannotApplyTypeParameter(name) => {
write!(f, "cannot apply type parameter `{}`", name)
}
Expand Down
Loading