Skip to content

Commit

Permalink
Auto merge of #651 - LeSeulArtichaut:visitor-breakty, r=jackh726
Browse files Browse the repository at this point in the history
Introduce `Visitor::BreakTy`

Implements the equivalent of MCP rust-lang/compiler-team#383 in chalk.
r? `@jackh726`

~~Should probably be blocked on rust-lang/compiler-team#383.~~
  • Loading branch information
bors committed Nov 15, 2020
2 parents e9c82ba + 905c72d commit bc99ed6
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 128 deletions.
6 changes: 3 additions & 3 deletions chalk-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ fn derive_any_visit(
s.bound_impl(
quote!(::chalk_ir::visit:: #trait_name <#interner>),
quote! {
fn #method_name <'i>(
fn #method_name <'i, B>(
&self,
visitor: &mut dyn ::chalk_ir::visit::Visitor < 'i, #interner >,
visitor: &mut dyn ::chalk_ir::visit::Visitor < 'i, #interner, BreakTy = B >,
outer_binder: ::chalk_ir::DebruijnIndex,
) -> ::chalk_ir::visit::ControlFlow<()>
) -> ::chalk_ir::visit::ControlFlow<B>
where
#interner: 'i
{
Expand Down
112 changes: 62 additions & 50 deletions chalk-ir/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,24 @@ pub trait Visitor<'i, I: Interner>
where
I: 'i,
{
/// The "break type" of the visitor, often `()`. It represents the result
/// the visitor yields when it stops visiting.
type BreakTy;

/// Creates a `dyn` value from this visitor. Unfortunately, this
/// must be added manually to each impl of visitor; it permits the
/// default implements below to create a `&mut dyn Visitor` from
/// `Self` without knowing what `Self` is (by invoking this
/// method). Effectively, this limits impls of `visitor` to types
/// for which we are able to create a dyn value (i.e., not `[T]`
/// types).
fn as_dyn(&mut self) -> &mut dyn Visitor<'i, I>;
fn as_dyn(&mut self) -> &mut dyn Visitor<'i, I, BreakTy = Self::BreakTy>;

/// Top-level callback: invoked for each `Ty<I>` that is
/// encountered when visiting. By default, invokes
/// `super_visit_with`, which will in turn invoke the more
/// specialized visiting methods below, like `visit_free_var`.
fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<Self::BreakTy> {
ty.super_visit_with(self.as_dyn(), outer_binder)
}

Expand All @@ -107,15 +111,19 @@ where
&mut self,
lifetime: &Lifetime<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
lifetime.super_visit_with(self.as_dyn(), outer_binder)
}

/// Top-level callback: invoked for each `Const<I>` that is
/// encountered when visiting. By default, invokes
/// `super_visit_with`, which will in turn invoke the more
/// specialized visiting methods below, like `visit_free_var`.
fn visit_const(&mut self, constant: &Const<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
fn visit_const(
&mut self,
constant: &Const<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<Self::BreakTy> {
constant.super_visit_with(self.as_dyn(), outer_binder)
}

Expand All @@ -124,12 +132,16 @@ where
&mut self,
clause: &ProgramClause<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
clause.super_visit_with(self.as_dyn(), outer_binder)
}

/// Invoked for every goal. By default, recursively visits the goals contents.
fn visit_goal(&mut self, goal: &Goal<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
fn visit_goal(
&mut self,
goal: &Goal<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<Self::BreakTy> {
goal.super_visit_with(self.as_dyn(), outer_binder)
}

Expand All @@ -138,7 +150,7 @@ where
&mut self,
domain_goal: &DomainGoal<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
domain_goal.super_visit_with(self.as_dyn(), outer_binder)
}

Expand All @@ -155,7 +167,7 @@ where
&mut self,
bound_var: BoundVar,
outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
if self.forbid_free_vars() {
panic!(
"unexpected free variable `{:?}` with outer binder {:?}",
Expand All @@ -178,7 +190,7 @@ where
&mut self,
universe: PlaceholderIndex,
_outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
if self.forbid_free_placeholders() {
panic!("unexpected placeholder type `{:?}`", universe)
} else {
Expand All @@ -191,7 +203,7 @@ where
&mut self,
where_clause: &WhereClause<I>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
where_clause.super_visit_with(self.as_dyn(), outer_binder)
}

Expand All @@ -208,7 +220,7 @@ where
&mut self,
var: InferenceVar,
_outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
) -> ControlFlow<Self::BreakTy> {
if self.forbid_inference_vars() {
panic!("unexpected inference type `{:?}`", var)
} else {
Expand All @@ -228,11 +240,11 @@ pub trait Visit<I: Interner>: Debug {
/// visitor. Typically `binders` starts as 0, but is adjusted when
/// we encounter `Binders<T>` in the IR or other similar
/// constructs.
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i;
}
Expand All @@ -242,11 +254,11 @@ pub trait Visit<I: Interner>: Debug {
/// the contents of the type.
pub trait SuperVisit<I: Interner>: Visit<I> {
/// Recursively visits the type contents.
fn super_visit_with<'i>(
fn super_visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i;
}
Expand All @@ -255,11 +267,11 @@ pub trait SuperVisit<I: Interner>: Visit<I> {
/// usually (in turn) invokes `super_visit_ty` to visit the individual
/// parts.
impl<I: Interner> Visit<I> for Ty<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -272,11 +284,11 @@ impl<I> SuperVisit<I> for Ty<I>
where
I: Interner,
{
fn super_visit_with<'i>(
fn super_visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand Down Expand Up @@ -346,11 +358,11 @@ where
}

impl<I: Interner> Visit<I> for Lifetime<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -359,11 +371,11 @@ impl<I: Interner> Visit<I> for Lifetime<I> {
}

impl<I: Interner> SuperVisit<I> for Lifetime<I> {
fn super_visit_with<'i>(
fn super_visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -389,11 +401,11 @@ impl<I: Interner> SuperVisit<I> for Lifetime<I> {
}

impl<I: Interner> Visit<I> for Const<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -402,11 +414,11 @@ impl<I: Interner> Visit<I> for Const<I> {
}

impl<I: Interner> SuperVisit<I> for Const<I> {
fn super_visit_with<'i>(
fn super_visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -429,11 +441,11 @@ impl<I: Interner> SuperVisit<I> for Const<I> {
}

impl<I: Interner> Visit<I> for Goal<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -442,11 +454,11 @@ impl<I: Interner> Visit<I> for Goal<I> {
}

impl<I: Interner> SuperVisit<I> for Goal<I> {
fn super_visit_with<'i>(
fn super_visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -456,11 +468,11 @@ impl<I: Interner> SuperVisit<I> for Goal<I> {
}

impl<I: Interner> Visit<I> for ProgramClause<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -469,11 +481,11 @@ impl<I: Interner> Visit<I> for ProgramClause<I> {
}

impl<I: Interner> Visit<I> for WhereClause<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -482,11 +494,11 @@ impl<I: Interner> Visit<I> for WhereClause<I> {
}

impl<I: Interner> Visit<I> for DomainGoal<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand Down
18 changes: 9 additions & 9 deletions chalk-ir/src/visit/binder_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use crate::interner::HasInterner;
use crate::{Binders, Canonical, ControlFlow, DebruijnIndex, FnPointer, Interner, Visit, Visitor};

impl<I: Interner> Visit<I> for FnPointer<I> {
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -24,11 +24,11 @@ impl<T, I: Interner> Visit<I> for Binders<T>
where
T: HasInterner + Visit<I>,
{
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand All @@ -41,11 +41,11 @@ where
I: Interner,
T: HasInterner<Interner = I> + Visit<I>,
{
fn visit_with<'i>(
fn visit_with<'i, B>(
&self,
visitor: &mut dyn Visitor<'i, I>,
visitor: &mut dyn Visitor<'i, I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<()>
) -> ControlFlow<B>
where
I: 'i,
{
Expand Down
Loading

0 comments on commit bc99ed6

Please sign in to comment.