Skip to content

Commit

Permalink
Intern Vec<QuantifiedWhereClause<I>>.
Browse files Browse the repository at this point in the history
  • Loading branch information
crlf0710 committed Apr 7, 2020
1 parent fd8cd45 commit 6384fc3
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 11 deletions.
14 changes: 7 additions & 7 deletions chalk-integration/src/lowering.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use chalk_ir::cast::{Cast, Caster};
use chalk_ir::interner::ChalkIr;
use chalk_ir::{
self, AssocTypeId, BoundVar, DebruijnIndex, ImplId, StructId, Substitution, TraitId,
self, AssocTypeId, BoundVar, DebruijnIndex, ImplId, QuantifiedWhereClauses, StructId,
Substitution, TraitId,
};
use chalk_parse::ast::*;
use chalk_rust_ir as rust_ir;
Expand Down Expand Up @@ -1000,10 +1001,9 @@ impl LowerTy for Ty {
// FIXME: Figure out a proper name for this type parameter
Some(chalk_ir::ParameterKind::Ty(intern(FIXME_SELF))),
|env| {
Ok(bounds
.lower(env)?
.iter()
.flat_map(|qil| {
Ok(QuantifiedWhereClauses::from(
interner,
bounds.lower(env)?.iter().flat_map(|qil| {
qil.into_where_clauses(
interner,
chalk_ir::TyData::BoundVar(BoundVar::new(
Expand All @@ -1012,8 +1012,8 @@ impl LowerTy for Ty {
))
.intern(interner),
)
})
.collect())
}),
))
},
)?,
})
Expand Down
9 changes: 9 additions & 0 deletions chalk-integration/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,15 @@ impl tls::DebugContext for Program {
let interner = self.interner();
write!(fmt, "{:?}", separator_trait_ref.debug(interner))
}

fn debug_quantified_where_clauses(
&self,
clauses: &chalk_ir::QuantifiedWhereClauses<ChalkIr>,
fmt: &mut fmt::Formatter<'_>,
) -> Result<(), fmt::Error> {
let interner = self.interner();
write!(fmt, "{:?}", clauses.as_slice(interner))
}
}

impl RustIrDatabase<ChalkIr> for Program {
Expand Down
1 change: 1 addition & 0 deletions chalk-ir/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ reflexive_impl!(for(I: Interner) DomainGoal<I>);
reflexive_impl!(for(I: Interner) Goal<I>);
reflexive_impl!(for(I: Interner) WhereClause<I>);
reflexive_impl!(for(I: Interner) ProgramClause<I>);
reflexive_impl!(for(I: Interner) QuantifiedWhereClause<I>);

impl<I: Interner> CastTo<WhereClause<I>> for TraitRef<I> {
fn cast_to(self, _interner: &I) -> WhereClause<I> {
Expand Down
7 changes: 7 additions & 0 deletions chalk-ir/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ impl<I: Interner> Debug for AliasTy<I> {
}
}

impl<I: Interner> Debug for QuantifiedWhereClauses<I> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
I::debug_quantified_where_clauses(self, fmt)
.unwrap_or_else(|| write!(fmt, "{:?}", self.interned))
}
}

impl<I: Interner> Display for Substitution<I> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> {
I::debug_substitution(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.parameters))
Expand Down
23 changes: 23 additions & 0 deletions chalk-ir/src/fold/boring_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,29 @@ impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for ProgramClauses<I> {
}
}

impl<I: Interner, TI: TargetInterner<I>> Fold<I, TI> for QuantifiedWhereClauses<I> {
type Result = QuantifiedWhereClauses<TI>;
fn fold_with<'i>(
&self,
folder: &mut dyn Folder<'i, I, TI>,
outer_binder: DebruijnIndex,
) -> Fallible<Self::Result>
where
I: 'i,
TI: 'i,
{
let interner = folder.interner();
let target_interner = folder.target_interner();
let folded = self
.iter(interner)
.map(|p| p.fold_with(folder, outer_binder));
Ok(QuantifiedWhereClauses::from_fallible(
target_interner,
folded,
)?)
}
}

#[macro_export]
macro_rules! copy_fold {
($t:ty) => {
Expand Down
65 changes: 65 additions & 0 deletions chalk-ir/src/interner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::ProgramClause;
use crate::ProgramClauseData;
use crate::ProgramClauseImplication;
use crate::ProgramClauses;
use crate::QuantifiedWhereClause;
use crate::QuantifiedWhereClauses;
use crate::SeparatorTraitRef;
use crate::StructId;
use crate::Substitution;
Expand Down Expand Up @@ -113,6 +115,14 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
/// converted back to its underlying data via `program_clause_data`.
type InternedProgramClause: Debug + Clone + Eq + Hash;

/// "Interned" representation of a list of quantified where clauses.
/// In normal user code, `Self::InternedQuantifiedWhereClauses` is not referenced.
/// Instead, we refer to `QuantifiedWhereClauses<Self>`, which wraps this type.
///
/// An `InternedQuantifiedWhereClauses` is created by `intern_quantified_where_clauses`
/// and can be converted back to its underlying data via `quantified_where_clauses_data`.
type InternedQuantifiedWhereClauses: Debug + Clone + Eq + Hash;

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

Expand Down Expand Up @@ -328,6 +338,21 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
None
}

/// Prints the debug representation of a QuantifiedWhereClauses. To get good
/// results, this requires inspecting TLS, and is difficult to
/// code without reference to a specific interner (and hence
/// fully known types).
///
/// Returns `None` to fallback to the default debug output (e.g.,
/// if no info about current program is available from TLS).
#[allow(unused_variables)]
fn debug_quantified_where_clauses(
clauses: &QuantifiedWhereClauses<Self>,
fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> {
None
}

/// Create an "interned" type from `ty`. This is not normally
/// invoked directly; instead, you invoke `TyData::intern` (which
/// will ultimately call this method).
Expand Down Expand Up @@ -413,6 +438,22 @@ pub trait Interner: Debug + Copy + Eq + Ord + Hash {
&self,
clauses: &'a Self::InternedProgramClauses,
) -> &'a [ProgramClause<Self>];

/// Create an "interned" quantified where clauses from `data`. This is not
/// normally invoked directly; instead, you invoke
/// `QuantifiedWhereClauses::from` (which will ultimately call this
/// method).
fn intern_quantified_where_clauses(
&self,
data: impl IntoIterator<Item = QuantifiedWhereClause<Self>>,
) -> Self::InternedQuantifiedWhereClauses;

/// Lookup the slice of `QuantifiedWhereClause` that was interned to
/// create a `QuantifiedWhereClauses`.
fn quantified_where_clauses_data<'a>(
&self,
clauses: &'a Self::InternedQuantifiedWhereClauses,
) -> &'a [QuantifiedWhereClause<Self>];
}

pub trait TargetInterner<I: Interner>: Interner {
Expand Down Expand Up @@ -469,6 +510,7 @@ mod default {
type InternedSubstitution = Vec<Parameter<ChalkIr>>;
type InternedProgramClause = ProgramClauseData<ChalkIr>;
type InternedProgramClauses = Vec<ProgramClause<ChalkIr>>;
type InternedQuantifiedWhereClauses = Vec<QuantifiedWhereClause<ChalkIr>>;
type DefId = RawId;
type Identifier = Identifier;

Expand Down Expand Up @@ -574,6 +616,15 @@ mod default {
})
}

fn debug_quantified_where_clauses(
clauses: &QuantifiedWhereClauses<Self>,
fmt: &mut fmt::Formatter<'_>,
) -> Option<fmt::Result> {
tls::with_current_program(|prog| {
Some(prog?.debug_quantified_where_clauses(clauses, fmt))
})
}

fn intern_ty(&self, ty: TyData<ChalkIr>) -> Arc<TyData<ChalkIr>> {
Arc::new(ty)
}
Expand Down Expand Up @@ -661,6 +712,20 @@ mod default {
) -> &'a [ProgramClause<Self>] {
clauses
}

fn intern_quantified_where_clauses(
&self,
data: impl IntoIterator<Item = QuantifiedWhereClause<Self>>,
) -> Self::InternedQuantifiedWhereClauses {
data.into_iter().collect()
}

fn quantified_where_clauses_data<'a>(
&self,
clauses: &'a Self::InternedQuantifiedWhereClauses,
) -> &'a [QuantifiedWhereClause<Self>] {
clauses
}
}

impl HasInterner for ChalkIr {
Expand Down
58 changes: 57 additions & 1 deletion chalk-ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ impl DebruijnIndex {
/// level of binder).
#[derive(Clone, PartialEq, Eq, Hash, Fold)]
pub struct DynTy<I: Interner> {
pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
pub bounds: Binders<QuantifiedWhereClauses<I>>,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
Expand Down Expand Up @@ -1033,6 +1033,62 @@ impl<I: Interner> QuantifiedWhereClause<I> {
}
}

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, HasInterner)]
pub struct QuantifiedWhereClauses<I: Interner> {
interned: I::InternedQuantifiedWhereClauses,
}

impl<I: Interner> QuantifiedWhereClauses<I> {
pub fn new(interner: &I) -> Self {
Self::from(interner, None::<QuantifiedWhereClause<I>>)
}

pub fn interned(&self) -> &I::InternedQuantifiedWhereClauses {
&self.interned
}

pub fn from(
interner: &I,
clauses: impl IntoIterator<Item = impl CastTo<QuantifiedWhereClause<I>>>,
) -> Self {
use crate::cast::Caster;
QuantifiedWhereClauses {
interned: I::intern_quantified_where_clauses(
interner,
clauses.into_iter().casted(interner),
),
}
}

pub fn from_fallible<E>(
interner: &I,
clauses: impl IntoIterator<Item = Result<impl CastTo<QuantifiedWhereClause<I>>, E>>,
) -> Result<Self, E> {
use crate::cast::Caster;
let clauses = clauses
.into_iter()
.casted(interner)
.collect::<Result<Vec<QuantifiedWhereClause<I>>, _>>()?;
Ok(Self::from(interner, clauses))
}

pub fn iter(&self, interner: &I) -> std::slice::Iter<'_, QuantifiedWhereClause<I>> {
self.as_slice(interner).iter()
}

pub fn is_empty(&self, interner: &I) -> bool {
self.as_slice(interner).is_empty()
}

pub fn len(&self, interner: &I) -> usize {
self.as_slice(interner).len()
}

pub fn as_slice(&self, interner: &I) -> &[QuantifiedWhereClause<I>] {
interner.quantified_where_clauses_data(&self.interned)
}
}

impl<I: Interner> DomainGoal<I> {
/// Convert `Implemented(...)` into `FromEnv(...)`, but leave other
/// goals unchanged.
Expand Down
10 changes: 8 additions & 2 deletions chalk-ir/src/tls.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::interner::ChalkIr;
use crate::{
debug::SeparatorTraitRef, AliasTy, ApplicationTy, AssocTypeId, Goal, Goals, Lifetime,
Parameter, ProgramClause, ProgramClauseImplication, ProgramClauses, StructId, Substitution,
TraitId, Ty,
Parameter, ProgramClause, ProgramClauseImplication, ProgramClauses, QuantifiedWhereClauses,
StructId, Substitution, TraitId, Ty,
};
use std::cell::RefCell;
use std::fmt;
Expand Down Expand Up @@ -98,6 +98,12 @@ pub trait DebugContext {
separator_trait_ref: &SeparatorTraitRef<'_, ChalkIr>,
fmt: &mut fmt::Formatter<'_>,
) -> Result<(), fmt::Error>;

fn debug_quantified_where_clauses(
&self,
clauses: &QuantifiedWhereClauses<ChalkIr>,
fmt: &mut fmt::Formatter<'_>,
) -> Result<(), fmt::Error>;
}

pub fn with_current_program<R>(op: impl FnOnce(Option<&Arc<dyn DebugContext>>) -> R) -> R {
Expand Down
11 changes: 11 additions & 0 deletions chalk-ir/src/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,17 @@ impl<I: Interner> Zip<I> for ProgramClauses<I> {
}
}

impl<I: Interner> Zip<I> for QuantifiedWhereClauses<I> {
fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
where
I: 'i,
{
let interner = zipper.interner();
Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
Ok(())
}
}

/// Generates a Zip impl that requires the two enums be the same
/// variant, then zips each field of the variant in turn. Only works
/// if all variants have a single parenthesized value right now.
Expand Down
2 changes: 1 addition & 1 deletion chalk-solve/src/clauses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ fn program_clauses_that_could_match<I: Interner>(
// and `bounded_ty` is the `exists<T> { .. }`
// clauses shown above.

for exists_qwc in &dyn_ty.bounds {
for exists_qwc in dyn_ty.bounds.map_ref(|r| r.iter(interner)) {
// Replace the `T` from `exists<T> { .. }` with `self_ty`,
// yielding clases like
//
Expand Down
6 changes: 6 additions & 0 deletions chalk-solve/src/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ impl<I: Interner> FoldInputTypes for Substitution<I> {
}
}

impl<I: Interner> FoldInputTypes for QuantifiedWhereClauses<I> {
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
self.as_slice(interner).fold(interner, accumulator)
}
}

impl<I: Interner> FoldInputTypes for Ty<I> {
fn fold(&self, interner: &I, accumulator: &mut Vec<Ty<I>>) {
match self.data(interner) {
Expand Down

0 comments on commit 6384fc3

Please sign in to comment.