Skip to content

Commit 0dc925e

Browse files
committed
Intern Vec<ProgramClause<I>>
1 parent b828b09 commit 0dc925e

File tree

15 files changed

+214
-37
lines changed

15 files changed

+214
-37
lines changed

chalk-engine/src/context.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,6 @@ pub trait Context: Clone + Debug {
154154

155155
fn goal_from_goal_in_environment(goal: &Self::GoalInEnvironment) -> &Self::Goal;
156156

157-
// Used by: simplify
158-
fn add_clauses(env: &Self::Environment, clauses: Self::ProgramClauses) -> Self::Environment;
159-
160157
/// Selects the next appropriate subgoal index for evaluation.
161158
/// Used by: logic
162159
fn next_subgoal_index(ex_clause: &ExClause<Self>) -> usize;
@@ -180,6 +177,13 @@ pub trait ContextOps<C: Context>: Sized + Clone + Debug + AggregateOps<C> {
180177
infer: &mut C::InferenceTable,
181178
) -> Result<Vec<C::ProgramClause>, Floundered>;
182179

180+
// Used by: simplify
181+
fn add_clauses(
182+
&self,
183+
env: &C::Environment,
184+
clauses: C::ProgramClauses,
185+
) -> C::Environment;
186+
183187
/// Create an inference table for processing a new goal and instantiate that goal
184188
/// in that context, returning "all the pieces".
185189
///

chalk-engine/src/simplify.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl<C: Context> Forest<C> {
4141
pending_goals.push((environment, context.into_hh_goal(subgoal)))
4242
}
4343
HhGoal::Implies(wc, subgoal) => {
44-
let new_environment = C::add_clauses(&environment, wc);
44+
let new_environment = context.add_clauses(&environment, wc);
4545
pending_goals.push((new_environment, context.into_hh_goal(subgoal)));
4646
}
4747
HhGoal::All(subgoals) => {

chalk-integration/src/lowering.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1303,11 +1303,11 @@ impl<'k> LowerGoal<Env<'k>> for Goal {
13031303
// `T: Trait<Assoc = U>` to `FromEnv(T: Trait)` and `FromEnv(T: Trait<Assoc = U>)`
13041304
// in the assumptions of an `if` goal, e.g. `if (T: Trait) { ... }` lowers to
13051305
// `if (FromEnv(T: Trait)) { ... /* this part is untouched */ ... }`.
1306-
let where_clauses: LowerResult<Vec<_>> = hyp
1306+
let where_clauses = hyp
13071307
.into_iter()
13081308
.flat_map(|h| h.lower_clause(env).apply_result())
1309-
.map(|result| result.map(|h| h.into_from_env_clause(interner)))
1310-
.collect();
1309+
.map(|result| result.map(|h| h.into_from_env_clause(interner)));
1310+
let where_clauses = chalk_ir::ProgramClauses::from_fallible(interner, where_clauses);
13111311
Ok(chalk_ir::GoalData::Implies(where_clauses?, g.lower(env)?).intern(interner))
13121312
}
13131313
Goal::And(g1, g2s) => {

chalk-integration/src/program.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use chalk_ir::interner::ChalkIr;
55
use chalk_ir::tls;
66
use chalk_ir::{
77
debug::SeparatorTraitRef, AliasTy, ApplicationTy, AssocTypeId, Goal, Goals, ImplId, Lifetime,
8-
Parameter, ProgramClause, ProgramClauseImplication, StructId, Substitution, TraitId, Ty,
9-
TyData, TypeName,
8+
Parameter, ProgramClause, ProgramClauseImplication, ProgramClauses, StructId, Substitution,
9+
TraitId, Ty, TyData, TypeName,
1010
};
1111
use chalk_rust_ir::{
1212
AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ImplDatum, ImplType, StructDatum,
@@ -182,6 +182,15 @@ impl tls::DebugContext for Program {
182182
write!(fmt, "{:?}", clause.data(interner))
183183
}
184184

185+
fn debug_program_clauses(
186+
&self,
187+
clauses: &ProgramClauses<ChalkIr>,
188+
fmt: &mut fmt::Formatter<'_>,
189+
) -> Result<(), fmt::Error> {
190+
let interner = self.interner();
191+
write!(fmt, "{:?}", clauses.as_slice(interner))
192+
}
193+
185194
fn debug_application_ty(
186195
&self,
187196
application_ty: &ApplicationTy<ChalkIr>,

chalk-ir/src/debug.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ impl<I: Interner> Debug for ProgramClause<I> {
6565
}
6666
}
6767

68+
impl<I: Interner> Debug for ProgramClauses<I> {
69+
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
70+
I::debug_program_clauses(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.clauses))
71+
}
72+
}
73+
6874
impl<I: Interner> Debug for ApplicationTy<I> {
6975
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
7076
I::debug_application_ty(self, fmt).unwrap_or_else(|| write!(fmt, "ApplicationTy(?)"))

chalk-ir/src/fold/boring_impls.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,26 @@ impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for Goals<I> {
172172
}
173173
}
174174

175+
impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for ProgramClauses<I> {
176+
type Result = ProgramClauses<TI>;
177+
fn fold_with<'i>(
178+
&self,
179+
folder: &mut dyn Folder<'i, I, TI>,
180+
outer_binder: DebruijnIndex,
181+
) -> Fallible<Self::Result>
182+
where
183+
I: 'i,
184+
TI: 'i,
185+
{
186+
let interner = folder.interner();
187+
let target_interner = folder.target_interner();
188+
let folded = self
189+
.iter(interner)
190+
.map(|p| p.fold_with(folder, outer_binder));
191+
Ok(ProgramClauses::from_fallible(target_interner, folded)?)
192+
}
193+
}
194+
175195
#[macro_export]
176196
macro_rules! copy_fold {
177197
($t:ty) => {

chalk-ir/src/interner.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::ParameterData;
1111
use crate::ProgramClause;
1212
use crate::ProgramClauseData;
1313
use crate::ProgramClauseImplication;
14+
use crate::ProgramClauses;
1415
use crate::SeparatorTraitRef;
1516
use crate::StructId;
1617
use crate::Substitution;
@@ -96,6 +97,14 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
9697
/// converted back to its underlying data via `substitution_data`.
9798
type InternedSubstitution: Debug + Clone + Eq + Hash;
9899

100+
/// "Interned" representation of a list of program clauses. In normal user code,
101+
/// `Self::InternedProgramClauses` is not referenced. Instead, we refer to
102+
/// `ProgramClauses<Self>`, which wraps this type.
103+
///
104+
/// An `InternedProgramClauses` is created by `intern_program_clauses` and can be
105+
/// converted back to its underlying data via `program_clauses_data`.
106+
type InternedProgramClauses: Debug + Clone + Eq + Hash;
107+
99108
/// "Interned" representation of a "program clause". In normal user code,
100109
/// `Self::InternedProgramClause` is not referenced. Instead, we refer to
101110
/// `ProgramClause<Self>`, which wraps this type.
@@ -259,6 +268,21 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
259268
None
260269
}
261270

271+
/// Prints the debug representation of a ProgramClauses. To get good
272+
/// results, this requires inspecting TLS, and is difficult to
273+
/// code without reference to a specific interner (and hence
274+
/// fully known types).
275+
///
276+
/// Returns `None` to fallback to the default debug output (e.g.,
277+
/// if no info about current program is available from TLS).
278+
#[allow(unused_variables)]
279+
fn debug_program_clauses(
280+
clauses: &ProgramClauses<Self>,
281+
fmt: &mut fmt::Formatter<'_>,
282+
) -> Option<fmt::Result> {
283+
None
284+
}
285+
262286
/// Prints the debug representation of an ApplicationTy. To get good
263287
/// results, this requires inspecting TLS, and is difficult to
264288
/// code without reference to a specific interner (and hence
@@ -374,6 +398,21 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
374398
&self,
375399
clause: &'a Self::InternedProgramClause,
376400
) -> &'a ProgramClauseData<Self>;
401+
402+
/// Create an "interned" program clauses from `data`. This is not
403+
/// normally invoked directly; instead, you invoke
404+
/// `ProgramClauses::from` (which will ultimately call this
405+
/// method).
406+
fn intern_program_clauses(
407+
&self,
408+
data: impl IntoIterator<Item = ProgramClause<Self>>,
409+
) -> Self::InternedProgramClauses;
410+
411+
/// Lookup the `ProgramClauseData` that was interned to create a `ProgramClause`.
412+
fn program_clauses_data<'a>(
413+
&self,
414+
clauses: &'a Self::InternedProgramClauses,
415+
) -> &'a [ProgramClause<Self>];
377416
}
378417

379418
pub trait TargetInterner<I: Interner>: Interner {
@@ -429,6 +468,7 @@ mod default {
429468
type InternedGoals = Vec<Goal<ChalkIr>>;
430469
type InternedSubstitution = Vec<Parameter<ChalkIr>>;
431470
type InternedProgramClause = ProgramClauseData<ChalkIr>;
471+
type InternedProgramClauses = Vec<ProgramClause<ChalkIr>>;
432472
type DefId = RawId;
433473
type Identifier = Identifier;
434474

@@ -504,6 +544,13 @@ mod default {
504544
tls::with_current_program(|prog| Some(prog?.debug_program_clause(clause, fmt)))
505545
}
506546

547+
fn debug_program_clauses(
548+
clause: &ProgramClauses<ChalkIr>,
549+
fmt: &mut fmt::Formatter<'_>,
550+
) -> Option<fmt::Result> {
551+
tls::with_current_program(|prog| Some(prog?.debug_program_clauses(clause, fmt)))
552+
}
553+
507554
fn debug_application_ty(
508555
application_ty: &ApplicationTy<ChalkIr>,
509556
fmt: &mut fmt::Formatter<'_>,
@@ -603,6 +650,20 @@ mod default {
603650
) -> &'a ProgramClauseData<Self> {
604651
clause
605652
}
653+
654+
fn intern_program_clauses(
655+
&self,
656+
data: impl IntoIterator<Item = ProgramClause<Self>>,
657+
) -> Vec<ProgramClause<Self>> {
658+
data.into_iter().collect()
659+
}
660+
661+
fn program_clauses_data<'a>(
662+
&self,
663+
clauses: &'a Vec<ProgramClause<Self>>,
664+
) -> &'a [ProgramClause<Self>] {
665+
clauses
666+
}
606667
}
607668

608669
impl HasInterner for ChalkIr {

chalk-ir/src/lib.rs

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,20 @@ pub mod tls;
4848
/// The set of assumptions we've made so far, and the current number of
4949
/// universal (forall) quantifiers we're within.
5050
pub struct Environment<I: Interner> {
51-
pub clauses: Vec<ProgramClause<I>>,
51+
pub clauses: ProgramClauses<I>,
5252
}
5353

5454
impl<I: Interner> Environment<I> {
55-
pub fn new() -> Self {
56-
Environment { clauses: vec![] }
55+
pub fn new(interner: &I) -> Self {
56+
Environment { clauses: ProgramClauses::new(interner) }
5757
}
5858

59-
pub fn add_clauses<II>(&self, clauses: II) -> Self
59+
pub fn add_clauses<II>(&self, interner: &I, clauses: II) -> Self
6060
where
6161
II: IntoIterator<Item = ProgramClause<I>>,
6262
{
6363
let mut env = self.clone();
64-
env.clauses = env.clauses.into_iter().chain(clauses).collect();
64+
env.clauses = ProgramClauses::from(interner, env.clauses.iter(interner).cloned().chain(clauses));
6565
env
6666
}
6767
}
@@ -1265,6 +1265,56 @@ impl<I: Interner> ProgramClause<I> {
12651265
}
12661266
}
12671267

1268+
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)]
1269+
pub struct ProgramClauses<I: Interner> {
1270+
clauses: I::InternedProgramClauses,
1271+
}
1272+
1273+
impl<I: Interner> ProgramClauses<I> {
1274+
pub fn new(interner: &I) -> Self {
1275+
Self::from(interner, None::<ProgramClause<I>>)
1276+
}
1277+
1278+
pub fn interned(&self) -> &I::InternedProgramClauses {
1279+
&self.clauses
1280+
}
1281+
1282+
pub fn from(interner: &I, clauses: impl IntoIterator<Item = impl CastTo<ProgramClause<I>>>) -> Self {
1283+
use crate::cast::Caster;
1284+
ProgramClauses {
1285+
clauses: I::intern_program_clauses(interner, clauses.into_iter().casted(interner)),
1286+
}
1287+
}
1288+
1289+
pub fn from_fallible<E>(
1290+
interner: &I,
1291+
clauses: impl IntoIterator<Item = Result<impl CastTo<ProgramClause<I>>, E>>,
1292+
) -> Result<Self, E> {
1293+
use crate::cast::Caster;
1294+
let clauses = clauses
1295+
.into_iter()
1296+
.casted(interner)
1297+
.collect::<Result<Vec<ProgramClause<I>>, _>>()?;
1298+
Ok(Self::from(interner, clauses))
1299+
}
1300+
1301+
pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, ProgramClause<I>> {
1302+
self.as_slice(interner).iter()
1303+
}
1304+
1305+
pub fn is_empty(&self, interner: &I) -> bool {
1306+
self.as_slice(interner).is_empty()
1307+
}
1308+
1309+
pub fn len(&self, interner: &I) -> usize {
1310+
self.as_slice(interner).len()
1311+
}
1312+
1313+
pub fn as_slice(&self, interner: &I) -> &[ProgramClause<I>] {
1314+
interner.program_clauses_data(&self.clauses)
1315+
}
1316+
}
1317+
12681318
/// Wraps a "canonicalized item". Items are canonicalized as follows:
12691319
///
12701320
/// All unresolved existential variables are "renumbered" according to their
@@ -1410,10 +1460,13 @@ impl<I: Interner> Goal<I> {
14101460
QuantifierKind::ForAll,
14111461
Binders::with_fresh_type_var(interner, |ty| {
14121462
GoalData::Implies(
1413-
vec![
1414-
DomainGoal::Compatible(()).cast(interner),
1415-
DomainGoal::DownstreamType(ty).cast(interner),
1416-
],
1463+
ProgramClauses::from(
1464+
interner,
1465+
vec![
1466+
DomainGoal::Compatible(()),
1467+
DomainGoal::DownstreamType(ty),
1468+
],
1469+
),
14171470
self.shifted_in(interner),
14181471
)
14191472
.intern(interner)
@@ -1422,7 +1475,7 @@ impl<I: Interner> Goal<I> {
14221475
.intern(interner)
14231476
}
14241477

1425-
pub fn implied_by(self, interner: &I, predicates: Vec<ProgramClause<I>>) -> Goal<I> {
1478+
pub fn implied_by(self, interner: &I, predicates: ProgramClauses<I>) -> Goal<I> {
14261479
GoalData::Implies(predicates, self).intern(interner)
14271480
}
14281481

@@ -1470,7 +1523,7 @@ pub enum GoalData<I: Interner> {
14701523
/// Introduces a binding at depth 0, shifting other bindings up
14711524
/// (deBruijn index).
14721525
Quantified(QuantifierKind, Binders<Goal<I>>),
1473-
Implies(Vec<ProgramClause<I>>, Goal<I>),
1526+
Implies(ProgramClauses<I>, Goal<I>),
14741527
All(Goals<I>),
14751528
Not(Goal<I>),
14761529

chalk-ir/src/tls.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::interner::ChalkIr;
22
use crate::{
33
debug::SeparatorTraitRef, AliasTy, ApplicationTy, AssocTypeId, Goal, Goals, Lifetime,
4-
Parameter, ProgramClause, ProgramClauseImplication, StructId, Substitution, TraitId, Ty,
4+
Parameter, ProgramClause, ProgramClauseImplication, ProgramClauses, StructId, Substitution,
5+
TraitId, Ty,
56
};
67
use std::cell::RefCell;
78
use std::fmt;
@@ -74,6 +75,12 @@ pub trait DebugContext {
7475
fmt: &mut fmt::Formatter<'_>,
7576
) -> Result<(), fmt::Error>;
7677

78+
fn debug_program_clauses(
79+
&self,
80+
clauses: &ProgramClauses<ChalkIr>,
81+
fmt: &mut fmt::Formatter<'_>,
82+
) -> Result<(), fmt::Error>;
83+
7784
fn debug_application_ty(
7885
&self,
7986
application_ty: &ApplicationTy<ChalkIr>,

chalk-ir/src/zip.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,9 @@ impl<I: Interner> Zip<I> for Environment<I> {
250250
where
251251
I: 'i,
252252
{
253-
assert_eq!(a.clauses.len(), b.clauses.len()); // or different numbers of clauses
254-
Zip::zip_with(zipper, &a.clauses, &b.clauses)?;
253+
let interner = zipper.interner();
254+
assert_eq!(a.clauses.len(interner), b.clauses.len(interner)); // or different numbers of clauses
255+
Zip::zip_with(zipper, a.clauses.as_slice(interner), b.clauses.as_slice(interner))?;
255256
Ok(())
256257
}
257258
}
@@ -267,6 +268,17 @@ impl<I: Interner> Zip<I> for Goals<I> {
267268
}
268269
}
269270

271+
impl<I: Interner> Zip<I> for ProgramClauses<I> {
272+
fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
273+
where
274+
I: 'i,
275+
{
276+
let interner = zipper.interner();
277+
Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
278+
Ok(())
279+
}
280+
}
281+
270282
/// Generates a Zip impl that requires the two enums be the same
271283
/// variant, then zips each field of the variant in turn. Only works
272284
/// if all variants have a single parenthesized value right now.

0 commit comments

Comments
 (0)