Skip to content
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

Implement associated constants #689

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions chalk-engine/src/slg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ impl<I: Interner> MayInvalidate<'_, I> {

// Only variants left are placeholder = concrete, which always fails
(ConstValue::Placeholder(_), _) | (ConstValue::Concrete(_), _) => true,

(ConstValue::ConstProjection(_), _) => todo!(),
}
}

Expand Down
2 changes: 2 additions & 0 deletions chalk-engine/src/slg/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,8 @@ impl<I: Interner> AntiUnifier<'_, '_, I> {
(ConstValue::Placeholder(_), _) | (_, ConstValue::Placeholder(_)) => {
self.new_const_variable(ty)
}

(ConstValue::ConstProjection(_), _) | (_, ConstValue::ConstProjection(_)) => todo!(),
}
}

Expand Down
2 changes: 2 additions & 0 deletions chalk-engine/src/slg/resolvent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,8 @@ impl<'i, I: Interner> Zipper<'i, I> for AnswerSubstitutor<'i, I> {
"structural mismatch between answer `{:?}` and pending goal `{:?}`",
answer, pending,
),

(ConstValue::ConstProjection(_), _) => todo!(),
}
}

Expand Down
31 changes: 25 additions & 6 deletions chalk-integration/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ use crate::{
tls, SolverChoice,
};
use chalk_ir::{
AdtId, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId, ConstrainedSubst,
Environment, FnDefId, GeneratorId, GenericArg, Goal, ImplId, InEnvironment, OpaqueTyId,
ProgramClause, ProgramClauses, Substitution, TraitId, Ty, TyKind, UCanonical,
AdtId, AssocConstId, AssocTypeId, Binders, Canonical, CanonicalVarKinds, ClosureId,
ConstrainedSubst, Environment, FnDefId, GeneratorId, GenericArg, Goal, ImplId, InEnvironment,
OpaqueTyId, ProgramClause, ProgramClauses, Substitution, TraitId, Ty, TyKind, UCanonical,
UnificationDatabase, Variances,
};
use chalk_solve::rust_ir::{
AdtDatum, AdtRepr, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind,
FnDefDatum, FnDefInputsAndOutputDatum, GeneratorDatum, GeneratorWitnessDatum, ImplDatum,
OpaqueTyDatum, TraitDatum, WellKnownTrait,
AdtDatum, AdtRepr, AssociatedConstDatum, AssociatedConstValue, AssociatedConstValueId,
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 +92,13 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
self.program_ir().unwrap().associated_ty_data(ty)
}

fn associated_const_data(
&self,
ty: AssocConstId<ChalkIr>,
) -> Arc<AssociatedConstDatum<ChalkIr>> {
self.program_ir().unwrap().associated_const_data(ty)
}

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

fn associated_const_value(
&self,
id: AssociatedConstValueId<ChalkIr>,
) -> Arc<AssociatedConstValue<ChalkIr>> {
self.program_ir().unwrap().associated_const_values[&id].clone()
}

fn opaque_ty_data(&self, id: OpaqueTyId<ChalkIr>) -> Arc<OpaqueTyDatum<ChalkIr>> {
self.program_ir().unwrap().opaque_ty_data(id)
}
Expand Down Expand Up @@ -235,6 +250,10 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
self.program_ir().unwrap().assoc_type_name(assoc_ty_id)
}

fn assoc_const_name(&self, assoc_const_id: AssocConstId<ChalkIr>) -> String {
self.program_ir().unwrap().assoc_const_name(assoc_const_id)
}

fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<ChalkIr>) -> String {
self.program_ir().unwrap().opaque_type_name(opaque_ty_id)
}
Expand Down
4 changes: 4 additions & 0 deletions chalk-integration/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub enum RustIrError {
InvalidFundamentalTypesParameters(Identifier),
NegativeImplAssociatedValues(Identifier),
MissingAssociatedType(Identifier),
MissingAssociatedConst(Identifier),
IncorrectNumberOfVarianceParameters {
identifier: Identifier,
expected: usize,
Expand Down Expand Up @@ -142,6 +143,9 @@ impl std::fmt::Display for RustIrError {
RustIrError::MissingAssociatedType(name) => {
write!(f, "no associated type `{}` defined in trait", name)
}
RustIrError::MissingAssociatedConst(name) => {
write!(f, "no associated constant `{}` defined in trait", name)
}
RustIrError::IncorrectNumberOfVarianceParameters {
identifier,
expected,
Expand Down
11 changes: 9 additions & 2 deletions chalk-integration/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use chalk_ir::{
TyKind,
};
use chalk_ir::{
AdtId, AliasTy, AssocTypeId, CanonicalVarKind, CanonicalVarKinds, ConstData, Constraint,
Constraints, FnDefId, Goals, InEnvironment, Lifetime, OpaqueTy, OpaqueTyId,
AdtId, AliasTy, AssocConstId, AssocTypeId, CanonicalVarKind, CanonicalVarKinds, ConstData,
Constraint, Constraints, FnDefId, Goals, InEnvironment, Lifetime, OpaqueTy, OpaqueTyId,
ProgramClauseImplication, ProgramClauses, ProjectionTy, QuantifiedWhereClauses,
SeparatorTraitRef, Substitution, TraitId, Ty, TyData, VariableKind, VariableKinds, Variances,
};
Expand Down Expand Up @@ -97,6 +97,13 @@ impl Interner for ChalkIr {
tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
}

fn debug_assoc_const_id(
id: AssocConstId<ChalkIr>,
fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> {
tls::with_current_program(|prog| Some(prog?.debug_assoc_const_id(id, fmt)))
}

fn debug_opaque_ty_id(
id: OpaqueTyId<ChalkIr>,
fmt: &mut fmt::Formatter<'_>,
Expand Down
57 changes: 52 additions & 5 deletions chalk-integration/src/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,18 +884,30 @@ impl LowerWithEnv for Lifetime {
}
}

impl LowerWithEnv for (&Impl, ImplId<ChalkIr>, &AssociatedTyValueIds) {
impl LowerWithEnv
for (
&Impl,
ImplId<ChalkIr>,
&AssociatedTyValueIds,
&AssociatedConstValueIds,
)
{
type Lowered = rust_ir::ImplDatum<ChalkIr>;

fn lower(&self, env: &Env) -> LowerResult<Self::Lowered> {
let (impl_, impl_id, associated_ty_value_ids) = self;
let (impl_, impl_id, associated_ty_value_ids, associated_const_value_ids) = self;

let polarity = impl_.polarity.lower();
let binders = env.in_binders(impl_.all_parameters(), |env| {
let trait_ref = impl_.trait_ref.lower(env)?;
debug!(?trait_ref);

if !polarity.is_positive() && !impl_.assoc_ty_values.is_empty() {
if !polarity.is_positive()
&& impl_
.assoc_item_values
.iter()
.any(|item| item.ty().is_some())
{
Err(RustIrError::NegativeImplAssociatedValues(
impl_.trait_ref.trait_name.clone(),
))?;
Expand All @@ -913,18 +925,29 @@ impl LowerWithEnv for (&Impl, ImplId<ChalkIr>, &AssociatedTyValueIds) {
// within the impl, which should have already assigned and
// stored in the map
let associated_ty_value_ids = impl_
.assoc_ty_values
.assoc_item_values
.iter()
.filter_map(|item| item.ty())
.map(|atv| associated_ty_value_ids[&(*impl_id, atv.name.str.clone())])
.collect();

debug!(?associated_ty_value_ids);

let associated_const_value_ids = impl_
.assoc_item_values
.iter()
.filter_map(|item| item.const_())
.map(|acv| associated_const_value_ids[&(*impl_id, acv.name.str.clone())])
.collect();

debug!(?associated_const_value_ids);

Ok(rust_ir::ImplDatum {
polarity,
binders,
impl_type: impl_.impl_type.lower(),
associated_ty_value_ids,
associated_const_value_ids,
})
}
}
Expand Down Expand Up @@ -993,16 +1016,29 @@ impl LowerWithEnv for (&TraitDefn, chalk_ir::TraitId<ChalkIr>) {
})?;

let associated_ty_ids: Vec<_> = trait_defn
.assoc_ty_defns
.assoc_item_defns
.iter()
.filter_map(|item| item.ty())
.map(|defn| env.lookup_associated_ty(*trait_id, &defn.name).unwrap().id)
.collect();

let associated_const_ids: Vec<_> = trait_defn
.assoc_item_defns
.iter()
.filter_map(|item| item.const_())
.map(|defn| {
env.lookup_associated_const(*trait_id, &defn.name)
.unwrap()
.id
})
.collect();

let trait_datum = rust_ir::TraitDatum {
id: *trait_id,
binders,
flags: trait_defn.flags.lower(),
associated_ty_ids,
associated_const_ids,
well_known: trait_defn.well_known.map(|def| def.lower()),
};

Expand Down Expand Up @@ -1030,6 +1066,16 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult<chalk_ir
((datum.trait_id, datum.name.clone()), lookup)
})
.collect();
let associated_const_lookups: BTreeMap<_, _> = program
.associated_const_data
.iter()
.map(|(&associated_const_id, datum)| {
let lookup = AssociatedConstLookup {
id: associated_const_id,
};
((datum.trait_id, datum.name.clone()), lookup)
})
.collect();

let auto_traits = program
.trait_data
Expand All @@ -1051,6 +1097,7 @@ pub fn lower_goal(goal: &Goal, program: &LoweredProgram) -> LowerResult<chalk_ir
trait_kinds: &program.trait_kinds,
opaque_ty_kinds: &program.opaque_ty_kinds,
associated_ty_lookups: &associated_ty_lookups,
associated_const_lookups: &associated_const_lookups,
foreign_ty_ids: &program.foreign_ty_ids,
parameter_map: BTreeMap::new(),
auto_traits: &auto_traits,
Expand Down
22 changes: 21 additions & 1 deletion chalk-integration/src/lowering/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use chalk_ir::{
};
use chalk_ir::{cast::Cast, ForeignDefId, WithKind};
use chalk_parse::ast::*;
use chalk_solve::rust_ir::AssociatedTyValueId;
use chalk_solve::rust_ir::{AssociatedConstValueId, AssociatedTyValueId};
use std::collections::BTreeMap;

use crate::error::RustIrError;
Expand All @@ -26,8 +26,12 @@ pub type AutoTraits = BTreeMap<chalk_ir::TraitId<ChalkIr>, bool>;
pub type OpaqueTyVariableKinds = BTreeMap<chalk_ir::OpaqueTyId<ChalkIr>, TypeKind>;
pub type GeneratorKinds = BTreeMap<chalk_ir::GeneratorId<ChalkIr>, TypeKind>;
pub type AssociatedTyLookups = BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedTyLookup>;
pub type AssociatedConstLookups =
BTreeMap<(chalk_ir::TraitId<ChalkIr>, Ident), AssociatedConstLookup>;
pub type AssociatedTyValueIds =
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedTyValueId<ChalkIr>>;
pub type AssociatedConstValueIds =
BTreeMap<(chalk_ir::ImplId<ChalkIr>, Ident), AssociatedConstValueId<ChalkIr>>;
pub type ForeignIds = BTreeMap<Ident, chalk_ir::ForeignDefId<ChalkIr>>;

pub type ParameterMap = BTreeMap<Ident, chalk_ir::WithKind<ChalkIr, BoundVar>>;
Expand All @@ -47,6 +51,7 @@ pub struct Env<'k> {
pub opaque_ty_ids: &'k OpaqueTyIds,
pub opaque_ty_kinds: &'k OpaqueTyVariableKinds,
pub associated_ty_lookups: &'k AssociatedTyLookups,
pub associated_const_lookups: &'k AssociatedConstLookups,
pub auto_traits: &'k AutoTraits,
pub foreign_ty_ids: &'k ForeignIds,
pub generator_ids: &'k GeneratorIds,
Expand Down Expand Up @@ -75,6 +80,11 @@ pub struct AssociatedTyLookup {
pub addl_variable_kinds: Vec<chalk_ir::VariableKind<ChalkIr>>,
}

#[derive(Debug, PartialEq, Eq)]
pub struct AssociatedConstLookup {
pub id: chalk_ir::AssocConstId<ChalkIr>,
}

pub enum TypeLookup<'k> {
Parameter(&'k WithKind<ChalkIr, BoundVar>),
Adt(AdtId<ChalkIr>),
Expand Down Expand Up @@ -222,6 +232,16 @@ impl Env<'_> {
.ok_or(RustIrError::MissingAssociatedType(ident.clone()))
}

pub fn lookup_associated_const(
&self,
trait_id: TraitId<ChalkIr>,
ident: &Identifier,
) -> LowerResult<&AssociatedConstLookup> {
self.associated_const_lookups
.get(&(trait_id, ident.str.clone()))
.ok_or(RustIrError::MissingAssociatedConst(ident.clone()))
}

/// Introduces new parameters, shifting the indices of existing
/// parameters to accommodate them. The indices of the new binders
/// will be assigned in order as they are iterated.
Expand Down
Loading