Skip to content

Commit

Permalink
Auto merge of #729 - henrikhorluck:std-controlflow, r=matthewjasper
Browse files Browse the repository at this point in the history
Replace `ControlFlow` with version in std

- Since Rust 1.55, `ControlFlow` is now available in std
- Some functions are not available in std yet, and the functional
  equivalents have been used (e.g. `ControlFlow::Break(())` instead of
  `ControlFlow::BREAK`, etc.)

Closes #725
  • Loading branch information
bors committed Oct 3, 2021
2 parents 03a20f1 + c518108 commit 10ba203
Show file tree
Hide file tree
Showing 13 changed files with 69 additions and 105 deletions.
4 changes: 2 additions & 2 deletions chalk-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,14 @@ fn derive_any_visit(
&self,
visitor: &mut dyn ::chalk_ir::visit::Visitor < 'i, #interner, BreakTy = B >,
outer_binder: ::chalk_ir::DebruijnIndex,
) -> ::chalk_ir::visit::ControlFlow<B>
) -> std::ops::ControlFlow<B>
where
#interner: 'i
{
match *self {
#body
}
::chalk_ir::visit::ControlFlow::CONTINUE
std::ops::ControlFlow::Continue(())
}
},
)
Expand Down
2 changes: 1 addition & 1 deletion chalk-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ use std::usize;

use chalk_derive::{Fold, HasInterner, Visit};
use chalk_ir::interner::Interner;
use chalk_ir::visit::ControlFlow;
use chalk_ir::{
AnswerSubst, Canonical, ConstrainedSubst, Constraint, DebruijnIndex, Goal, InEnvironment,
Substitution,
};
use std::ops::ControlFlow;

pub mod context;
mod derived;
Expand Down
3 changes: 2 additions & 1 deletion chalk-ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ extern crate self as chalk_ir;
use crate::cast::{Cast, CastTo, Caster};
use crate::fold::shift::Shift;
use crate::fold::{Fold, Folder, Subst, SuperFold};
use crate::visit::{ControlFlow, SuperVisit, Visit, VisitExt, Visitor};
use crate::visit::{SuperVisit, Visit, VisitExt, Visitor};
use chalk_derive::{Fold, HasInterner, SuperVisit, Visit, Zip};
use std::marker::PhantomData;
use std::ops::ControlFlow;

pub use crate::debug::SeparatorTraitRef;
#[macro_use(bitflags)]
Expand Down
71 changes: 14 additions & 57 deletions chalk-ir/src/visit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Traits for visiting bits of IR.
use std::fmt::Debug;
use std::ops::ControlFlow;

use crate::{
BoundVar, Const, ConstValue, DebruijnIndex, DomainGoal, Goal, InferenceVar, Interner, Lifetime,
Expand All @@ -12,59 +13,15 @@ pub mod visitors;

pub use visitors::VisitExt;

/// An copy of the unstable `std::ops::ControlFlow` for use in Chalk visitors.
pub enum ControlFlow<B, C = ()> {
/// Continue in the loop, using the given value for the next iteration
Continue(C),
/// Exit the loop, yielding the given value
Break(B),
}

impl<B, C> ControlFlow<B, C> {
/// Returns `true` if this is a `Break` variant.
#[inline]
pub fn is_break(&self) -> bool {
matches!(*self, ControlFlow::Break(_))
}

/// Returns `true` if this is a `Continue` variant.
#[inline]
pub fn is_continue(&self) -> bool {
matches!(*self, ControlFlow::Continue(_))
}

/// Converts the `ControlFlow` into an `Option` which is `Some`
/// if the `ControlFlow` was `Break` and `None` otherwise.
#[inline]
pub fn break_value(self) -> Option<B> {
match self {
ControlFlow::Continue(..) => None,
ControlFlow::Break(x) => Some(x),
}
}
}

impl<B> ControlFlow<B, ()> {
/// It's frequently the case that there's no value needed with `Continue`,
/// so this provides a way to avoid typing `(())`, if you prefer it.
pub const CONTINUE: Self = ControlFlow::Continue(());
}

impl<C> ControlFlow<(), C> {
/// APIs like `try_for_each` don't need values with `Break`,
/// so this provides a way to avoid typing `(())`, if you prefer it.
pub const BREAK: Self = ControlFlow::Break(());
}

/// Unwraps a `ControlFlow` or propagates its `Break` value.
/// This replaces the `Try` implementation that would be used
/// with `std::ops::ControlFlow`.
#[macro_export]
macro_rules! try_break {
($expr:expr) => {
match $expr {
$crate::visit::ControlFlow::Continue(c) => c,
$crate::visit::ControlFlow::Break(b) => return $crate::visit::ControlFlow::Break(b),
std::ops::ControlFlow::Continue(c) => c,
std::ops::ControlFlow::Break(b) => return std::ops::ControlFlow::Break(b),
}
};
}
Expand Down Expand Up @@ -174,7 +131,7 @@ where
bound_var, outer_binder
)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}

Expand All @@ -194,7 +151,7 @@ where
if self.forbid_free_placeholders() {
panic!("unexpected placeholder type `{:?}`", universe)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}

Expand Down Expand Up @@ -224,7 +181,7 @@ where
if self.forbid_inference_vars() {
panic!("unexpected inference type `{:?}`", var)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}

Expand Down Expand Up @@ -298,7 +255,7 @@ where
if let Some(_) = bound_var.shifted_out_to(outer_binder) {
visitor.visit_free_var(*bound_var, outer_binder)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
TyKind::Dyn(clauses) => clauses.visit_with(visitor, outer_binder),
Expand All @@ -311,7 +268,7 @@ where
substitution.visit_with(visitor, outer_binder)
}
TyKind::Scalar(scalar) => scalar.visit_with(visitor, outer_binder),
TyKind::Str => ControlFlow::CONTINUE,
TyKind::Str => ControlFlow::Continue(()),
TyKind::Tuple(arity, substitution) => {
try_break!(arity.visit_with(visitor, outer_binder));
substitution.visit_with(visitor, outer_binder)
Expand All @@ -334,7 +291,7 @@ where
try_break!(mutability.visit_with(visitor, outer_binder));
ty.visit_with(visitor, outer_binder)
}
TyKind::Never => ControlFlow::CONTINUE,
TyKind::Never => ControlFlow::Continue(()),
TyKind::Array(ty, const_) => {
try_break!(ty.visit_with(visitor, outer_binder));
const_.visit_with(visitor, outer_binder)
Expand All @@ -352,7 +309,7 @@ where
substitution.visit_with(visitor, outer_binder)
}
TyKind::Foreign(foreign_ty) => foreign_ty.visit_with(visitor, outer_binder),
TyKind::Error => ControlFlow::CONTINUE,
TyKind::Error => ControlFlow::Continue(()),
}
}
}
Expand Down Expand Up @@ -385,15 +342,15 @@ impl<I: Interner> SuperVisit<I> for Lifetime<I> {
if let Some(_) = bound_var.shifted_out_to(outer_binder) {
visitor.visit_free_var(*bound_var, outer_binder)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
LifetimeData::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder),
LifetimeData::Placeholder(universe) => {
visitor.visit_free_placeholder(*universe, outer_binder)
}
LifetimeData::Static | LifetimeData::Empty(_) | LifetimeData::Erased => {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
LifetimeData::Phantom(void, ..) => match *void {},
}
Expand Down Expand Up @@ -428,14 +385,14 @@ impl<I: Interner> SuperVisit<I> for Const<I> {
if let Some(_) = bound_var.shifted_out_to(outer_binder) {
visitor.visit_free_var(*bound_var, outer_binder)
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
ConstValue::InferenceVar(var) => visitor.visit_inference_var(*var, outer_binder),
ConstValue::Placeholder(universe) => {
visitor.visit_free_placeholder(*universe, outer_binder)
}
ConstValue::Concrete(_) => ControlFlow::CONTINUE,
ConstValue::Concrete(_) => ControlFlow::Continue(()),
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions chalk-ir/src/visit/boring_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ where
for e in it {
try_break!(e.visit_with(visitor, outer_binder));
}
ControlFlow::CONTINUE
ControlFlow::Continue(())
}

impl<T: Visit<I>, I: Interner> Visit<I> for &T {
Expand Down Expand Up @@ -104,7 +104,7 @@ macro_rules! tuple_visit {
$(
try_break!($n.visit_with(visitor, outer_binder));
)*
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
}
Expand All @@ -126,7 +126,7 @@ impl<T: Visit<I>, I: Interner> Visit<I> for Option<T> {
{
match self {
Some(e) => e.visit_with(visitor, outer_binder),
None => ControlFlow::CONTINUE,
None => ControlFlow::Continue(()),
}
}
}
Expand Down Expand Up @@ -186,7 +186,7 @@ macro_rules! const_visit {
where
I: 'i,
{
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
};
Expand Down Expand Up @@ -220,7 +220,7 @@ macro_rules! id_visit {
where
I: 'i,
{
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
};
Expand Down Expand Up @@ -305,6 +305,6 @@ impl<I: Interner> Visit<I> for PhantomData<I> {
where
I: 'i,
{
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
8 changes: 4 additions & 4 deletions chalk-ir/src/visit/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ use crate::{BoundVar, ControlFlow, DebruijnIndex, Interner, Visit, Visitor};
pub trait VisitExt<I: Interner>: Visit<I> {
/// Check whether there are free (non-bound) variables.
fn has_free_vars(&self, interner: &I) -> bool {
self.visit_with(
let flow = self.visit_with(
&mut FindFreeVarsVisitor { interner },
DebruijnIndex::INNERMOST,
)
.is_break()
);
matches!(flow, ControlFlow::Break(_))
}
}

Expand All @@ -36,6 +36,6 @@ impl<'i, I: Interner> Visitor<'i, I> for FindFreeVarsVisitor<'i, I> {
_bound_var: BoundVar,
_outer_binder: DebruijnIndex,
) -> ControlFlow<()> {
ControlFlow::BREAK
ControlFlow::Break(())
}
}
22 changes: 12 additions & 10 deletions chalk-solve/src/clauses/builtin_traits/unsize.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::collections::HashSet;
use std::iter;
use std::ops::ControlFlow;

use crate::clauses::ClauseBuilder;
use crate::rust_ir::AdtKind;
use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait};
use chalk_ir::{
cast::Cast,
interner::HasInterner,
visit::{ControlFlow, SuperVisit, Visit, Visitor},
visit::{SuperVisit, Visit, Visitor},
Binders, Const, ConstValue, DebruijnIndex, DomainGoal, DynTy, EqGoal, Goal, LifetimeOutlives,
QuantifiedWhereClauses, Substitution, TraitId, Ty, TyKind, TypeOutlives, WhereClause,
};
Expand All @@ -34,7 +35,7 @@ impl<'a, I: Interner> Visitor<'a, I> for UnsizeParameterCollector<'a, I> {
if bound_var.debruijn.shifted_in() == outer_binder {
self.parameters.insert(bound_var.index);
}
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
_ => ty.super_visit_with(self, outer_binder),
}
Expand All @@ -49,7 +50,7 @@ impl<'a, I: Interner> Visitor<'a, I> for UnsizeParameterCollector<'a, I> {
self.parameters.insert(bound_var.index);
}
}
ControlFlow::CONTINUE
ControlFlow::Continue(())
}

fn interner(&self) -> &'a I {
Expand Down Expand Up @@ -90,9 +91,9 @@ impl<'a, 'p, I: Interner> Visitor<'a, I> for ParameterOccurenceCheck<'a, 'p, I>
if bound_var.debruijn.shifted_in() == outer_binder
&& self.parameters.contains(&bound_var.index)
{
ControlFlow::BREAK
ControlFlow::Break(())
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
_ => ty.super_visit_with(self, outer_binder),
Expand All @@ -107,12 +108,12 @@ impl<'a, 'p, I: Interner> Visitor<'a, I> for ParameterOccurenceCheck<'a, 'p, I>
if bound_var.debruijn.shifted_in() == outer_binder
&& self.parameters.contains(&bound_var.index)
{
ControlFlow::BREAK
ControlFlow::Break(())
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
_ => ControlFlow::CONTINUE,
_ => ControlFlow::Continue(()),
}
}

Expand All @@ -130,8 +131,9 @@ fn uses_outer_binder_params<I: Interner>(
interner,
parameters,
};
v.visit_with(&mut visitor, DebruijnIndex::INNERMOST)
.is_break()

let flow = v.visit_with(&mut visitor, DebruijnIndex::INNERMOST);
matches!(flow, ControlFlow::Break(_))
}

fn principal_id<'a, I: Interner>(
Expand Down
9 changes: 5 additions & 4 deletions chalk-solve/src/clauses/env_elaborator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ use crate::RustIrDatabase;
use crate::Ty;
use crate::{debug_span, TyKind};
use chalk_ir::interner::Interner;
use chalk_ir::visit::{ControlFlow, Visit, Visitor};
use chalk_ir::visit::{Visit, Visitor};
use chalk_ir::{DebruijnIndex, Environment};
use rustc_hash::FxHashSet;
use std::ops::ControlFlow;
use tracing::instrument;

/// When proving a `FromEnv` goal, we elaborate all `FromEnv` goals
Expand Down Expand Up @@ -71,7 +72,7 @@ impl<'me, 'builder, I: Interner> Visitor<'me, I> for EnvElaborator<'me, 'builder
.unwrap()
}
}
ControlFlow::CONTINUE
ControlFlow::Continue(())
}

fn visit_domain_goal(
Expand All @@ -95,12 +96,12 @@ impl<'me, 'builder, I: Interner> Visitor<'me, I> for EnvElaborator<'me, 'builder
.associated_ty_data(associated_ty_id)
.to_program_clauses(self.builder, self.environment);
}
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
FromEnv::Ty(ty) => ty.visit_with(self, outer_binder),
}
} else {
ControlFlow::CONTINUE
ControlFlow::Continue(())
}
}
}
Loading

0 comments on commit 10ba203

Please sign in to comment.