From 79126279bf2f64b9245d1967de80d94292d9853d Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 19 Jun 2022 07:51:15 +0100 Subject: [PATCH 1/6] Rename TypeFolder to FallibleTypeFolder --- chalk-derive/src/lib.rs | 2 +- chalk-engine/src/normalize_deep.rs | 6 +-- chalk-engine/src/strand.rs | 4 +- chalk-ir/src/fold.rs | 53 +++++++++++++------------- chalk-ir/src/fold/binder_impls.rs | 6 +-- chalk-ir/src/fold/boring_impls.rs | 30 +++++++-------- chalk-ir/src/fold/shift.rs | 8 ++-- chalk-ir/src/fold/subst.rs | 4 +- chalk-ir/src/lib.rs | 6 +-- chalk-solve/src/clauses/generalize.rs | 6 +-- chalk-solve/src/infer/canonicalize.rs | 6 +-- chalk-solve/src/infer/invert.rs | 6 +-- chalk-solve/src/infer/ucanonicalize.rs | 10 ++--- chalk-solve/src/infer/unify.rs | 6 +-- 14 files changed, 77 insertions(+), 76 deletions(-) diff --git a/chalk-derive/src/lib.rs b/chalk-derive/src/lib.rs index ecf01307033..a5ac9b40a7c 100644 --- a/chalk-derive/src/lib.rs +++ b/chalk-derive/src/lib.rs @@ -287,7 +287,7 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { quote! { fn fold_with( self, - folder: &mut dyn ::chalk_ir::fold::TypeFolder < #interner, Error = E >, + folder: &mut dyn ::chalk_ir::fold::FallibleTypeFolder < #interner, Error = E >, outer_binder: ::chalk_ir::DebruijnIndex, ) -> ::std::result::Result { Ok(match self { #body }) diff --git a/chalk-engine/src/normalize_deep.rs b/chalk-engine/src/normalize_deep.rs index d7c45befe79..1b5af1329a0 100644 --- a/chalk-engine/src/normalize_deep.rs +++ b/chalk-engine/src/normalize_deep.rs @@ -1,5 +1,5 @@ use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{TypeFoldable, TypeFolder}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; use chalk_ir::interner::Interner; use chalk_ir::*; use chalk_solve::infer::InferenceTable; @@ -35,10 +35,10 @@ impl DeepNormalizer<'_, I> { } } -impl TypeFolder for DeepNormalizer<'_, I> { +impl FallibleTypeFolder for DeepNormalizer<'_, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-engine/src/strand.rs b/chalk-engine/src/strand.rs index ccc392ee1e5..5cbe8e99a5f 100644 --- a/chalk-engine/src/strand.rs +++ b/chalk-engine/src/strand.rs @@ -3,7 +3,7 @@ use crate::{ExClause, TableIndex, TimeStamp}; use std::fmt::Debug; use chalk_derive::HasInterner; -use chalk_ir::fold::{TypeFoldable, TypeFolder}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; use chalk_ir::interner::Interner; use chalk_ir::{Canonical, DebruijnIndex, UniverseMap}; @@ -38,7 +38,7 @@ pub(crate) struct SelectedSubgoal { impl TypeFoldable for Strand { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { Ok(Strand { diff --git a/chalk-ir/src/fold.rs b/chalk-ir/src/fold.rs index 390d8809bb4..1b9ac7bfd0c 100644 --- a/chalk-ir/src/fold.rs +++ b/chalk-ir/src/fold.rs @@ -17,8 +17,8 @@ pub use self::subst::Subst; /// certain changes applied. The idea is that it contains methods that /// let you swap types/lifetimes for new types/lifetimes; meanwhile, /// each bit of IR implements the `TypeFoldable` trait which, given a -/// `TypeFolder`, will reconstruct itself, invoking the folder's methods -/// to transform each of the types/lifetimes embedded within. +/// `FallibleTypeFolder`, will reconstruct itself, invoking the folder's +/// methods to transform each of the types/lifetimes embedded within. /// /// # Usage patterns /// @@ -29,15 +29,15 @@ pub use self::subst::Subst; /// more often, just free existential variables) that appear within /// the term. /// -/// For this reason, the `TypeFolder` trait extends two other traits that -/// contain methods that are invoked when just those particular +/// For this reason, the `FallibleTypeFolder` trait extends two other +/// traits that contain methods that are invoked when just those particular /// /// In particular, folders can intercept references to free variables /// (either existentially or universally quantified) and replace them /// with other types/lifetimes as appropriate. /// -/// To create a folder `F`, one never implements `TypeFolder` directly, but instead -/// implements one of each of these three sub-traits: +/// To create a folder `F`, one never implements `FallibleTypeFolder` +/// directly, but instead implements one of each of these three sub-traits: /// /// - `FreeVarFolder` -- folds `BoundVar` instances that appear free /// in the term being folded (use `DefaultFreeVarFolder` to @@ -49,24 +49,25 @@ pub use self::subst::Subst; /// that appear in the term being folded (use /// `DefaultPlaceholderFolder` to ignore/forbid these altogether) /// -/// To **apply** a folder, use the `TypeFoldable::fold_with` method, like so +/// To **apply** a folder, use the `TypeFoldable::fold_with` method, +/// like so /// /// ```rust,ignore /// let x = x.fold_with(&mut folder, 0); /// ``` -pub trait TypeFolder { +pub trait FallibleTypeFolder { /// The type this folder returns when folding fails. This is /// commonly [`NoSolution`]. type Error; /// Creates a `dyn` value from this folder. Unfortunately, this - /// must be added manually to each impl of TypeFolder; it permits the - /// default implements below to create a `&mut dyn TypeFolder` from - /// `Self` without knowing what `Self` is (by invoking this - /// method). Effectively, this limits impls of `TypeFolder` to types - /// for which we are able to create a dyn value (i.e., not `[T]` - /// types). - fn as_dyn(&mut self) -> &mut dyn TypeFolder; + /// must be added manually to each impl of FallibleTypeFolder; it + /// permits the default implements below to create a + /// `&mut dyn FallibleTypeFolder` from `Self` without knowing what + /// `Self` is (by invoking this method). Effectively, this limits + /// impls of `FallibleTypeFolder` to types for which we are able to + /// create a dyn value (i.e., not `[T]` types). + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder; /// Top-level callback: invoked for each `Ty` that is /// encountered when folding. By default, invokes @@ -318,7 +319,7 @@ pub trait TypeFoldable: Debug + Sized { /// constructs. fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result; } @@ -330,7 +331,7 @@ pub trait TypeSuperFoldable: TypeFoldable { /// Recursively folds the value. fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result; } @@ -341,7 +342,7 @@ pub trait TypeSuperFoldable: TypeFoldable { impl TypeFoldable for Ty { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { folder.fold_ty(self, outer_binder) @@ -355,7 +356,7 @@ where { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result, E> { let interner = folder.interner(); @@ -463,7 +464,7 @@ where impl TypeFoldable for Lifetime { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { folder.fold_lifetime(self, outer_binder) @@ -476,7 +477,7 @@ where { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result, E> { let interner = folder.interner(); @@ -513,7 +514,7 @@ where impl TypeFoldable for Const { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { folder.fold_const(self, outer_binder) @@ -526,7 +527,7 @@ where { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result, E> { let interner = folder.interner(); @@ -562,7 +563,7 @@ where impl TypeFoldable for Goal { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { folder.fold_goal(self, outer_binder) @@ -573,7 +574,7 @@ impl TypeFoldable for Goal { impl TypeSuperFoldable for Goal { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -592,7 +593,7 @@ impl TypeSuperFoldable for Goal { impl TypeFoldable for ProgramClause { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { folder.fold_program_clause(self, outer_binder) diff --git a/chalk-ir/src/fold/binder_impls.rs b/chalk-ir/src/fold/binder_impls.rs index 8b35238c759..8900657924d 100644 --- a/chalk-ir/src/fold/binder_impls.rs +++ b/chalk-ir/src/fold/binder_impls.rs @@ -8,7 +8,7 @@ use crate::*; impl TypeFoldable for FnPointer { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let FnPointer { @@ -35,7 +35,7 @@ where { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let Binders { @@ -57,7 +57,7 @@ where { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let Canonical { diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index 74fb43aeb43..1d81a37fc1b 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -11,7 +11,7 @@ use std::marker::PhantomData; impl, I: Interner> TypeFoldable for Vec { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { in_place::fallible_map_vec(self, |e| e.fold_with(folder, outer_binder)) @@ -21,7 +21,7 @@ impl, I: Interner> TypeFoldable for Vec { impl, I: Interner> TypeFoldable for Box { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { in_place::fallible_map_box(self, |e| e.fold_with(folder, outer_binder)) @@ -31,7 +31,7 @@ impl, I: Interner> TypeFoldable for Box { macro_rules! tuple_fold { ($($n:ident),*) => { impl<$($n: TypeFoldable,)* I: Interner> TypeFoldable for ($($n,)*) { - fn fold_with(self, folder: &mut dyn TypeFolder, outer_binder: DebruijnIndex) -> Result + fn fold_with(self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex) -> Result { #[allow(non_snake_case)] let ($($n),*) = self; @@ -49,7 +49,7 @@ tuple_fold!(A, B, C, D, E); impl, I: Interner> TypeFoldable for Option { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { match self { @@ -62,7 +62,7 @@ impl, I: Interner> TypeFoldable for Option { impl TypeFoldable for GenericArg { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -78,7 +78,7 @@ impl TypeFoldable for GenericArg { impl TypeFoldable for Substitution { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -94,7 +94,7 @@ impl TypeFoldable for Substitution { impl TypeFoldable for Goals { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -109,7 +109,7 @@ impl TypeFoldable for Goals { impl TypeFoldable for ProgramClauses { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -124,7 +124,7 @@ impl TypeFoldable for ProgramClauses { impl TypeFoldable for QuantifiedWhereClauses { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -139,7 +139,7 @@ impl TypeFoldable for QuantifiedWhereClauses { impl TypeFoldable for Constraints { fn fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let interner = folder.interner(); @@ -158,7 +158,7 @@ macro_rules! copy_fold { impl $crate::fold::TypeFoldable for $t { fn fold_with( self, - _folder: &mut dyn ($crate::fold::TypeFolder), + _folder: &mut dyn ($crate::fold::FallibleTypeFolder), _outer_binder: DebruijnIndex, ) -> ::std::result::Result { Ok(self) @@ -189,7 +189,7 @@ macro_rules! id_fold { impl $crate::fold::TypeFoldable for $t { fn fold_with( self, - _folder: &mut dyn ($crate::fold::TypeFolder), + _folder: &mut dyn ($crate::fold::FallibleTypeFolder), _outer_binder: DebruijnIndex, ) -> ::std::result::Result { Ok(self) @@ -211,7 +211,7 @@ id_fold!(ForeignDefId); impl TypeSuperFoldable for ProgramClauseData { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> ::std::result::Result { Ok(ProgramClauseData(self.0.fold_with(folder, outer_binder)?)) @@ -221,7 +221,7 @@ impl TypeSuperFoldable for ProgramClauseData { impl TypeSuperFoldable for ProgramClause { fn super_fold_with( self, - folder: &mut dyn TypeFolder, + folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> ::std::result::Result { let clause = self.data(folder.interner()).clone(); @@ -234,7 +234,7 @@ impl TypeSuperFoldable for ProgramClause { impl TypeFoldable for PhantomData { fn fold_with( self, - _folder: &mut dyn TypeFolder, + _folder: &mut dyn FallibleTypeFolder, _outer_binder: DebruijnIndex, ) -> ::std::result::Result { Ok(PhantomData) diff --git a/chalk-ir/src/fold/shift.rs b/chalk-ir/src/fold/shift.rs index cfbe6f114a0..f3fa6082cd0 100644 --- a/chalk-ir/src/fold/shift.rs +++ b/chalk-ir/src/fold/shift.rs @@ -71,10 +71,10 @@ impl Shifter { } } -impl TypeFolder for Shifter { +impl FallibleTypeFolder for Shifter { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } @@ -141,10 +141,10 @@ impl DownShifter { } } -impl TypeFolder for DownShifter { +impl FallibleTypeFolder for DownShifter { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-ir/src/fold/subst.rs b/chalk-ir/src/fold/subst.rs index 89ffe6e0fa2..de40f255773 100644 --- a/chalk-ir/src/fold/subst.rs +++ b/chalk-ir/src/fold/subst.rs @@ -25,10 +25,10 @@ impl Subst<'_, I> { } } -impl TypeFolder for Subst<'_, I> { +impl FallibleTypeFolder for Subst<'_, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index ffc5cfcf285..39bbdafea45 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -8,7 +8,7 @@ extern crate self as chalk_ir; use crate::cast::{Cast, CastTo, Caster}; use crate::fold::shift::Shift; -use crate::fold::{Subst, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use crate::fold::{FallibleTypeFolder, Subst, TypeFoldable, TypeSuperFoldable}; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor, VisitExt}; use chalk_derive::{HasInterner, TypeFoldable, TypeSuperVisitable, TypeVisitable, Zip}; use std::marker::PhantomData; @@ -2825,10 +2825,10 @@ impl<'a, I: Interner> ToGenericArg for (usize, &'a VariableKind) { } } -impl<'i, I: Interner, A: AsParameters> TypeFolder for &SubstFolder<'i, I, A> { +impl<'i, I: Interner, A: AsParameters> FallibleTypeFolder for &SubstFolder<'i, I, A> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-solve/src/clauses/generalize.rs b/chalk-solve/src/clauses/generalize.rs index 91f7e7b832f..05ccfae2f2c 100644 --- a/chalk-solve/src/clauses/generalize.rs +++ b/chalk-solve/src/clauses/generalize.rs @@ -7,7 +7,7 @@ //! types passed to `program_clauses` in the clauses we generate. use chalk_ir::{ - fold::{TypeFoldable, TypeFolder}, + fold::{FallibleTypeFolder, TypeFoldable}, interner::{HasInterner, Interner}, Binders, BoundVar, Const, ConstData, ConstValue, DebruijnIndex, Fallible, Lifetime, LifetimeData, NoSolution, Ty, TyKind, TyVariableKind, VariableKind, VariableKinds, @@ -40,10 +40,10 @@ impl Generalize { } } -impl TypeFolder for Generalize { +impl FallibleTypeFolder for Generalize { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-solve/src/infer/canonicalize.rs b/chalk-solve/src/infer/canonicalize.rs index cd55056f264..d8f3b38fecf 100644 --- a/chalk-solve/src/infer/canonicalize.rs +++ b/chalk-solve/src/infer/canonicalize.rs @@ -1,6 +1,6 @@ use crate::debug_span; use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use chalk_ir::interner::{HasInterner, Interner}; use chalk_ir::*; use std::cmp::max; @@ -101,10 +101,10 @@ impl<'q, I: Interner> Canonicalizer<'q, I> { } } -impl<'i, I: Interner> TypeFolder for Canonicalizer<'i, I> { +impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-solve/src/infer/invert.rs b/chalk-solve/src/infer/invert.rs index 36e32ee428c..6f013c37b38 100644 --- a/chalk-solve/src/infer/invert.rs +++ b/chalk-solve/src/infer/invert.rs @@ -1,5 +1,5 @@ use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{TypeFoldable, TypeFolder}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; use chalk_ir::interner::HasInterner; use chalk_ir::interner::Interner; use chalk_ir::*; @@ -127,10 +127,10 @@ impl<'q, I: Interner> Inverter<'q, I> { } } -impl<'i, I: Interner> TypeFolder for Inverter<'i, I> { +impl<'i, I: Interner> FallibleTypeFolder for Inverter<'i, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-solve/src/infer/ucanonicalize.rs b/chalk-solve/src/infer/ucanonicalize.rs index 6f09a4490eb..20ad5b2a940 100644 --- a/chalk-solve/src/infer/ucanonicalize.rs +++ b/chalk-solve/src/infer/ucanonicalize.rs @@ -1,5 +1,5 @@ use crate::debug_span; -use chalk_ir::fold::{TypeFoldable, TypeFolder}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; use chalk_ir::interner::{HasInterner, Interner}; use chalk_ir::visit::{TypeVisitable, TypeVisitor}; use chalk_ir::*; @@ -222,10 +222,10 @@ struct UMapToCanonical<'q, I> { universes: &'q UniverseMap, } -impl<'i, I: Interner> TypeFolder for UMapToCanonical<'i, I> { +impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } @@ -294,10 +294,10 @@ struct UMapFromCanonical<'q, I> { universes: &'q UniverseMap, } -impl<'i, I: Interner> TypeFolder for UMapFromCanonical<'i, I> { +impl<'i, I: Interner> FallibleTypeFolder for UMapFromCanonical<'i, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } diff --git a/chalk-solve/src/infer/unify.rs b/chalk-solve/src/infer/unify.rs index 469fdd27f94..2c789f1ca90 100644 --- a/chalk-solve/src/infer/unify.rs +++ b/chalk-solve/src/infer/unify.rs @@ -2,7 +2,7 @@ use super::var::*; use super::*; use crate::debug_span; use chalk_ir::cast::Cast; -use chalk_ir::fold::{TypeFoldable, TypeFolder}; +use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; use chalk_ir::interner::{HasInterner, Interner}; use chalk_ir::zip::{Zip, Zipper}; use chalk_ir::UnificationDatabase; @@ -1246,10 +1246,10 @@ impl<'u, 't, I: Interner> OccursCheck<'u, 't, I> { } } -impl<'i, I: Interner> TypeFolder for OccursCheck<'_, 'i, I> { +impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } From 23d7523356f56af6f4e54d3324ea6db60f97a7f0 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 19 Jun 2022 08:40:28 +0100 Subject: [PATCH 2/6] Rename fallible methods --- chalk-derive/src/lib.rs | 4 +- chalk-engine/src/normalize_deep.rs | 14 +- chalk-engine/src/strand.rs | 4 +- chalk-ir/src/fold.rs | 209 +++++++++++++------------ chalk-ir/src/fold/binder_impls.rs | 12 +- chalk-ir/src/fold/boring_impls.rs | 56 +++---- chalk-ir/src/fold/shift.rs | 16 +- chalk-ir/src/fold/subst.rs | 8 +- chalk-ir/src/lib.rs | 8 +- chalk-solve/src/clauses/generalize.rs | 8 +- chalk-solve/src/infer/canonicalize.rs | 26 +-- chalk-solve/src/infer/invert.rs | 6 +- chalk-solve/src/infer/ucanonicalize.rs | 14 +- chalk-solve/src/infer/unify.rs | 22 +-- 14 files changed, 213 insertions(+), 194 deletions(-) diff --git a/chalk-derive/src/lib.rs b/chalk-derive/src/lib.rs index a5ac9b40a7c..77709b27726 100644 --- a/chalk-derive/src/lib.rs +++ b/chalk-derive/src/lib.rs @@ -269,7 +269,7 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { vi.construct(|_, index| { let bind = &bindings[index]; quote! { - ::chalk_ir::fold::TypeFoldable::fold_with(#bind, folder, outer_binder)? + ::chalk_ir::fold::TypeFoldable::try_fold_with(#bind, folder, outer_binder)? } }) }); @@ -285,7 +285,7 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { s.bound_impl( quote!(::chalk_ir::fold::TypeFoldable<#interner>), quote! { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn ::chalk_ir::fold::FallibleTypeFolder < #interner, Error = E >, outer_binder: ::chalk_ir::DebruijnIndex, diff --git a/chalk-engine/src/normalize_deep.rs b/chalk-engine/src/normalize_deep.rs index 1b5af1329a0..2b8be951510 100644 --- a/chalk-engine/src/normalize_deep.rs +++ b/chalk-engine/src/normalize_deep.rs @@ -27,7 +27,7 @@ impl DeepNormalizer<'_, I> { value: T, ) -> T { value - .fold_with( + .try_fold_with( &mut DeepNormalizer { interner, table }, DebruijnIndex::INNERMOST, ) @@ -42,7 +42,7 @@ impl FallibleTypeFolder for DeepNormalizer<'_, I> { self } - fn fold_inference_ty( + fn try_fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, @@ -53,7 +53,7 @@ impl FallibleTypeFolder for DeepNormalizer<'_, I> { Some(ty) => Ok(ty .assert_ty_ref(interner) .clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in(interner)), // FIXME shift None => { // Normalize all inference vars which have been unified into a @@ -63,7 +63,7 @@ impl FallibleTypeFolder for DeepNormalizer<'_, I> { } } - fn fold_inference_lifetime( + fn try_fold_inference_lifetime( &mut self, var: InferenceVar, _outer_binder: DebruijnIndex, @@ -73,13 +73,13 @@ impl FallibleTypeFolder for DeepNormalizer<'_, I> { Some(l) => Ok(l .assert_lifetime_ref(interner) .clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in(interner)), None => Ok(var.to_lifetime(interner)), // FIXME shift } } - fn fold_inference_const( + fn try_fold_inference_const( &mut self, ty: Ty, var: InferenceVar, @@ -90,7 +90,7 @@ impl FallibleTypeFolder for DeepNormalizer<'_, I> { Some(c) => Ok(c .assert_const_ref(interner) .clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in(interner)), None => Ok(var.to_const(interner, ty)), // FIXME shift } diff --git a/chalk-engine/src/strand.rs b/chalk-engine/src/strand.rs index 5cbe8e99a5f..da25a778d87 100644 --- a/chalk-engine/src/strand.rs +++ b/chalk-engine/src/strand.rs @@ -36,13 +36,13 @@ pub(crate) struct SelectedSubgoal { } impl TypeFoldable for Strand { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { Ok(Strand { - ex_clause: self.ex_clause.fold_with(folder, outer_binder)?, + ex_clause: self.ex_clause.try_fold_with(folder, outer_binder)?, last_pursued_time: self.last_pursued_time, selected_subgoal: self.selected_subgoal, }) diff --git a/chalk-ir/src/fold.rs b/chalk-ir/src/fold.rs index 1b9ac7bfd0c..c44fc79d706 100644 --- a/chalk-ir/src/fold.rs +++ b/chalk-ir/src/fold.rs @@ -49,11 +49,11 @@ pub use self::subst::Subst; /// that appear in the term being folded (use /// `DefaultPlaceholderFolder` to ignore/forbid these altogether) /// -/// To **apply** a folder, use the `TypeFoldable::fold_with` method, +/// To **apply** a folder, use the `TypeFoldable::try_fold_with` method, /// like so /// /// ```rust,ignore -/// let x = x.fold_with(&mut folder, 0); +/// let x = x.try_fold_with(&mut folder, 0); /// ``` pub trait FallibleTypeFolder { /// The type this folder returns when folding fails. This is @@ -71,52 +71,56 @@ pub trait FallibleTypeFolder { /// Top-level callback: invoked for each `Ty` that is /// encountered when folding. By default, invokes - /// `super_fold_with`, which will in turn invoke the more - /// specialized folding methods below, like `fold_free_var_ty`. - fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Result, Self::Error> { - ty.super_fold_with(self.as_dyn(), outer_binder) + /// `try_super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `try_fold_free_var_ty`. + fn try_fold_ty( + &mut self, + ty: Ty, + outer_binder: DebruijnIndex, + ) -> Result, Self::Error> { + ty.try_super_fold_with(self.as_dyn(), outer_binder) } /// Top-level callback: invoked for each `Lifetime` that is /// encountered when folding. By default, invokes - /// `super_fold_with`, which will in turn invoke the more - /// specialized folding methods below, like `fold_free_var_lifetime`. - fn fold_lifetime( + /// `try_super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `try_fold_free_var_lifetime`. + fn try_fold_lifetime( &mut self, lifetime: Lifetime, outer_binder: DebruijnIndex, ) -> Result, Self::Error> { - lifetime.super_fold_with(self.as_dyn(), outer_binder) + lifetime.try_super_fold_with(self.as_dyn(), outer_binder) } /// Top-level callback: invoked for each `Const` that is /// encountered when folding. By default, invokes - /// `super_fold_with`, which will in turn invoke the more - /// specialized folding methods below, like `fold_free_var_const`. - fn fold_const( + /// `try_super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `try_fold_free_var_const`. + fn try_fold_const( &mut self, constant: Const, outer_binder: DebruijnIndex, ) -> Result, Self::Error> { - constant.super_fold_with(self.as_dyn(), outer_binder) + constant.try_super_fold_with(self.as_dyn(), outer_binder) } /// Invoked for every program clause. By default, recursively folds the goals contents. - fn fold_program_clause( + fn try_fold_program_clause( &mut self, clause: ProgramClause, outer_binder: DebruijnIndex, ) -> Result, Self::Error> { - clause.super_fold_with(self.as_dyn(), outer_binder) + clause.try_super_fold_with(self.as_dyn(), outer_binder) } /// Invoked for every goal. By default, recursively folds the goals contents. - fn fold_goal( + fn try_fold_goal( &mut self, goal: Goal, outer_binder: DebruijnIndex, ) -> Result, Self::Error> { - goal.super_fold_with(self.as_dyn(), outer_binder) + goal.try_super_fold_with(self.as_dyn(), outer_binder) } /// If overridden to return true, then folding will panic if a @@ -135,7 +139,7 @@ pub trait FallibleTypeFolder { /// /// This should return a type suitable for a context with /// `binders` in scope. - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -151,8 +155,8 @@ pub trait FallibleTypeFolder { } } - /// As `fold_free_var_ty`, but for lifetimes. - fn fold_free_var_lifetime( + /// As `try_fold_free_var_ty`, but for lifetimes. + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -168,8 +172,8 @@ pub trait FallibleTypeFolder { } } - /// As `fold_free_var_ty`, but for constants. - fn fold_free_var_const( + /// As `try_fold_free_var_ty`, but for constants. + fn try_fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, @@ -183,7 +187,7 @@ pub trait FallibleTypeFolder { } else { let bound_var = bound_var.shifted_in_from(outer_binder); Ok(ConstData { - ty: ty.fold_with(self.as_dyn(), outer_binder)?, + ty: ty.try_fold_with(self.as_dyn(), outer_binder)?, value: ConstValue::::BoundVar(bound_var), } .intern(self.interner())) @@ -204,7 +208,7 @@ pub trait FallibleTypeFolder { /// - `universe` is the universe of the `TypeName::ForAll` that was found /// - `binders` is the number of binders in scope #[allow(unused_variables)] - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, outer_binder: DebruijnIndex, @@ -216,9 +220,9 @@ pub trait FallibleTypeFolder { } } - /// As with `fold_free_placeholder_ty`, but for lifetimes. + /// As with `try_fold_free_placeholder_ty`, but for lifetimes. #[allow(unused_variables)] - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, universe: PlaceholderIndex, outer_binder: DebruijnIndex, @@ -230,9 +234,9 @@ pub trait FallibleTypeFolder { } } - /// As with `fold_free_placeholder_ty`, but for constants. + /// As with `try_fold_free_placeholder_ty`, but for constants. #[allow(unused_variables)] - fn fold_free_placeholder_const( + fn try_fold_free_placeholder_const( &mut self, ty: Ty, universe: PlaceholderIndex, @@ -241,7 +245,10 @@ pub trait FallibleTypeFolder { if self.forbid_free_placeholders() { panic!("unexpected placeholder const `{:?}`", universe) } else { - Ok(universe.to_const(self.interner(), ty.fold_with(self.as_dyn(), outer_binder)?)) + Ok(universe.to_const( + self.interner(), + ty.try_fold_with(self.as_dyn(), outer_binder)?, + )) } } @@ -260,7 +267,7 @@ pub trait FallibleTypeFolder { /// - `universe` is the universe of the `TypeName::ForAll` that was found /// - `binders` is the number of binders in scope #[allow(unused_variables)] - fn fold_inference_ty( + fn try_fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, @@ -273,9 +280,9 @@ pub trait FallibleTypeFolder { } } - /// As with `fold_inference_ty`, but for lifetimes. + /// As with `try_fold_inference_ty`, but for lifetimes. #[allow(unused_variables)] - fn fold_inference_lifetime( + fn try_fold_inference_lifetime( &mut self, var: InferenceVar, outer_binder: DebruijnIndex, @@ -287,9 +294,9 @@ pub trait FallibleTypeFolder { } } - /// As with `fold_inference_ty`, but for constants. + /// As with `try_fold_inference_ty`, but for constants. #[allow(unused_variables)] - fn fold_inference_const( + fn try_fold_inference_const( &mut self, ty: Ty, var: InferenceVar, @@ -298,7 +305,10 @@ pub trait FallibleTypeFolder { if self.forbid_inference_vars() { panic!("unexpected inference const `{:?}`", var) } else { - Ok(var.to_const(self.interner(), ty.fold_with(self.as_dyn(), outer_binder)?)) + Ok(var.to_const( + self.interner(), + ty.try_fold_with(self.as_dyn(), outer_binder)?, + )) } } @@ -317,7 +327,7 @@ pub trait TypeFoldable: Debug + Sized { /// folder. Typically `binders` starts as 0, but is adjusted when /// we encounter `Binders` in the IR or other similar /// constructs. - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -329,23 +339,23 @@ pub trait TypeFoldable: Debug + Sized { /// the contents of the type. pub trait TypeSuperFoldable: TypeFoldable { /// Recursively folds the value. - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result; } -/// "Folding" a type invokes the `fold_ty` method on the folder; this -/// usually (in turn) invokes `super_fold_ty` to fold the individual +/// "Folding" a type invokes the `try_fold_ty` method on the folder; this +/// usually (in turn) invokes `try_super_fold_ty` to fold the individual /// parts. impl TypeFoldable for Ty { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - folder.fold_ty(self, outer_binder) + folder.try_fold_ty(self, outer_binder) } } @@ -354,7 +364,7 @@ impl TypeSuperFoldable for Ty where I: Interner, { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -367,7 +377,7 @@ where // that we have traversed during folding; // therefore, it is free. Let the folder have a // crack at it. - folder.fold_free_var_ty(bound_var1, outer_binder)? + folder.try_fold_free_var_ty(bound_var1, outer_binder)? } else { // This variable was bound within the binders that // we folded over, so just return a bound @@ -375,83 +385,86 @@ where self } } - TyKind::Dyn(clauses) => TyKind::Dyn(clauses.clone().fold_with(folder, outer_binder)?) - .intern(folder.interner()), + TyKind::Dyn(clauses) => { + TyKind::Dyn(clauses.clone().try_fold_with(folder, outer_binder)?) + .intern(folder.interner()) + } TyKind::InferenceVar(var, kind) => { - folder.fold_inference_ty(*var, *kind, outer_binder)? + folder.try_fold_inference_ty(*var, *kind, outer_binder)? } - TyKind::Placeholder(ui) => folder.fold_free_placeholder_ty(*ui, outer_binder)?, - TyKind::Alias(proj) => TyKind::Alias(proj.clone().fold_with(folder, outer_binder)?) - .intern(folder.interner()), - TyKind::Function(fun) => TyKind::Function(fun.clone().fold_with(folder, outer_binder)?) + TyKind::Placeholder(ui) => folder.try_fold_free_placeholder_ty(*ui, outer_binder)?, + TyKind::Alias(proj) => TyKind::Alias(proj.clone().try_fold_with(folder, outer_binder)?) .intern(folder.interner()), + TyKind::Function(fun) => { + TyKind::Function(fun.clone().try_fold_with(folder, outer_binder)?) + .intern(folder.interner()) + } TyKind::Adt(id, substitution) => TyKind::Adt( - id.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + id.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::AssociatedType(assoc_ty, substitution) => TyKind::AssociatedType( - assoc_ty.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + assoc_ty.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), - TyKind::Scalar(scalar) => { - TyKind::Scalar(scalar.fold_with(folder, outer_binder)?).intern(folder.interner()) - } + TyKind::Scalar(scalar) => TyKind::Scalar(scalar.try_fold_with(folder, outer_binder)?) + .intern(folder.interner()), TyKind::Str => TyKind::Str.intern(folder.interner()), TyKind::Tuple(arity, substitution) => TyKind::Tuple( *arity, - substitution.clone().fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::OpaqueType(opaque_ty, substitution) => TyKind::OpaqueType( - opaque_ty.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + opaque_ty.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Slice(substitution) => { - TyKind::Slice(substitution.clone().fold_with(folder, outer_binder)?) + TyKind::Slice(substitution.clone().try_fold_with(folder, outer_binder)?) .intern(folder.interner()) } TyKind::FnDef(fn_def, substitution) => TyKind::FnDef( - fn_def.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + fn_def.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Ref(mutability, lifetime, ty) => TyKind::Ref( - mutability.fold_with(folder, outer_binder)?, - lifetime.clone().fold_with(folder, outer_binder)?, - ty.clone().fold_with(folder, outer_binder)?, + mutability.try_fold_with(folder, outer_binder)?, + lifetime.clone().try_fold_with(folder, outer_binder)?, + ty.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Raw(mutability, ty) => TyKind::Raw( - mutability.fold_with(folder, outer_binder)?, - ty.clone().fold_with(folder, outer_binder)?, + mutability.try_fold_with(folder, outer_binder)?, + ty.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Never => TyKind::Never.intern(folder.interner()), TyKind::Array(ty, const_) => TyKind::Array( - ty.clone().fold_with(folder, outer_binder)?, - const_.clone().fold_with(folder, outer_binder)?, + ty.clone().try_fold_with(folder, outer_binder)?, + const_.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Closure(id, substitution) => TyKind::Closure( - id.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + id.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Generator(id, substitution) => TyKind::Generator( - id.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + id.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::GeneratorWitness(id, substitution) => TyKind::GeneratorWitness( - id.fold_with(folder, outer_binder)?, - substitution.clone().fold_with(folder, outer_binder)?, + id.try_fold_with(folder, outer_binder)?, + substitution.clone().try_fold_with(folder, outer_binder)?, ) .intern(folder.interner()), TyKind::Foreign(id) => { - TyKind::Foreign(id.fold_with(folder, outer_binder)?).intern(folder.interner()) + TyKind::Foreign(id.try_fold_with(folder, outer_binder)?).intern(folder.interner()) } TyKind::Error => TyKind::Error.intern(folder.interner()), }) @@ -462,12 +475,12 @@ where /// usually (in turn) invokes `super_fold_lifetime` to fold the individual /// parts. impl TypeFoldable for Lifetime { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - folder.fold_lifetime(self, outer_binder) + folder.try_fold_lifetime(self, outer_binder) } } @@ -475,7 +488,7 @@ impl TypeSuperFoldable for Lifetime where I: Interner, { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -488,7 +501,7 @@ where // that we have traversed during folding; // therefore, it is free. Let the folder have a // crack at it. - folder.fold_free_var_lifetime(bound_var1, outer_binder) + folder.try_fold_free_var_lifetime(bound_var1, outer_binder) } else { // This variable was bound within the binders that // we folded over, so just return a bound @@ -496,9 +509,11 @@ where Ok(self) } } - LifetimeData::InferenceVar(var) => folder.fold_inference_lifetime(*var, outer_binder), + LifetimeData::InferenceVar(var) => { + folder.try_fold_inference_lifetime(*var, outer_binder) + } LifetimeData::Placeholder(universe) => { - folder.fold_free_placeholder_lifetime(*universe, outer_binder) + folder.try_fold_free_placeholder_lifetime(*universe, outer_binder) } LifetimeData::Static => Ok(LifetimeData::::Static.intern(folder.interner())), LifetimeData::Empty(ui) => Ok(LifetimeData::::Empty(*ui).intern(folder.interner())), @@ -512,12 +527,12 @@ where /// usually (in turn) invokes `super_fold_const` to fold the individual /// parts. impl TypeFoldable for Const { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - folder.fold_const(self, outer_binder) + folder.try_fold_const(self, outer_binder) } } @@ -525,27 +540,27 @@ impl TypeSuperFoldable for Const where I: Interner, { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result, E> { let interner = folder.interner(); let ConstData { ref ty, ref value } = self.data(interner); - let mut fold_ty = || ty.clone().fold_with(folder, outer_binder); + let mut fold_ty = || ty.clone().try_fold_with(folder, outer_binder); match value { ConstValue::BoundVar(bound_var) => { if let Some(bound_var1) = bound_var.shifted_out_to(outer_binder) { - folder.fold_free_var_const(ty.clone(), bound_var1, outer_binder) + folder.try_fold_free_var_const(ty.clone(), bound_var1, outer_binder) } else { Ok(self) } } ConstValue::InferenceVar(var) => { - folder.fold_inference_const(ty.clone(), *var, outer_binder) + folder.try_fold_inference_const(ty.clone(), *var, outer_binder) } ConstValue::Placeholder(universe) => { - folder.fold_free_placeholder_const(ty.clone(), *universe, outer_binder) + folder.try_fold_free_placeholder_const(ty.clone(), *universe, outer_binder) } ConstValue::Concrete(ev) => Ok(ConstData { ty: fold_ty()?, @@ -561,18 +576,18 @@ where /// Folding a goal invokes the `fold_goal` callback (which will, by /// default, invoke super-fold). impl TypeFoldable for Goal { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - folder.fold_goal(self, outer_binder) + folder.try_fold_goal(self, outer_binder) } } /// Superfold folds recursively. impl TypeSuperFoldable for Goal { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -582,7 +597,7 @@ impl TypeSuperFoldable for Goal { interner, self.data(interner) .clone() - .fold_with(folder, outer_binder)?, + .try_fold_with(folder, outer_binder)?, )) } } @@ -591,11 +606,11 @@ impl TypeSuperFoldable for Goal { /// callback on the folder (which will, by default, invoke the /// `super_fold_with` method on the program clause). impl TypeFoldable for ProgramClause { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - folder.fold_program_clause(self, outer_binder) + folder.try_fold_program_clause(self, outer_binder) } } diff --git a/chalk-ir/src/fold/binder_impls.rs b/chalk-ir/src/fold/binder_impls.rs index 8900657924d..1f44c162962 100644 --- a/chalk-ir/src/fold/binder_impls.rs +++ b/chalk-ir/src/fold/binder_impls.rs @@ -6,7 +6,7 @@ use crate::*; impl TypeFoldable for FnPointer { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -18,7 +18,7 @@ impl TypeFoldable for FnPointer { } = self; Ok(FnPointer { num_binders, - substitution: substitution.fold_with(folder, outer_binder.shifted_in())?, + substitution: substitution.try_fold_with(folder, outer_binder.shifted_in())?, sig: FnSig { abi: sig.abi, safety: sig.safety, @@ -33,7 +33,7 @@ where T: HasInterner + TypeFoldable, I: Interner, { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -42,7 +42,7 @@ where binders: self_binders, value: self_value, } = self; - let value = self_value.fold_with(folder, outer_binder.shifted_in())?; + let value = self_value.try_fold_with(folder, outer_binder.shifted_in())?; let binders = VariableKinds { interned: self_binders.interned().clone(), }; @@ -55,7 +55,7 @@ where I: Interner, T: HasInterner + TypeFoldable, { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -64,7 +64,7 @@ where binders: self_binders, value: self_value, } = self; - let value = self_value.fold_with(folder, outer_binder.shifted_in())?; + let value = self_value.try_fold_with(folder, outer_binder.shifted_in())?; let binders = CanonicalVarKinds { interned: self_binders.interned().clone(), }; diff --git a/chalk-ir/src/fold/boring_impls.rs b/chalk-ir/src/fold/boring_impls.rs index 1d81a37fc1b..fb4e3e30b9d 100644 --- a/chalk-ir/src/fold/boring_impls.rs +++ b/chalk-ir/src/fold/boring_impls.rs @@ -9,33 +9,33 @@ use crate::*; use std::marker::PhantomData; impl, I: Interner> TypeFoldable for Vec { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - in_place::fallible_map_vec(self, |e| e.fold_with(folder, outer_binder)) + in_place::fallible_map_vec(self, |e| e.try_fold_with(folder, outer_binder)) } } impl, I: Interner> TypeFoldable for Box { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { - in_place::fallible_map_box(self, |e| e.fold_with(folder, outer_binder)) + in_place::fallible_map_box(self, |e| e.try_fold_with(folder, outer_binder)) } } macro_rules! tuple_fold { ($($n:ident),*) => { impl<$($n: TypeFoldable,)* I: Interner> TypeFoldable for ($($n,)*) { - fn fold_with(self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex) -> Result + fn try_fold_with(self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex) -> Result { #[allow(non_snake_case)] let ($($n),*) = self; - Ok(($($n.fold_with(folder, outer_binder)?,)*)) + Ok(($($n.try_fold_with(folder, outer_binder)?,)*)) } } } @@ -47,20 +47,20 @@ tuple_fold!(A, B, C, D); tuple_fold!(A, B, C, D, E); impl, I: Interner> TypeFoldable for Option { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { match self { None => Ok(None), - Some(e) => Ok(Some(e.fold_with(folder, outer_binder)?)), + Some(e) => Ok(Some(e.try_fold_with(folder, outer_binder)?)), } } } impl TypeFoldable for GenericArg { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -70,13 +70,13 @@ impl TypeFoldable for GenericArg { let data = self .data(interner) .clone() - .fold_with(folder, outer_binder)?; + .try_fold_with(folder, outer_binder)?; Ok(GenericArg::new(interner, data)) } } impl TypeFoldable for Substitution { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -86,13 +86,13 @@ impl TypeFoldable for Substitution { let folded = self .iter(interner) .cloned() - .map(|p| p.fold_with(folder, outer_binder)); + .map(|p| p.try_fold_with(folder, outer_binder)); Substitution::from_fallible(interner, folded) } } impl TypeFoldable for Goals { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -101,13 +101,13 @@ impl TypeFoldable for Goals { let folded = self .iter(interner) .cloned() - .map(|p| p.fold_with(folder, outer_binder)); + .map(|p| p.try_fold_with(folder, outer_binder)); Goals::from_fallible(interner, folded) } } impl TypeFoldable for ProgramClauses { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -116,13 +116,13 @@ impl TypeFoldable for ProgramClauses { let folded = self .iter(interner) .cloned() - .map(|p| p.fold_with(folder, outer_binder)); + .map(|p| p.try_fold_with(folder, outer_binder)); ProgramClauses::from_fallible(interner, folded) } } impl TypeFoldable for QuantifiedWhereClauses { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -131,13 +131,13 @@ impl TypeFoldable for QuantifiedWhereClauses { let folded = self .iter(interner) .cloned() - .map(|p| p.fold_with(folder, outer_binder)); + .map(|p| p.try_fold_with(folder, outer_binder)); QuantifiedWhereClauses::from_fallible(interner, folded) } } impl TypeFoldable for Constraints { - fn fold_with( + fn try_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, @@ -146,7 +146,7 @@ impl TypeFoldable for Constraints { let folded = self .iter(interner) .cloned() - .map(|p| p.fold_with(folder, outer_binder)); + .map(|p| p.try_fold_with(folder, outer_binder)); Constraints::from_fallible(interner, folded) } } @@ -156,7 +156,7 @@ impl TypeFoldable for Constraints { macro_rules! copy_fold { ($t:ty) => { impl $crate::fold::TypeFoldable for $t { - fn fold_with( + fn try_fold_with( self, _folder: &mut dyn ($crate::fold::FallibleTypeFolder), _outer_binder: DebruijnIndex, @@ -187,7 +187,7 @@ copy_fold!(Safety); macro_rules! id_fold { ($t:ident) => { impl $crate::fold::TypeFoldable for $t { - fn fold_with( + fn try_fold_with( self, _folder: &mut dyn ($crate::fold::FallibleTypeFolder), _outer_binder: DebruijnIndex, @@ -209,30 +209,32 @@ id_fold!(GeneratorId); id_fold!(ForeignDefId); impl TypeSuperFoldable for ProgramClauseData { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> ::std::result::Result { - Ok(ProgramClauseData(self.0.fold_with(folder, outer_binder)?)) + Ok(ProgramClauseData( + self.0.try_fold_with(folder, outer_binder)?, + )) } } impl TypeSuperFoldable for ProgramClause { - fn super_fold_with( + fn try_super_fold_with( self, folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> ::std::result::Result { let clause = self.data(folder.interner()).clone(); Ok(clause - .super_fold_with(folder, outer_binder)? + .try_super_fold_with(folder, outer_binder)? .intern(folder.interner())) } } impl TypeFoldable for PhantomData { - fn fold_with( + fn try_fold_with( self, _folder: &mut dyn FallibleTypeFolder, _outer_binder: DebruijnIndex, diff --git a/chalk-ir/src/fold/shift.rs b/chalk-ir/src/fold/shift.rs index f3fa6082cd0..0f6888c7617 100644 --- a/chalk-ir/src/fold/shift.rs +++ b/chalk-ir/src/fold/shift.rs @@ -29,7 +29,7 @@ impl, I: Interner> Shift for T { } fn shifted_in_from(self, interner: I, source_binder: DebruijnIndex) -> T { - self.fold_with( + self.try_fold_with( &mut Shifter { source_binder, interner, @@ -40,7 +40,7 @@ impl, I: Interner> Shift for T { } fn shifted_out_to(self, interner: I, target_binder: DebruijnIndex) -> Fallible { - self.fold_with( + self.try_fold_with( &mut DownShifter { target_binder, interner, @@ -78,7 +78,7 @@ impl FallibleTypeFolder for Shifter { self } - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -86,7 +86,7 @@ impl FallibleTypeFolder for Shifter { Ok(TyKind::::BoundVar(self.adjust(bound_var, outer_binder)).intern(self.interner())) } - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -97,7 +97,7 @@ impl FallibleTypeFolder for Shifter { ) } - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, @@ -148,7 +148,7 @@ impl FallibleTypeFolder for DownShifter { self } - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -156,7 +156,7 @@ impl FallibleTypeFolder for DownShifter { Ok(TyKind::::BoundVar(self.adjust(bound_var, outer_binder)?).intern(self.interner())) } - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -167,7 +167,7 @@ impl FallibleTypeFolder for DownShifter { ) } - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, diff --git a/chalk-ir/src/fold/subst.rs b/chalk-ir/src/fold/subst.rs index de40f255773..b83943a7483 100644 --- a/chalk-ir/src/fold/subst.rs +++ b/chalk-ir/src/fold/subst.rs @@ -14,7 +14,7 @@ impl Subst<'_, I> { /// Applies the substitution by folding pub fn apply>(interner: I, parameters: &[GenericArg], value: T) -> T { value - .fold_with( + .try_fold_with( &mut Subst { parameters, interner, @@ -51,7 +51,7 @@ impl FallibleTypeFolder for Subst<'_, I> { /// for { [A, u32] } /// ^ represented as `^0.0` /// ``` - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -73,7 +73,7 @@ impl FallibleTypeFolder for Subst<'_, I> { } /// see `fold_free_var_ty` - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -95,7 +95,7 @@ impl FallibleTypeFolder for Subst<'_, I> { } /// see `fold_free_var_ty` - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 39bbdafea45..0f038322dcd 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -2791,7 +2791,7 @@ impl> Substitute for A { T: TypeFoldable, { value - .fold_with( + .try_fold_with( &mut &SubstFolder { interner, subst: self, @@ -2832,7 +2832,7 @@ impl<'i, I: Interner, A: AsParameters> FallibleTypeFolder for &SubstFolder self } - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -2843,7 +2843,7 @@ impl<'i, I: Interner, A: AsParameters> FallibleTypeFolder for &SubstFolder Ok(ty.clone().shifted_in_from(self.interner(), outer_binder)) } - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -2854,7 +2854,7 @@ impl<'i, I: Interner, A: AsParameters> FallibleTypeFolder for &SubstFolder Ok(l.clone().shifted_in_from(self.interner(), outer_binder)) } - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, _ty: Ty, bound_var: BoundVar, diff --git a/chalk-solve/src/clauses/generalize.rs b/chalk-solve/src/clauses/generalize.rs index 05ccfae2f2c..d4ba7085933 100644 --- a/chalk-solve/src/clauses/generalize.rs +++ b/chalk-solve/src/clauses/generalize.rs @@ -31,7 +31,7 @@ impl Generalize { interner, }; let value = value - .fold_with(&mut generalize, DebruijnIndex::INNERMOST) + .try_fold_with(&mut generalize, DebruijnIndex::INNERMOST) .unwrap(); Binders::new( VariableKinds::from_iter(interner, generalize.binders), @@ -47,7 +47,7 @@ impl FallibleTypeFolder for Generalize { self } - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, @@ -62,7 +62,7 @@ impl FallibleTypeFolder for Generalize { Ok(TyKind::BoundVar(new_var).intern(self.interner())) } - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, @@ -82,7 +82,7 @@ impl FallibleTypeFolder for Generalize { .intern(self.interner())) } - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, diff --git a/chalk-solve/src/infer/canonicalize.rs b/chalk-solve/src/infer/canonicalize.rs index d8f3b38fecf..2fb6a5623e9 100644 --- a/chalk-solve/src/infer/canonicalize.rs +++ b/chalk-solve/src/infer/canonicalize.rs @@ -39,7 +39,9 @@ impl InferenceTable { max_universe: UniverseIndex::root(), interner, }; - let value = value.fold_with(&mut q, DebruijnIndex::INNERMOST).unwrap(); + let value = value + .try_fold_with(&mut q, DebruijnIndex::INNERMOST) + .unwrap(); let free_vars = q.free_vars.clone(); Canonicalized { @@ -108,7 +110,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { self } - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -118,7 +120,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { Ok(universe.to_ty(interner)) } - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -128,7 +130,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { Ok(universe.to_lifetime(interner)) } - fn fold_free_placeholder_const( + fn try_fold_free_placeholder_const( &mut self, ty: Ty, universe: PlaceholderIndex, @@ -144,7 +146,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { } #[instrument(level = "debug", skip(self))] - fn fold_inference_ty( + fn try_fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, @@ -157,7 +159,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { debug!("bound to {:?}", ty); Ok(ty .clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in_from(interner, outer_binder)) } None => { @@ -176,7 +178,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { } #[instrument(level = "debug", skip(self))] - fn fold_inference_lifetime( + fn try_fold_inference_lifetime( &mut self, var: InferenceVar, outer_binder: DebruijnIndex, @@ -187,7 +189,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { let l = l.assert_lifetime_ref(interner); debug!("bound to {:?}", l); Ok(l.clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in_from(interner, outer_binder)) } None => { @@ -204,7 +206,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { } #[instrument(level = "debug", skip(self, ty))] - fn fold_inference_const( + fn try_fold_inference_const( &mut self, ty: Ty, var: InferenceVar, @@ -216,7 +218,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { let c = c.assert_const_ref(interner); debug!("bound to {:?}", c); Ok(c.clone() - .fold_with(self, DebruijnIndex::INNERMOST)? + .try_fold_with(self, DebruijnIndex::INNERMOST)? .shifted_in_from(interner, outer_binder)) } None => { @@ -233,7 +235,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { } } - fn fold_lifetime( + fn try_fold_lifetime( &mut self, lifetime: Lifetime, outer_binder: DebruijnIndex, @@ -244,7 +246,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { // inference. We shouldn't see it in canonicalization. panic!("Cannot canonicalize ReEmpty in non-root universe") } - _ => lifetime.super_fold_with(self, outer_binder), + _ => lifetime.try_super_fold_with(self, outer_binder), } } diff --git a/chalk-solve/src/infer/invert.rs b/chalk-solve/src/infer/invert.rs index 6f013c37b38..08114ea484f 100644 --- a/chalk-solve/src/infer/invert.rs +++ b/chalk-solve/src/infer/invert.rs @@ -90,7 +90,7 @@ impl InferenceTable { assert!(quantified.binders.is_empty(interner)); let inverted = quantified .value - .fold_with(&mut Inverter::new(interner, self), DebruijnIndex::INNERMOST) + .try_fold_with(&mut Inverter::new(interner, self), DebruijnIndex::INNERMOST) .unwrap(); Some(inverted) } @@ -134,7 +134,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Inverter<'i, I> { self } - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -148,7 +148,7 @@ impl<'i, I: Interner> FallibleTypeFolder for Inverter<'i, I> { .shifted_in(self.interner())) } - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, diff --git a/chalk-solve/src/infer/ucanonicalize.rs b/chalk-solve/src/infer/ucanonicalize.rs index 20ad5b2a940..506251f26e4 100644 --- a/chalk-solve/src/infer/ucanonicalize.rs +++ b/chalk-solve/src/infer/ucanonicalize.rs @@ -36,7 +36,7 @@ impl InferenceTable { let value1 = value0 .value .clone() - .fold_with( + .try_fold_with( &mut UMapToCanonical { universes: &universes, interner, @@ -169,7 +169,7 @@ impl UniverseMapExt for UniverseMap { let value = canonical_value .value .clone() - .fold_with( + .try_fold_with( &mut UMapFromCanonical { interner, universes: self, @@ -233,7 +233,7 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { true } - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -249,7 +249,7 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { .to_ty(self.interner())) } - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -266,7 +266,7 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { .to_lifetime(self.interner())) } - fn fold_free_placeholder_const( + fn try_fold_free_placeholder_const( &mut self, ty: Ty, universe0: PlaceholderIndex, @@ -301,7 +301,7 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapFromCanonical<'i, I> { self } - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -314,7 +314,7 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapFromCanonical<'i, I> { .to_ty(self.interner())) } - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, diff --git a/chalk-solve/src/infer/unify.rs b/chalk-solve/src/infer/unify.rs index 2c789f1ca90..3c9d617537f 100644 --- a/chalk-solve/src/infer/unify.rs +++ b/chalk-solve/src/infer/unify.rs @@ -876,7 +876,7 @@ impl<'t, I: Interner> Unifier<'t, I> { debug!("trying fold_with on {:?}", ty); let ty1 = ty .clone() - .fold_with( + .try_fold_with( &mut OccursCheck::new(self, var, universe_index), DebruijnIndex::INNERMOST, ) @@ -1133,7 +1133,7 @@ impl<'t, I: Interner> Unifier<'t, I> { // as the variable is unified. let universe_index = self.table.universe_of_unbound_var(var); - let c1 = c.clone().fold_with( + let c1 = c.clone().try_fold_with( &mut OccursCheck::new(self, var, universe_index), DebruijnIndex::INNERMOST, )?; @@ -1253,7 +1253,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { self } - fn fold_free_placeholder_ty( + fn try_fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -1270,7 +1270,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { } } - fn fold_free_placeholder_const( + fn try_fold_free_placeholder_const( &mut self, ty: Ty, universe: PlaceholderIndex, @@ -1285,7 +1285,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { } #[instrument(level = "debug", skip(self))] - fn fold_free_placeholder_lifetime( + fn try_fold_free_placeholder_lifetime( &mut self, ui: PlaceholderIndex, _outer_binder: DebruijnIndex, @@ -1319,7 +1319,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { } } - fn fold_inference_ty( + fn try_fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, @@ -1333,7 +1333,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { let normalized_ty = normalized_ty.assert_ty_ref(interner); let normalized_ty = normalized_ty .clone() - .fold_with(self, DebruijnIndex::INNERMOST)?; + .try_fold_with(self, DebruijnIndex::INNERMOST)?; assert!(!normalized_ty.needs_shift(interner)); Ok(normalized_ty) } @@ -1369,7 +1369,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { } } - fn fold_inference_const( + fn try_fold_inference_const( &mut self, ty: Ty, var: InferenceVar, @@ -1383,7 +1383,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { let normalized_const = normalized_const.assert_const_ref(interner); let normalized_const = normalized_const .clone() - .fold_with(self, DebruijnIndex::INNERMOST)?; + .try_fold_with(self, DebruijnIndex::INNERMOST)?; assert!(!normalized_const.needs_shift(interner)); Ok(normalized_const) } @@ -1415,7 +1415,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { } } - fn fold_inference_lifetime( + fn try_fold_inference_lifetime( &mut self, var: InferenceVar, outer_binder: DebruijnIndex, @@ -1444,7 +1444,7 @@ impl<'i, I: Interner> FallibleTypeFolder for OccursCheck<'_, 'i, I> { InferenceValue::Bound(l) => { let l = l.assert_lifetime_ref(interner); - let l = l.clone().fold_with(self, outer_binder)?; + let l = l.clone().try_fold_with(self, outer_binder)?; assert!(!l.needs_shift(interner)); Ok(l) } From bbcdc797090677fef0a2cce04b2b789af45207ca Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 22 Jun 2022 00:33:28 +0100 Subject: [PATCH 3/6] Add infallible folder --- chalk-ir/src/fold.rs | 305 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) diff --git a/chalk-ir/src/fold.rs b/chalk-ir/src/fold.rs index c44fc79d706..fa8f0c06334 100644 --- a/chalk-ir/src/fold.rs +++ b/chalk-ir/src/fold.rs @@ -1,6 +1,7 @@ //! Traits for transforming bits of IR. use crate::*; +use std::convert::Infallible; use std::fmt::Debug; mod binder_impls; @@ -20,6 +21,11 @@ pub use self::subst::Subst; /// `FallibleTypeFolder`, will reconstruct itself, invoking the folder's /// methods to transform each of the types/lifetimes embedded within. /// +/// As the name suggests, folds performed by `FallibleTypeFolder` can +/// fail (with type `Error`); if the folder cannot fail, consider +/// implementing `TypeFolder` instead (which is an infallible, but +/// otherwise equivalent, trait). +/// /// # Usage patterns /// /// ## Substituting for free variables @@ -316,6 +322,289 @@ pub trait FallibleTypeFolder { fn interner(&self) -> I; } +/// A "folder" is a transformer that can be used to make a copy of +/// some term -- that is, some bit of IR, such as a `Goal` -- with +/// certain changes applied. The idea is that it contains methods that +/// let you swap types/lifetimes for new types/lifetimes; meanwhile, +/// each bit of IR implements the `TypeFoldable` trait which, given a +/// `TypeFolder`, will reconstruct itself, invoking the folder's methods +/// to transform each of the types/lifetimes embedded within. +/// +/// Folds performed by `TypeFolder` cannot fail. If folds might fail, +/// consider implementing `FallibleTypeFolder` instead (which is a +/// fallible, but otherwise equivalent, trait). +/// +/// # Usage patterns +/// +/// ## Substituting for free variables +/// +/// Most of the time, though, we are not interested in adjust +/// arbitrary types/lifetimes, but rather just free variables (even +/// more often, just free existential variables) that appear within +/// the term. +/// +/// For this reason, the `TypeFolder` trait extends two other traits that +/// contain methods that are invoked when just those particular +/// +/// In particular, folders can intercept references to free variables +/// (either existentially or universally quantified) and replace them +/// with other types/lifetimes as appropriate. +/// +/// To create a folder `F`, one never implements `TypeFolder` directly, but instead +/// implements one of each of these three sub-traits: +/// +/// - `FreeVarFolder` -- folds `BoundVar` instances that appear free +/// in the term being folded (use `DefaultFreeVarFolder` to +/// ignore/forbid these altogether) +/// - `InferenceFolder` -- folds existential `InferenceVar` instances +/// that appear in the term being folded (use +/// `DefaultInferenceFolder` to ignore/forbid these altogether) +/// - `PlaceholderFolder` -- folds universal `Placeholder` instances +/// that appear in the term being folded (use +/// `DefaultPlaceholderFolder` to ignore/forbid these altogether) +/// +/// To **apply** a folder, use the `TypeFoldable::fold_with` method, like so +/// +/// ```rust,ignore +/// let x = x.fold_with(&mut folder, 0); +/// ``` +pub trait TypeFolder: FallibleTypeFolder { + /// Creates a `dyn` value from this folder. Unfortunately, this + /// must be added manually to each impl of TypeFolder; it permits the + /// default implements below to create a `&mut dyn TypeFolder` from + /// `Self` without knowing what `Self` is (by invoking this + /// method). Effectively, this limits impls of `TypeFolder` to types + /// for which we are able to create a dyn value (i.e., not `[T]` + /// types). + fn as_dyn(&mut self) -> &mut dyn TypeFolder; + + /// Top-level callback: invoked for each `Ty` that is + /// encountered when folding. By default, invokes + /// `super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `fold_free_var_ty`. + fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty { + ty.super_fold_with(TypeFolder::as_dyn(self), outer_binder) + } + + /// Top-level callback: invoked for each `Lifetime` that is + /// encountered when folding. By default, invokes + /// `super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `fold_free_var_lifetime`. + fn fold_lifetime(&mut self, lifetime: Lifetime, outer_binder: DebruijnIndex) -> Lifetime { + lifetime.super_fold_with(TypeFolder::as_dyn(self), outer_binder) + } + + /// Top-level callback: invoked for each `Const` that is + /// encountered when folding. By default, invokes + /// `super_fold_with`, which will in turn invoke the more + /// specialized folding methods below, like `fold_free_var_const`. + fn fold_const(&mut self, constant: Const, outer_binder: DebruijnIndex) -> Const { + constant.super_fold_with(TypeFolder::as_dyn(self), outer_binder) + } + + /// Invoked for every program clause. By default, recursively folds the goals contents. + fn fold_program_clause( + &mut self, + clause: ProgramClause, + outer_binder: DebruijnIndex, + ) -> ProgramClause { + clause.super_fold_with(TypeFolder::as_dyn(self), outer_binder) + } + + /// Invoked for every goal. By default, recursively folds the goals contents. + fn fold_goal(&mut self, goal: Goal, outer_binder: DebruijnIndex) -> Goal { + goal.super_fold_with(TypeFolder::as_dyn(self), outer_binder) + } + + /// If overridden to return true, then folding will panic if a + /// free variable is encountered. This should be done if free + /// type/lifetime variables are not expected. + fn forbid_free_vars(&self) -> bool { + false + } + + /// Invoked for `TyKind::BoundVar` instances that are not bound + /// within the type being folded over: + /// + /// - `depth` is the depth of the `TyKind::BoundVar`; this has + /// been adjusted to account for binders in scope. + /// - `binders` is the number of binders in scope. + /// + /// This should return a type suitable for a context with + /// `binders` in scope. + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { + if TypeFolder::forbid_free_vars(self) { + panic!( + "unexpected free variable with depth `{:?}` with outer binder {:?}", + bound_var, outer_binder + ) + } else { + let bound_var = bound_var.shifted_in_from(outer_binder); + TyKind::::BoundVar(bound_var).intern(TypeFolder::interner(self)) + } + } + + /// As `fold_free_var_ty`, but for lifetimes. + fn fold_free_var_lifetime( + &mut self, + bound_var: BoundVar, + outer_binder: DebruijnIndex, + ) -> Lifetime { + if TypeFolder::forbid_free_vars(self) { + panic!( + "unexpected free variable with depth `{:?}` with outer binder {:?}", + bound_var, outer_binder + ) + } else { + let bound_var = bound_var.shifted_in_from(outer_binder); + LifetimeData::::BoundVar(bound_var).intern(TypeFolder::interner(self)) + } + } + + /// As `fold_free_var_ty`, but for constants. + fn fold_free_var_const( + &mut self, + ty: Ty, + bound_var: BoundVar, + outer_binder: DebruijnIndex, + ) -> Const { + if TypeFolder::forbid_free_vars(self) { + panic!( + "unexpected free variable with depth `{:?}` with outer binder {:?}", + bound_var, outer_binder + ) + } else { + let bound_var = bound_var.shifted_in_from(outer_binder); + ConstData { + ty: ty.fold_with(TypeFolder::as_dyn(self), outer_binder), + value: ConstValue::::BoundVar(bound_var), + } + .intern(TypeFolder::interner(self)) + } + } + + /// If overridden to return true, we will panic when a free + /// placeholder type/lifetime/const is encountered. + fn forbid_free_placeholders(&self) -> bool { + false + } + + /// Invoked for each occurrence of a placeholder type; these are + /// used when we instantiate binders universally. Returns a type + /// to use instead, which should be suitably shifted to account + /// for `binders`. + /// + /// - `universe` is the universe of the `TypeName::ForAll` that was found + /// - `binders` is the number of binders in scope + #[allow(unused_variables)] + fn fold_free_placeholder_ty( + &mut self, + universe: PlaceholderIndex, + outer_binder: DebruijnIndex, + ) -> Ty { + if TypeFolder::forbid_free_placeholders(self) { + panic!("unexpected placeholder type `{:?}`", universe) + } else { + universe.to_ty::(TypeFolder::interner(self)) + } + } + + /// As with `fold_free_placeholder_ty`, but for lifetimes. + #[allow(unused_variables)] + fn fold_free_placeholder_lifetime( + &mut self, + universe: PlaceholderIndex, + outer_binder: DebruijnIndex, + ) -> Lifetime { + if TypeFolder::forbid_free_placeholders(self) { + panic!("unexpected placeholder lifetime `{:?}`", universe) + } else { + universe.to_lifetime(TypeFolder::interner(self)) + } + } + + /// As with `fold_free_placeholder_ty`, but for constants. + #[allow(unused_variables)] + fn fold_free_placeholder_const( + &mut self, + ty: Ty, + universe: PlaceholderIndex, + outer_binder: DebruijnIndex, + ) -> Const { + if TypeFolder::forbid_free_placeholders(self) { + panic!("unexpected placeholder const `{:?}`", universe) + } else { + universe.to_const( + TypeFolder::interner(self), + ty.fold_with(TypeFolder::as_dyn(self), outer_binder), + ) + } + } + + /// If overridden to return true, inference variables will trigger + /// panics when folded. Used when inference variables are + /// unexpected. + fn forbid_inference_vars(&self) -> bool { + false + } + + /// Invoked for each occurrence of a inference type; these are + /// used when we instantiate binders universally. Returns a type + /// to use instead, which should be suitably shifted to account + /// for `binders`. + /// + /// - `universe` is the universe of the `TypeName::ForAll` that was found + /// - `binders` is the number of binders in scope + #[allow(unused_variables)] + fn fold_inference_ty( + &mut self, + var: InferenceVar, + kind: TyVariableKind, + outer_binder: DebruijnIndex, + ) -> Ty { + if TypeFolder::forbid_inference_vars(self) { + panic!("unexpected inference type `{:?}`", var) + } else { + var.to_ty(TypeFolder::interner(self), kind) + } + } + + /// As with `fold_inference_ty`, but for lifetimes. + #[allow(unused_variables)] + fn fold_inference_lifetime( + &mut self, + var: InferenceVar, + outer_binder: DebruijnIndex, + ) -> Lifetime { + if TypeFolder::forbid_inference_vars(self) { + panic!("unexpected inference lifetime `'{:?}`", var) + } else { + var.to_lifetime(TypeFolder::interner(self)) + } + } + + /// As with `fold_inference_ty`, but for constants. + #[allow(unused_variables)] + fn fold_inference_const( + &mut self, + ty: Ty, + var: InferenceVar, + outer_binder: DebruijnIndex, + ) -> Const { + if TypeFolder::forbid_inference_vars(self) { + panic!("unexpected inference const `{:?}`", var) + } else { + var.to_const( + TypeFolder::interner(self), + ty.fold_with(TypeFolder::as_dyn(self), outer_binder), + ) + } + } + + /// Gets the interner that is being folded from. + fn interner(&self) -> I; +} + /// Applies the given `TypeFolder` to a value, producing a folded result /// of type `Self::Result`. The result type is typically the same as /// the source type, but in some cases we convert from borrowed @@ -332,6 +621,14 @@ pub trait TypeFoldable: Debug + Sized { folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result; + + /// A convenient alternative to `try_fold_with` for use with infallible + /// folders. Do not override this method, to ensure coherence with + /// `try_fold_with`. + fn fold_with(self, folder: &mut dyn TypeFolder, outer_binder: DebruijnIndex) -> Self { + self.try_fold_with(FallibleTypeFolder::as_dyn(folder), outer_binder) + .unwrap() + } } /// For types where "fold" invokes a callback on the `TypeFolder`, the @@ -344,6 +641,14 @@ pub trait TypeSuperFoldable: TypeFoldable { folder: &mut dyn FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result; + + /// A convenient alternative to `try_super_fold_with` for use with + /// infallible folders. Do not override this method, to ensure coherence + /// with `try_super_fold_with`. + fn super_fold_with(self, folder: &mut dyn TypeFolder, outer_binder: DebruijnIndex) -> Self { + self.try_super_fold_with(FallibleTypeFolder::as_dyn(folder), outer_binder) + .unwrap() + } } /// "Folding" a type invokes the `try_fold_ty` method on the folder; this From 48f1cfc94213f8b244d1dcc6015753f346ec8152 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 22 Jun 2022 09:33:16 +0100 Subject: [PATCH 4/6] derive(FallibleTypeFolder) for infallible folders --- chalk-derive/src/lib.rs | 148 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/chalk-derive/src/lib.rs b/chalk-derive/src/lib.rs index 77709b27726..a64fd90aa8a 100644 --- a/chalk-derive/src/lib.rs +++ b/chalk-derive/src/lib.rs @@ -117,6 +117,7 @@ enum DeriveKind { FromInterner, } +decl_derive!([FallibleTypeFolder, attributes(has_interner)] => derive_fallible_type_folder); decl_derive!([HasInterner, attributes(has_interner)] => derive_has_interner); decl_derive!([TypeVisitable, attributes(has_interner)] => derive_type_visitable); decl_derive!([TypeSuperVisitable, attributes(has_interner)] => derive_type_super_visitable); @@ -295,3 +296,150 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { }, ) } + +fn derive_fallible_type_folder(mut s: synstructure::Structure) -> TokenStream { + let (interner, _) = find_interner(&mut s); + s.underscore_const(true); + s.unbound_impl( + quote!(::chalk_ir::fold::FallibleTypeFolder<#interner>), + quote! { + type Error = ::core::convert::Infallible; + + fn as_dyn(&mut self) -> &mut dyn ::chalk_ir::fold::FallibleTypeFolder { + self + } + + fn try_fold_ty( + &mut self, + ty: ::chalk_ir::Ty<#interner>, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Ty<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_ty(self, ty, outer_binder)) + } + + fn try_fold_lifetime( + &mut self, + lifetime: ::chalk_ir::Lifetime<#interner>, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Lifetime<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_lifetime(self, lifetime, outer_binder)) + } + + fn try_fold_const( + &mut self, + constant: ::chalk_ir::Const<#interner>, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Const<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_const(self, constant, outer_binder)) + } + + fn try_fold_program_clause( + &mut self, + clause: ::chalk_ir::ProgramClause<#interner>, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::ProgramClause<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_program_clause(self, clause, outer_binder)) + } + + fn try_fold_goal( + &mut self, + goal: ::chalk_ir::Goal<#interner>, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Goal<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_goal(self, goal, outer_binder)) + } + + fn forbid_free_vars(&self) -> bool { + ::chalk_ir::fold::TypeFolder::forbid_free_vars(self) + } + + fn try_fold_free_var_ty( + &mut self, + bound_var: ::chalk_ir::BoundVar, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Ty<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_var_ty(self, bound_var, outer_binder)) + } + + fn try_fold_free_var_lifetime( + &mut self, + bound_var: ::chalk_ir::BoundVar, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Lifetime<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_var_lifetime(self, bound_var, outer_binder)) + } + + fn try_fold_free_var_const( + &mut self, + ty: ::chalk_ir::Ty<#interner>, + bound_var: ::chalk_ir::BoundVar, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Const<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_var_const(self, ty, bound_var, outer_binder)) + } + + fn forbid_free_placeholders(&self) -> bool { + ::chalk_ir::fold::TypeFolder::forbid_free_placeholders(self) + } + + fn try_fold_free_placeholder_ty( + &mut self, + universe: ::chalk_ir::PlaceholderIndex, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Ty<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_placeholder_ty(self, universe, outer_binder)) + } + + fn try_fold_free_placeholder_lifetime( + &mut self, + universe: ::chalk_ir::PlaceholderIndex, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Lifetime<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_placeholder_lifetime(self, universe, outer_binder)) + } + + fn try_fold_free_placeholder_const( + &mut self, + ty: ::chalk_ir::Ty<#interner>, + universe: ::chalk_ir::PlaceholderIndex, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Const<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_free_placeholder_const(self, ty, universe, outer_binder)) + } + + fn forbid_inference_vars(&self) -> bool { + ::chalk_ir::fold::TypeFolder::forbid_inference_vars(self) + } + + fn try_fold_inference_ty( + &mut self, + var: ::chalk_ir::InferenceVar, + kind: ::chalk_ir::TyVariableKind, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Ty<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_inference_ty(self, var, kind, outer_binder)) + } + + fn try_fold_inference_lifetime( + &mut self, + var: ::chalk_ir::InferenceVar, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Lifetime<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_inference_lifetime(self, var, outer_binder)) + } + + fn try_fold_inference_const( + &mut self, + ty: ::chalk_ir::Ty<#interner>, + var: ::chalk_ir::InferenceVar, + outer_binder: ::chalk_ir::DebruijnIndex, + ) -> ::core::result::Result<::chalk_ir::Const<#interner>, Self::Error> { + ::core::result::Result::Ok(::chalk_ir::fold::TypeFolder::fold_inference_const(self, ty, var, outer_binder)) + } + + fn interner(&self) -> #interner { + ::chalk_ir::fold::TypeFolder::interner(self) + } + }, + ) +} From 5b9c408ad222201ab2ef50191ecb4bf7b419fbe0 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 22 Jun 2022 09:30:30 +0100 Subject: [PATCH 5/6] Support deriving on more types --- chalk-derive/src/lib.rs | 136 +++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 64 deletions(-) diff --git a/chalk-derive/src/lib.rs b/chalk-derive/src/lib.rs index a64fd90aa8a..00035aea7ae 100644 --- a/chalk-derive/src/lib.rs +++ b/chalk-derive/src/lib.rs @@ -3,17 +3,17 @@ extern crate proc_macro; use proc_macro2::{Span, TokenStream}; use quote::quote; use quote::ToTokens; -use syn::{parse_quote, DeriveInput, GenericParam, Ident, TypeParamBound}; +use syn::{parse_quote, DeriveInput, Ident, TypeParam, TypeParamBound}; use synstructure::decl_derive; /// Checks whether a generic parameter has a `: HasInterner` bound -fn has_interner(param: &GenericParam) -> Option<&Ident> { +fn has_interner(param: &TypeParam) -> Option<&Ident> { bounded_by_trait(param, "HasInterner") } /// Checks whether a generic parameter has a `: Interner` bound -fn is_interner(param: &GenericParam) -> Option<&Ident> { +fn is_interner(param: &TypeParam) -> Option<&Ident> { bounded_by_trait(param, "Interner") } @@ -28,48 +28,44 @@ fn has_interner_attr(input: &DeriveInput) -> Option { ) } -fn bounded_by_trait<'p>(param: &'p GenericParam, name: &str) -> Option<&'p Ident> { +fn bounded_by_trait<'p>(param: &'p TypeParam, name: &str) -> Option<&'p Ident> { let name = Some(String::from(name)); - match param { - GenericParam::Type(ref t) => t.bounds.iter().find_map(|b| { - if let TypeParamBound::Trait(trait_bound) = b { - if trait_bound - .path - .segments - .last() - .map(|s| s.ident.to_string()) - == name - { - return Some(&t.ident); - } + param.bounds.iter().find_map(|b| { + if let TypeParamBound::Trait(trait_bound) = b { + if trait_bound + .path + .segments + .last() + .map(|s| s.ident.to_string()) + == name + { + return Some(¶m.ident); } - None - }), - _ => None, - } + } + None + }) } -fn get_generic_param(input: &DeriveInput) -> &GenericParam { - match input.generics.params.len() { - 1 => {} +fn get_intern_param(input: &DeriveInput) -> Option<(DeriveKind, &Ident)> { + let mut params = input.generics.type_params().filter_map(|param| { + has_interner(param) + .map(|ident| (DeriveKind::FromHasInterner, ident)) + .or_else(|| is_interner(param).map(|ident| (DeriveKind::FromInterner, ident))) + }); - 0 => panic!( - "deriving this trait requires a single type parameter or a `#[has_interner]` attr" - ), + let param = params.next(); + assert!(params.next().is_none(), "deriving this trait only works with at most one type parameter that implements HasInterner or Interner"); - _ => panic!("deriving this trait only works with a single type parameter"), - }; - &input.generics.params[0] + param } -fn get_generic_param_name(input: &DeriveInput) -> Option<&Ident> { - match get_generic_param(input) { - GenericParam::Type(t) => Some(&t.ident), - _ => None, - } +fn get_intern_param_name(input: &DeriveInput) -> &Ident { + get_intern_param(input) + .expect("deriving this trait requires a parameter that implements HasInterner or Interner") + .1 } -fn find_interner(s: &mut synstructure::Structure) -> (TokenStream, DeriveKind) { +fn try_find_interner(s: &mut synstructure::Structure) -> Option<(TokenStream, DeriveKind)> { let input = s.ast(); if let Some(arg) = has_interner_attr(input) { @@ -79,35 +75,40 @@ fn find_interner(s: &mut synstructure::Structure) -> (TokenStream, DeriveKind) { // struct S { // // } - return (arg, DeriveKind::FromHasInternerAttr); + return Some((arg, DeriveKind::FromHasInternerAttr)); } - let generic_param0 = get_generic_param(input); - - if let Some(param) = has_interner(generic_param0) { - // HasInterner bound: - // - // Example: - // - // struct Binders { } - s.add_impl_generic(parse_quote! { _I }); - - s.add_where_predicate(parse_quote! { _I: ::chalk_ir::interner::Interner }); - s.add_where_predicate( - parse_quote! { #param: ::chalk_ir::interner::HasInterner }, - ); + get_intern_param(input).map(|generic_param0| match generic_param0 { + (DeriveKind::FromHasInterner, param) => { + // HasInterner bound: + // + // Example: + // + // struct Binders { } + s.add_impl_generic(parse_quote! { _I }); + + s.add_where_predicate(parse_quote! { _I: ::chalk_ir::interner::Interner }); + s.add_where_predicate( + parse_quote! { #param: ::chalk_ir::interner::HasInterner }, + ); + + (quote! { _I }, DeriveKind::FromHasInterner) + } + (DeriveKind::FromInterner, i) => { + // Interner bound: + // + // Example: + // + // struct Foo { } + (quote! { #i }, DeriveKind::FromInterner) + } + _ => unreachable!(), + }) +} - (quote! { _I }, DeriveKind::FromHasInterner) - } else if let Some(i) = is_interner(generic_param0) { - // Interner bound: - // - // Example: - // - // struct Foo { } - (quote! { #i }, DeriveKind::FromInterner) - } else { - panic!("deriving this trait requires a parameter that implements HasInterner or Interner",); - } +fn find_interner(s: &mut synstructure::Structure) -> (TokenStream, DeriveKind) { + try_find_interner(s) + .expect("deriving this trait requires a `#[has_interner]` attr or a parameter that implements HasInterner or Interner") } #[derive(Copy, Clone, PartialEq)] @@ -174,7 +175,7 @@ fn derive_any_type_visitable( }); if kind == DeriveKind::FromHasInterner { - let param = get_generic_param_name(input).unwrap(); + let param = get_intern_param_name(input); s.add_where_predicate(parse_quote! { #param: ::chalk_ir::visit::TypeVisitable<#interner> }); } @@ -278,7 +279,7 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { let input = s.ast(); if kind == DeriveKind::FromHasInterner { - let param = get_generic_param_name(input).unwrap(); + let param = get_intern_param_name(input); s.add_where_predicate(parse_quote! { #param: ::chalk_ir::fold::TypeFoldable<#interner> }); }; @@ -298,7 +299,14 @@ fn derive_type_foldable(mut s: synstructure::Structure) -> TokenStream { } fn derive_fallible_type_folder(mut s: synstructure::Structure) -> TokenStream { - let (interner, _) = find_interner(&mut s); + let interner = try_find_interner(&mut s).map_or_else( + || { + s.add_impl_generic(parse_quote! { _I }); + s.add_where_predicate(parse_quote! { _I: ::chalk_ir::interner::Interner }); + quote! { _I } + }, + |(interner, _)| interner, + ); s.underscore_const(true); s.unbound_impl( quote!(::chalk_ir::fold::FallibleTypeFolder<#interner>), From 994bc59222a1c8e74728757666df89d30bc44b35 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 22 Jun 2022 09:15:34 +0100 Subject: [PATCH 6/6] Convert non-failing fallible folders to infallible --- chalk-engine/src/normalize_deep.rs | 46 +++++++-------- chalk-ir/src/fold/shift.rs | 40 ++++++------- chalk-ir/src/fold/subst.rs | 57 +++++++++---------- chalk-ir/src/lib.rs | 44 +++++++-------- chalk-solve/src/clauses/generalize.rs | 36 ++++++------ chalk-solve/src/infer/canonicalize.rs | 78 ++++++++++++-------------- chalk-solve/src/infer/invert.rs | 32 +++++------ chalk-solve/src/infer/ucanonicalize.rs | 61 ++++++++++---------- 8 files changed, 183 insertions(+), 211 deletions(-) diff --git a/chalk-engine/src/normalize_deep.rs b/chalk-engine/src/normalize_deep.rs index 2b8be951510..9f36f3ce526 100644 --- a/chalk-engine/src/normalize_deep.rs +++ b/chalk-engine/src/normalize_deep.rs @@ -1,9 +1,11 @@ +use chalk_derive::FallibleTypeFolder; use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; +use chalk_ir::fold::{TypeFoldable, TypeFolder}; use chalk_ir::interner::Interner; use chalk_ir::*; use chalk_solve::infer::InferenceTable; +#[derive(FallibleTypeFolder)] pub(crate) struct DeepNormalizer<'table, I: Interner> { table: &'table mut InferenceTable, interner: I, @@ -35,64 +37,62 @@ impl DeepNormalizer<'_, I> { } } -impl FallibleTypeFolder for DeepNormalizer<'_, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl TypeFolder for DeepNormalizer<'_, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_inference_ty( + fn fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let interner = self.interner; match self.table.probe_var(var) { - Some(ty) => Ok(ty + Some(ty) => ty .assert_ty_ref(interner) .clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in(interner)), // FIXME shift + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in(interner), // FIXME shift None => { // Normalize all inference vars which have been unified into a // single variable. Ena calls this the "root" variable. - Ok(self.table.inference_var_root(var).to_ty(interner, kind)) + self.table.inference_var_root(var).to_ty(interner, kind) } } } - fn try_fold_inference_lifetime( + fn fold_inference_lifetime( &mut self, var: InferenceVar, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let interner = self.interner; match self.table.probe_var(var) { - Some(l) => Ok(l + Some(l) => l .assert_lifetime_ref(interner) .clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in(interner)), - None => Ok(var.to_lifetime(interner)), // FIXME shift + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in(interner), + None => var.to_lifetime(interner), // FIXME shift } } - fn try_fold_inference_const( + fn fold_inference_const( &mut self, ty: Ty, var: InferenceVar, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { let interner = self.interner; match self.table.probe_var(var) { - Some(c) => Ok(c + Some(c) => c .assert_const_ref(interner) .clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in(interner)), - None => Ok(var.to_const(interner, ty)), // FIXME shift + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in(interner), + None => var.to_const(interner, ty), // FIXME shift } } diff --git a/chalk-ir/src/fold/shift.rs b/chalk-ir/src/fold/shift.rs index 0f6888c7617..f7e5e4a4abd 100644 --- a/chalk-ir/src/fold/shift.rs +++ b/chalk-ir/src/fold/shift.rs @@ -1,6 +1,5 @@ //! Shifting of debruijn indices -use super::TypeFoldable; use crate::*; /// Methods for converting debruijn indices to move values into or out @@ -55,12 +54,13 @@ impl, I: Interner> Shift for T { } /// A folder that adjusts debruijn indices by a certain amount. -struct Shifter { +#[derive(FallibleTypeFolder)] +struct Shifter { source_binder: DebruijnIndex, interner: I, } -impl Shifter { +impl Shifter { /// Given a free variable at `depth`, shifts that depth to `depth /// + self.adjustment`, and then wraps *that* within the internal /// set `binders`. @@ -71,42 +71,34 @@ impl Shifter { } } -impl FallibleTypeFolder for Shifter { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl TypeFolder for Shifter { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible> { - Ok(TyKind::::BoundVar(self.adjust(bound_var, outer_binder)).intern(self.interner())) + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { + TyKind::::BoundVar(self.adjust(bound_var, outer_binder)) + .intern(TypeFolder::interner(self)) } - fn try_fold_free_var_lifetime( + fn fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { - Ok( - LifetimeData::::BoundVar(self.adjust(bound_var, outer_binder)) - .intern(self.interner()), - ) + ) -> Lifetime { + LifetimeData::::BoundVar(self.adjust(bound_var, outer_binder)) + .intern(TypeFolder::interner(self)) } - fn try_fold_free_var_const( + fn fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { // const types don't have free variables, so we can skip folding `ty` - Ok(self - .adjust(bound_var, outer_binder) - .to_const(self.interner(), ty)) + self.adjust(bound_var, outer_binder) + .to_const(TypeFolder::interner(self), ty) } fn interner(&self) -> I { diff --git a/chalk-ir/src/fold/subst.rs b/chalk-ir/src/fold/subst.rs index b83943a7483..7cff8d89c91 100644 --- a/chalk-ir/src/fold/subst.rs +++ b/chalk-ir/src/fold/subst.rs @@ -2,6 +2,7 @@ use super::*; use crate::fold::shift::Shift; /// Substitution used during folding +#[derive(FallibleTypeFolder)] pub struct Subst<'s, I: Interner> { /// Values to substitute. A reference to a free variable with /// index `i` will be mapped to `parameters[i]` -- if `i > @@ -25,10 +26,8 @@ impl Subst<'_, I> { } } -impl FallibleTypeFolder for Subst<'_, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl TypeFolder for Subst<'_, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -51,69 +50,65 @@ impl FallibleTypeFolder for Subst<'_, I> { /// for { [A, u32] } /// ^ represented as `^0.0` /// ``` - fn try_fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible> { + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { if let Some(index) = bound_var.index_if_innermost() { - match self.parameters[index].data(self.interner()) { - GenericArgData::Ty(t) => { - Ok(t.clone().shifted_in_from(self.interner(), outer_binder)) - } + match self.parameters[index].data(TypeFolder::interner(self)) { + GenericArgData::Ty(t) => t + .clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder), _ => panic!("mismatched kinds in substitution"), } } else { - Ok(bound_var + bound_var .shifted_out() .expect("cannot fail because this is not the innermost") .shifted_in_from(outer_binder) - .to_ty(self.interner())) + .to_ty(TypeFolder::interner(self)) } } /// see `fold_free_var_ty` - fn try_fold_free_var_lifetime( + fn fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { if let Some(index) = bound_var.index_if_innermost() { - match self.parameters[index].data(self.interner()) { - GenericArgData::Lifetime(l) => { - Ok(l.clone().shifted_in_from(self.interner(), outer_binder)) - } + match self.parameters[index].data(TypeFolder::interner(self)) { + GenericArgData::Lifetime(l) => l + .clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder), _ => panic!("mismatched kinds in substitution"), } } else { - Ok(bound_var + bound_var .shifted_out() .unwrap() .shifted_in_from(outer_binder) - .to_lifetime(self.interner())) + .to_lifetime(TypeFolder::interner(self)) } } /// see `fold_free_var_ty` - fn try_fold_free_var_const( + fn fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { if let Some(index) = bound_var.index_if_innermost() { - match self.parameters[index].data(self.interner()) { - GenericArgData::Const(c) => { - Ok(c.clone().shifted_in_from(self.interner(), outer_binder)) - } + match self.parameters[index].data(TypeFolder::interner(self)) { + GenericArgData::Const(c) => c + .clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder), _ => panic!("mismatched kinds in substitution"), } } else { - Ok(bound_var + bound_var .shifted_out() .unwrap() .shifted_in_from(outer_binder) - .to_const(self.interner(), ty)) + .to_const(TypeFolder::interner(self), ty) } } diff --git a/chalk-ir/src/lib.rs b/chalk-ir/src/lib.rs index 0f038322dcd..b40ac3f5259 100644 --- a/chalk-ir/src/lib.rs +++ b/chalk-ir/src/lib.rs @@ -8,9 +8,11 @@ extern crate self as chalk_ir; use crate::cast::{Cast, CastTo, Caster}; use crate::fold::shift::Shift; -use crate::fold::{FallibleTypeFolder, Subst, TypeFoldable, TypeSuperFoldable}; +use crate::fold::{FallibleTypeFolder, Subst, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor, VisitExt}; -use chalk_derive::{HasInterner, TypeFoldable, TypeSuperVisitable, TypeVisitable, Zip}; +use chalk_derive::{ + FallibleTypeFolder, HasInterner, TypeFoldable, TypeSuperVisitable, TypeVisitable, Zip, +}; use std::marker::PhantomData; use std::ops::ControlFlow; @@ -2725,6 +2727,7 @@ impl Substitution { } } +#[derive(FallibleTypeFolder)] struct SubstFolder<'i, I: Interner, A: AsParameters> { interner: I, subst: &'i A, @@ -2792,7 +2795,7 @@ impl> Substitute for A { { value .try_fold_with( - &mut &SubstFolder { + &mut SubstFolder { interner, subst: self, }, @@ -2825,45 +2828,42 @@ impl<'a, I: Interner> ToGenericArg for (usize, &'a VariableKind) { } } -impl<'i, I: Interner, A: AsParameters> FallibleTypeFolder for &SubstFolder<'i, I, A> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl<'i, I: Interner, A: AsParameters> TypeFolder for SubstFolder<'i, I, A> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible> { + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); let ty = self.at(bound_var.index); - let ty = ty.assert_ty_ref(self.interner()); - Ok(ty.clone().shifted_in_from(self.interner(), outer_binder)) + let ty = ty.assert_ty_ref(TypeFolder::interner(self)); + ty.clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder) } - fn try_fold_free_var_lifetime( + fn fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); let l = self.at(bound_var.index); - let l = l.assert_lifetime_ref(self.interner()); - Ok(l.clone().shifted_in_from(self.interner(), outer_binder)) + let l = l.assert_lifetime_ref(TypeFolder::interner(self)); + l.clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder) } - fn try_fold_free_var_const( + fn fold_free_var_const( &mut self, _ty: Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { assert_eq!(bound_var.debruijn, DebruijnIndex::INNERMOST); let c = self.at(bound_var.index); - let c = c.assert_const_ref(self.interner()); - Ok(c.clone().shifted_in_from(self.interner(), outer_binder)) + let c = c.assert_const_ref(TypeFolder::interner(self)); + c.clone() + .shifted_in_from(TypeFolder::interner(self), outer_binder) } fn interner(&self) -> I { diff --git a/chalk-solve/src/clauses/generalize.rs b/chalk-solve/src/clauses/generalize.rs index d4ba7085933..bff05b36995 100644 --- a/chalk-solve/src/clauses/generalize.rs +++ b/chalk-solve/src/clauses/generalize.rs @@ -6,14 +6,16 @@ //! happen with `dyn Trait` currently; that's the only case where we use the //! types passed to `program_clauses` in the clauses we generate. +use chalk_derive::FallibleTypeFolder; use chalk_ir::{ - fold::{FallibleTypeFolder, TypeFoldable}, + fold::{TypeFoldable, TypeFolder}, interner::{HasInterner, Interner}, - Binders, BoundVar, Const, ConstData, ConstValue, DebruijnIndex, Fallible, Lifetime, - LifetimeData, NoSolution, Ty, TyKind, TyVariableKind, VariableKind, VariableKinds, + Binders, BoundVar, Const, ConstData, ConstValue, DebruijnIndex, Lifetime, LifetimeData, Ty, + TyKind, TyVariableKind, VariableKind, VariableKinds, }; use rustc_hash::FxHashMap; +#[derive(FallibleTypeFolder)] pub struct Generalize { binders: Vec>, mapping: FxHashMap, @@ -40,18 +42,12 @@ impl Generalize { } } -impl FallibleTypeFolder for Generalize { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl TypeFolder for Generalize { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible> { + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { let binder_vec = &mut self.binders; let new_index = self.mapping.entry(bound_var).or_insert_with(|| { let i = binder_vec.len(); @@ -59,15 +55,15 @@ impl FallibleTypeFolder for Generalize { i }); let new_var = BoundVar::new(outer_binder, *new_index); - Ok(TyKind::BoundVar(new_var).intern(self.interner())) + TyKind::BoundVar(new_var).intern(TypeFolder::interner(self)) } - fn try_fold_free_var_const( + fn fold_free_var_const( &mut self, ty: Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { let binder_vec = &mut self.binders; let new_index = self.mapping.entry(bound_var).or_insert_with(|| { let i = binder_vec.len(); @@ -75,18 +71,18 @@ impl FallibleTypeFolder for Generalize { i }); let new_var = BoundVar::new(outer_binder, *new_index); - Ok(ConstData { + ConstData { ty, value: ConstValue::BoundVar(new_var), } - .intern(self.interner())) + .intern(TypeFolder::interner(self)) } - fn try_fold_free_var_lifetime( + fn fold_free_var_lifetime( &mut self, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let binder_vec = &mut self.binders; let new_index = self.mapping.entry(bound_var).or_insert_with(|| { let i = binder_vec.len(); @@ -94,7 +90,7 @@ impl FallibleTypeFolder for Generalize { i }); let new_var = BoundVar::new(outer_binder, *new_index); - Ok(LifetimeData::BoundVar(new_var).intern(self.interner())) + LifetimeData::BoundVar(new_var).intern(TypeFolder::interner(self)) } fn interner(&self) -> I { diff --git a/chalk-solve/src/infer/canonicalize.rs b/chalk-solve/src/infer/canonicalize.rs index 2fb6a5623e9..56fe88a5630 100644 --- a/chalk-solve/src/infer/canonicalize.rs +++ b/chalk-solve/src/infer/canonicalize.rs @@ -1,6 +1,7 @@ use crate::debug_span; +use chalk_derive::FallibleTypeFolder; use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; +use chalk_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use chalk_ir::interner::{HasInterner, Interner}; use chalk_ir::*; use std::cmp::max; @@ -63,6 +64,7 @@ pub struct Canonicalized { pub free_vars: Vec>, } +#[derive(FallibleTypeFolder)] struct Canonicalizer<'q, I: Interner> { table: &'q mut InferenceTable, free_vars: Vec>, @@ -103,42 +105,40 @@ impl<'q, I: Interner> Canonicalizer<'q, I> { } } -impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl<'i, I: Interner> TypeFolder for Canonicalizer<'i, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_placeholder_ty( + fn fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let interner = self.interner; self.max_universe = max(self.max_universe, universe.ui); - Ok(universe.to_ty(interner)) + universe.to_ty(interner) } - fn try_fold_free_placeholder_lifetime( + fn fold_free_placeholder_lifetime( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let interner = self.interner; self.max_universe = max(self.max_universe, universe.ui); - Ok(universe.to_lifetime(interner)) + universe.to_lifetime(interner) } - fn try_fold_free_placeholder_const( + fn fold_free_placeholder_const( &mut self, ty: Ty, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { let interner = self.interner; self.max_universe = max(self.max_universe, universe.ui); - Ok(universe.to_const(interner, ty)) + universe.to_const(interner, ty) } fn forbid_free_vars(&self) -> bool { @@ -146,21 +146,20 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { } #[instrument(level = "debug", skip(self))] - fn try_fold_inference_ty( + fn fold_inference_ty( &mut self, var: InferenceVar, kind: TyVariableKind, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let interner = self.interner; match self.table.probe_var(var) { Some(ty) => { let ty = ty.assert_ty_ref(interner); debug!("bound to {:?}", ty); - Ok(ty - .clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in_from(interner, outer_binder)) + ty.clone() + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in_from(interner, outer_binder) } None => { // If this variable is not yet bound, find its @@ -172,54 +171,51 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var)); debug!(position=?bound_var, "not yet unified"); - Ok(TyKind::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner)) + TyKind::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner) } } } #[instrument(level = "debug", skip(self))] - fn try_fold_inference_lifetime( + fn fold_inference_lifetime( &mut self, var: InferenceVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let interner = self.interner; match self.table.probe_var(var) { Some(l) => { let l = l.assert_lifetime_ref(interner); debug!("bound to {:?}", l); - Ok(l.clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in_from(interner, outer_binder)) + l.clone() + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in_from(interner, outer_binder) } None => { let free_var = ParameterEnaVariable::new(VariableKind::Lifetime, self.table.unify.find(var)); let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var)); debug!(position=?bound_var, "not yet unified"); - Ok( - LifetimeData::BoundVar(bound_var.shifted_in_from(outer_binder)) - .intern(interner), - ) + LifetimeData::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner) } } } #[instrument(level = "debug", skip(self, ty))] - fn try_fold_inference_const( + fn fold_inference_const( &mut self, ty: Ty, var: InferenceVar, outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { let interner = self.interner; match self.table.probe_var(var) { Some(c) => { let c = c.assert_const_ref(interner); debug!("bound to {:?}", c); - Ok(c.clone() - .try_fold_with(self, DebruijnIndex::INNERMOST)? - .shifted_in_from(interner, outer_binder)) + c.clone() + .fold_with(self, DebruijnIndex::INNERMOST) + .shifted_in_from(interner, outer_binder) } None => { let free_var = ParameterEnaVariable::new( @@ -228,25 +224,21 @@ impl<'i, I: Interner> FallibleTypeFolder for Canonicalizer<'i, I> { ); let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var)); debug!(position = ?bound_var, "not yet unified"); - Ok(bound_var + bound_var .shifted_in_from(outer_binder) - .to_const(interner, ty)) + .to_const(interner, ty) } } } - fn try_fold_lifetime( - &mut self, - lifetime: Lifetime, - outer_binder: DebruijnIndex, - ) -> Fallible> { + fn fold_lifetime(&mut self, lifetime: Lifetime, outer_binder: DebruijnIndex) -> Lifetime { match *lifetime.data(self.interner) { LifetimeData::Empty(ui) if ui.counter != 0 => { // ReEmpty in non-root universes is only used by lexical region // inference. We shouldn't see it in canonicalization. panic!("Cannot canonicalize ReEmpty in non-root universe") } - _ => lifetime.try_super_fold_with(self, outer_binder), + _ => lifetime.super_fold_with(self, outer_binder), } } diff --git a/chalk-solve/src/infer/invert.rs b/chalk-solve/src/infer/invert.rs index 08114ea484f..e5bc3590ced 100644 --- a/chalk-solve/src/infer/invert.rs +++ b/chalk-solve/src/infer/invert.rs @@ -1,5 +1,6 @@ +use chalk_derive::FallibleTypeFolder; use chalk_ir::fold::shift::Shift; -use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; +use chalk_ir::fold::{TypeFoldable, TypeFolder}; use chalk_ir::interner::HasInterner; use chalk_ir::interner::Interner; use chalk_ir::*; @@ -109,6 +110,7 @@ impl InferenceTable { } } +#[derive(FallibleTypeFolder)] struct Inverter<'q, I: Interner> { table: &'q mut InferenceTable, inverted_ty: FxHashMap>, @@ -127,39 +129,35 @@ impl<'q, I: Interner> Inverter<'q, I> { } } -impl<'i, I: Interner> FallibleTypeFolder for Inverter<'i, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl<'i, I: Interner> TypeFolder for Inverter<'i, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_placeholder_ty( + fn fold_free_placeholder_ty( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let table = &mut self.table; - Ok(self - .inverted_ty + self.inverted_ty .entry(universe) .or_insert_with(|| table.new_variable(universe.ui)) - .to_ty(self.interner()) - .shifted_in(self.interner())) + .to_ty(TypeFolder::interner(self)) + .shifted_in(TypeFolder::interner(self)) } - fn try_fold_free_placeholder_lifetime( + fn fold_free_placeholder_lifetime( &mut self, universe: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let table = &mut self.table; - Ok(self - .inverted_lifetime + self.inverted_lifetime .entry(universe) .or_insert_with(|| table.new_variable(universe.ui)) - .to_lifetime(self.interner()) - .shifted_in(self.interner())) + .to_lifetime(TypeFolder::interner(self)) + .shifted_in(TypeFolder::interner(self)) } fn forbid_free_vars(&self) -> bool { diff --git a/chalk-solve/src/infer/ucanonicalize.rs b/chalk-solve/src/infer/ucanonicalize.rs index 506251f26e4..b44880e3764 100644 --- a/chalk-solve/src/infer/ucanonicalize.rs +++ b/chalk-solve/src/infer/ucanonicalize.rs @@ -1,5 +1,6 @@ use crate::debug_span; -use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable}; +use chalk_derive::FallibleTypeFolder; +use chalk_ir::fold::{TypeFoldable, TypeFolder}; use chalk_ir::interner::{HasInterner, Interner}; use chalk_ir::visit::{TypeVisitable, TypeVisitor}; use chalk_ir::*; @@ -217,15 +218,14 @@ impl TypeVisitor for UCollector<'_, I> { } } -struct UMapToCanonical<'q, I> { +#[derive(FallibleTypeFolder)] +struct UMapToCanonical<'q, I: Interner> { interner: I, universes: &'q UniverseMap, } -impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl<'i, I: Interner> TypeFolder for UMapToCanonical<'i, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -233,55 +233,55 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { true } - fn try_fold_free_placeholder_ty( + fn fold_free_placeholder_ty( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let ui = self .universes .map_universe_to_canonical(universe0.ui) .expect("Expected UCollector to encounter this universe"); - Ok(PlaceholderIndex { + PlaceholderIndex { ui, idx: universe0.idx, } - .to_ty(self.interner())) + .to_ty(TypeFolder::interner(self)) } - fn try_fold_free_placeholder_lifetime( + fn fold_free_placeholder_lifetime( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let universe = self .universes .map_universe_to_canonical(universe0.ui) .expect("Expected UCollector to encounter this universe"); - Ok(PlaceholderIndex { + PlaceholderIndex { ui: universe, idx: universe0.idx, } - .to_lifetime(self.interner())) + .to_lifetime(TypeFolder::interner(self)) } - fn try_fold_free_placeholder_const( + fn fold_free_placeholder_const( &mut self, ty: Ty, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Const { let universe = self .universes .map_universe_to_canonical(universe0.ui) .expect("Expected UCollector to encounter this universe"); - Ok(PlaceholderIndex { + PlaceholderIndex { ui: universe, idx: universe0.idx, } - .to_const(self.interner(), ty)) + .to_const(TypeFolder::interner(self), ty) } fn interner(&self) -> I { @@ -289,42 +289,41 @@ impl<'i, I: Interner> FallibleTypeFolder for UMapToCanonical<'i, I> { } } -struct UMapFromCanonical<'q, I> { +#[derive(FallibleTypeFolder)] +struct UMapFromCanonical<'q, I: Interner> { interner: I, universes: &'q UniverseMap, } -impl<'i, I: Interner> FallibleTypeFolder for UMapFromCanonical<'i, I> { - type Error = NoSolution; - - fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { +impl<'i, I: Interner> TypeFolder for UMapFromCanonical<'i, I> { + fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } - fn try_fold_free_placeholder_ty( + fn fold_free_placeholder_ty( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Ty { let ui = self.universes.map_universe_from_canonical(universe0.ui); - Ok(PlaceholderIndex { + PlaceholderIndex { ui, idx: universe0.idx, } - .to_ty(self.interner())) + .to_ty(TypeFolder::interner(self)) } - fn try_fold_free_placeholder_lifetime( + fn fold_free_placeholder_lifetime( &mut self, universe0: PlaceholderIndex, _outer_binder: DebruijnIndex, - ) -> Fallible> { + ) -> Lifetime { let universe = self.universes.map_universe_from_canonical(universe0.ui); - Ok(PlaceholderIndex { + PlaceholderIndex { ui: universe, idx: universe0.idx, } - .to_lifetime(self.interner())) + .to_lifetime(TypeFolder::interner(self)) } fn forbid_inference_vars(&self) -> bool {