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

Intern Vec<QuantifiedWhereClause<I>>. #379

Merged
merged 1 commit into from
Apr 7, 2020
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
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>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is getting to be an annoying amount of boilerplate -- not to be addressed in this PR, but I wonder if we can cleanup and encapsulate this pattern better.

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