From 569fb43aa09eb4008155dcf0a2f7082c3afddefa Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 May 2024 12:42:22 -0400 Subject: [PATCH 1/3] Uplift RegionVid --- compiler/rustc_borrowck/src/facts.rs | 27 +++++++++++++++++-- compiler/rustc_borrowck/src/polonius/mod.rs | 10 ++++--- .../rustc_borrowck/src/region_infer/mod.rs | 10 +++---- .../src/type_check/liveness/polonius.rs | 4 +-- compiler/rustc_borrowck/src/type_check/mod.rs | 14 +++++----- compiler/rustc_middle/src/ty/context.rs | 1 - compiler/rustc_middle/src/ty/region.rs | 18 +------------ .../rustc_middle/src/ty/structural_impls.rs | 12 --------- compiler/rustc_type_ir/src/debug.rs | 6 ++--- compiler/rustc_type_ir/src/infcx.rs | 9 +++---- compiler/rustc_type_ir/src/interner.rs | 1 - compiler/rustc_type_ir/src/region_kind.rs | 27 ++++++++++++++++--- 12 files changed, 75 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index e7faec7bbac1e..51ea59e2092a5 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -15,8 +15,31 @@ use std::path::Path; #[derive(Copy, Clone, Debug)] pub struct RustcFacts; +rustc_index::newtype_index! { + /// A (kinda) newtype of `RegionVid` so we can implement `Atom` on it. + #[orderable] + #[debug_format = "'?{}"] + pub struct PoloniusRegionVid {} +} + +impl polonius_engine::Atom for PoloniusRegionVid { + fn index(self) -> usize { + self.as_usize() + } +} +impl From for PoloniusRegionVid { + fn from(value: RegionVid) -> Self { + Self::from_usize(value.as_usize()) + } +} +impl From for RegionVid { + fn from(value: PoloniusRegionVid) -> Self { + Self::from_usize(value.as_usize()) + } +} + impl polonius_engine::FactTypes for RustcFacts { - type Origin = RegionVid; + type Origin = PoloniusRegionVid; type Loan = BorrowIndex; type Point = LocationIndex; type Variable = Local; @@ -119,7 +142,7 @@ trait FactRow { ) -> Result<(), Box>; } -impl FactRow for RegionVid { +impl FactRow for PoloniusRegionVid { fn write( &self, out: &mut dyn Write, diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 40126d50d57e6..9984f76e6d446 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; use crate::borrow_set::BorrowSet; -use crate::facts::AllFacts; +use crate::facts::{AllFacts, PoloniusRegionVid}; use crate::location::LocationTable; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::universal_regions::UniversalRegions; @@ -137,7 +137,9 @@ fn emit_universal_region_facts( // the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index // added to the existing number of loans, as if they succeeded them in the set. // - all_facts.universal_region.extend(universal_regions.universal_regions()); + all_facts + .universal_region + .extend(universal_regions.universal_regions().map(PoloniusRegionVid::from)); let borrow_count = borrow_set.len(); debug!( "emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}", @@ -148,7 +150,7 @@ fn emit_universal_region_facts( for universal_region in universal_regions.universal_regions() { let universal_region_idx = universal_region.index(); let placeholder_loan_idx = borrow_count + universal_region_idx; - all_facts.placeholder.push((universal_region, placeholder_loan_idx.into())); + all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into())); } // 2: the universal region relations `outlives` constraints are emitted as @@ -160,7 +162,7 @@ fn emit_universal_region_facts( fr1={:?}, fr2={:?}", fr1, fr2 ); - all_facts.known_placeholder_subset.push((fr1, fr2)); + all_facts.known_placeholder_subset.push((fr1.into(), fr2.into())); } } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 167ca7ba04570..b57cf9066cf33 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1506,7 +1506,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { subset_errors.sort(); subset_errors.dedup(); - for (longer_fr, shorter_fr) in subset_errors.into_iter() { + for &(longer_fr, shorter_fr) in subset_errors.into_iter() { debug!( "check_polonius_subset_errors: subset_error longer_fr={:?},\ shorter_fr={:?}", @@ -1514,14 +1514,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); let propagated = self.try_propagate_universal_region_error( - *longer_fr, - *shorter_fr, + longer_fr.into(), + shorter_fr.into(), &mut propagated_outlives_requirements, ); if propagated == RegionRelationCheckResult::Error { errors_buffer.push(RegionErrorKind::RegionError { - longer_fr: *longer_fr, - shorter_fr: *shorter_fr, + longer_fr: longer_fr.into(), + shorter_fr: shorter_fr.into(), fr_origin: NllRegionVariableOrigin::FreeRegion, is_reported: true, }); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index 7f5302270439c..ccfa9f12ef45a 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -117,7 +117,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>( let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| { let region_vid = universal_regions.to_region_vid(region); - facts.use_of_var_derefs_origin.push((local, region_vid)); + facts.use_of_var_derefs_origin.push((local, region_vid.into())); }); } } @@ -136,7 +136,7 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>( let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| { let region_vid = universal_regions.to_region_vid(drop_live_region); - facts.drop_of_var_derefs_origin.push((local, region_vid)); + facts.drop_of_var_derefs_origin.push((local, region_vid.into())); }); } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6cf9ac45aa3ef..2ad1110f06fd9 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -260,16 +260,14 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { |constraint: &OutlivesConstraint<'_>| { if let Some(from_location) = constraint.locations.from_location() { Either::Left(iter::once(( - constraint.sup, - constraint.sub, + constraint.sup.into(), + constraint.sub.into(), location_table.mid_index(from_location), ))) } else { - Either::Right( - location_table - .all_points() - .map(move |location| (constraint.sup, constraint.sub, location)), - ) + Either::Right(location_table.all_points().map(move |location| { + (constraint.sup.into(), constraint.sub.into(), location) + })) } }, )); @@ -2547,7 +2545,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(borrow_index) = borrow_set.get_index_of(&location) { let region_vid = borrow_region.as_var(); all_facts.loan_issued_at.push(( - region_vid, + region_vid.into(), borrow_index, location_table.mid_index(location), )); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d75f250275bce..8185c99c2fd20 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -134,7 +134,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; type BoundRegion = ty::BoundRegion; - type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; type ParamEnv = ty::ParamEnv<'tcx>; diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 7540f0ab83ff0..551e2ea229561 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -1,13 +1,12 @@ -use polonius_engine::Atom; use rustc_data_structures::intern::Interned; use rustc_errors::MultiSpan; use rustc_hir::def_id::DefId; -use rustc_index::Idx; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::symbol::sym; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use rustc_type_ir::RegionKind as IrRegionKind; +pub use rustc_type_ir::RegionVid; use std::ops::Deref; use crate::ty::{self, BoundVar, TyCtxt, TypeFlags}; @@ -348,21 +347,6 @@ impl std::fmt::Debug for EarlyParamRegion { } } -rustc_index::newtype_index! { - /// A **region** (lifetime) **v**ariable **ID**. - #[derive(HashStable)] - #[encodable] - #[orderable] - #[debug_format = "'?{}"] - pub struct RegionVid {} -} - -impl Atom for RegionVid { - fn index(self) -> usize { - Idx::index(self) - } -} - #[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, Copy)] #[derive(HashStable)] /// The parameter representation of late-bound function parameters, "some region diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7d24824d568f4..c5be9f46e307d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -259,18 +259,6 @@ impl<'tcx> DebugWithInfcx> for Region<'tcx> { } } -impl<'tcx> DebugWithInfcx> for ty::RegionVid { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - match this.infcx.universe_of_lt(*this.data) { - Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()), - None => write!(f, "{:?}", this.data), - } - } -} - impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty::Binder<'tcx, T> { fn fmt>>( this: WithInfcx<'_, Infcx, &Self>, diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 9298360f749ac..b89be1332d6ba 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -1,4 +1,4 @@ -use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex}; +use crate::{ConstVid, InferCtxtLike, Interner, RegionVid, TyVid, UniverseIndex}; use core::fmt; use std::marker::PhantomData; @@ -16,7 +16,7 @@ impl InferCtxtLike for NoInfcx { None } - fn universe_of_lt(&self, _lt: I::InferRegion) -> Option { + fn universe_of_lt(&self, _lt: RegionVid) -> Option { None } @@ -32,7 +32,7 @@ impl InferCtxtLike for NoInfcx { None } - fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option { + fn opportunistic_resolve_lt_var(&self, _vid: RegionVid) -> Option { None } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index a53287c19878b..5485ae318ece7 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -1,4 +1,4 @@ -use crate::{ConstVid, Interner, TyVid, UniverseIndex}; +use crate::{ConstVid, Interner, RegionVid, TyVid, UniverseIndex}; pub trait InferCtxtLike { type Interner: Interner; @@ -13,10 +13,7 @@ pub trait InferCtxtLike { /// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type. fn probe_ty_var(&self, vid: TyVid) -> Option<::Ty>; - fn universe_of_lt( - &self, - lt: ::InferRegion, - ) -> Option; + fn universe_of_lt(&self, lt: RegionVid) -> Option; /// Resolve `InferRegion` to its inferred region, if it has been equated with /// a non-infer region. @@ -27,7 +24,7 @@ pub trait InferCtxtLike { /// var we're trying to resolve. That's why it's called *opportunistic*. fn opportunistic_resolve_lt_var( &self, - vid: ::InferRegion, + vid: RegionVid, ) -> Option<::Region>; fn universe_of_ct(&self, ct: ConstVid) -> Option; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0b51d2e75f457..c6dc57718cc3f 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -79,7 +79,6 @@ pub trait Interner: type EarlyParamRegion: Copy + Debug + Hash + Eq; type LateParamRegion: Copy + Debug + Hash + Eq; type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike; - type InferRegion: Copy + DebugWithInfcx + Hash + Eq; type PlaceholderRegion: PlaceholderLike; // Predicates diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index eaae4ee0130bf..48ade27328943 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -1,13 +1,35 @@ #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_macros::{TyDecodable, TyEncodable}; +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use std::fmt; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; use self::RegionKind::*; +rustc_index::newtype_index! { + /// A **region** **v**ariable **ID**. + #[encodable] + #[orderable] + #[debug_format = "'?{}"] + #[gate_rustc_only] + #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] + pub struct RegionVid {} +} + +impl DebugWithInfcx for RegionVid { + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + match this.infcx.universe_of_lt(*this.data) { + Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()), + None => write!(f, "{:?}", this.data), + } + } +} + /// Representation of regions. Note that the NLL checker uses a distinct /// representation of regions. For this reason, it internally replaces all the /// regions with inference variables -- the index of the variable is then used @@ -152,7 +174,7 @@ pub enum RegionKind { ReStatic, /// A region variable. Should not exist outside of type inference. - ReVar(I::InferRegion), + ReVar(RegionVid), /// A placeholder region -- the higher-ranked version of `ReLateParam`. /// Should not exist outside of type inference. @@ -251,7 +273,6 @@ where I::EarlyParamRegion: HashStable, I::BoundRegion: HashStable, I::LateParamRegion: HashStable, - I::InferRegion: HashStable, I::PlaceholderRegion: HashStable, { #[inline] From b0f1afd1fc29646d9c2d383fb4d1e86477dde73e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 May 2024 13:04:44 -0400 Subject: [PATCH 2/3] Rework var resolution in InferCtxtLike, uplift EagerResolver --- compiler/rustc_infer/src/infer/mod.rs | 44 ++++++---- compiler/rustc_infer/src/infer/resolve.rs | 81 ------------------ compiler/rustc_middle/src/ty/consts.rs | 8 ++ compiler/rustc_middle/src/ty/sty.rs | 8 ++ .../src/canonicalizer.rs | 42 ++++++---- compiler/rustc_next_trait_solver/src/lib.rs | 1 + .../rustc_next_trait_solver/src/resolve.rs | 83 +++++++++++++++++++ .../src/solve/eval_ctxt/canonical.rs | 2 +- .../src/solve/inspect/analyse.rs | 2 +- compiler/rustc_type_ir/src/debug.rs | 30 ++++--- compiler/rustc_type_ir/src/infcx.rs | 41 ++++----- compiler/rustc_type_ir/src/inherent.rs | 15 +++- 12 files changed, 198 insertions(+), 159 deletions(-) create mode 100644 compiler/rustc_next_trait_solver/src/resolve.rs diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 723f4c81ca52e..8d4011421bd33 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -369,33 +369,43 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { } } - fn root_ty_var(&self, vid: TyVid) -> TyVid { - self.root_var(vid) + fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> { + self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) } - fn probe_ty_var(&self, vid: TyVid) -> Option> { - self.probe_ty_var(vid).ok() + fn defining_opaque_types(&self) -> &'tcx ty::List { + self.defining_opaque_types } - fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> Option> { - let re = self - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(self.tcx, vid); - if *re == ty::ReVar(vid) { None } else { Some(re) } + fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> { + match self.probe_ty_var(vid) { + Ok(ty) => ty, + Err(_) => Ty::new_var(self.tcx, self.root_var(vid)), + } } - fn root_ct_var(&self, vid: ConstVid) -> ConstVid { - self.root_const_var(vid) + fn opportunistic_resolve_int_var(&self, vid: IntVid) -> Ty<'tcx> { + self.opportunistic_resolve_int_var(vid) } - fn probe_ct_var(&self, vid: ConstVid) -> Option> { - self.probe_const_var(vid).ok() + fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> Ty<'tcx> { + self.opportunistic_resolve_float_var(vid) } - fn defining_opaque_types(&self) -> &'tcx ty::List { - self.defining_opaque_types + fn opportunistic_resolve_ct_var(&self, vid: ConstVid, ty: Ty<'tcx>) -> ty::Const<'tcx> { + match self.probe_const_var(vid) { + Ok(ct) => ct, + Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid), ty), + } + } + + fn opportunistic_resolve_effect_var(&self, vid: EffectVid, ty: Ty<'tcx>) -> ty::Const<'tcx> { + match self.probe_effect_var(vid) { + Some(ct) => ct, + None => { + ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)), ty) + } + } } } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 61b13dd9a54fd..21ef2e89523f5 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -173,84 +173,3 @@ impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { } } } - -/////////////////////////////////////////////////////////////////////////// -// EAGER RESOLUTION - -/// Resolves ty, region, and const vars to their inferred values or their root vars. -pub struct EagerResolver<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, -} - -impl<'a, 'tcx> EagerResolver<'a, 'tcx> { - pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self { - EagerResolver { infcx } - } -} - -impl<'tcx> TypeFolder> for EagerResolver<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match *t.kind() { - ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) { - Ok(t) => t.fold_with(self), - Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)), - }, - ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid), - ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid), - _ => { - if t.has_infer() { - t.super_fold_with(self) - } else { - t - } - } - } - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReVar(vid) => self - .infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(self.infcx.tcx, vid), - _ => r, - } - } - - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { - match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - // FIXME: we need to fold the ty too, I think. - match self.infcx.probe_const_var(vid) { - Ok(c) => c.fold_with(self), - Err(_) => { - ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty()) - } - } - } - ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { - debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool); - self.infcx.probe_effect_var(vid).unwrap_or_else(|| { - ty::Const::new_infer( - self.infcx.tcx, - ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)), - self.infcx.tcx.types.bool, - ) - }) - } - _ => { - if c.has_infer() { - c.super_fold_with(self) - } else { - c - } - } - } - } -} diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 9dc30447f0e57..f7cc055be11c2 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -175,6 +175,14 @@ impl<'tcx> Const<'tcx> { } impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { + fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Self { + Const::new_infer(tcx, infer, ty) + } + + fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self { + Const::new_var(tcx, vid, ty) + } + fn new_anon_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 7c41c5f512e6e..2d9d178449e09 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1611,6 +1611,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { tcx.types.bool } + fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self { + Ty::new_infer(tcx, infer) + } + + fn new_var(tcx: TyCtxt<'tcx>, vid: ty::TyVid) -> Self { + Ty::new_var(tcx, vid) + } + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 755f5cfa5a378..696639e9c1b65 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -268,7 +268,7 @@ impl, I: Interner> TypeFolder ty::ReVar(vid) => { assert_eq!( self.infcx.opportunistic_resolve_lt_var(vid), - None, + r, "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { @@ -302,13 +302,8 @@ impl, I: Interner> TypeFolder ty::Infer(i) => match i { ty::TyVar(vid) => { assert_eq!( - self.infcx.root_ty_var(vid), - vid, - "ty vid should have been resolved fully before canonicalization" - ); - assert_eq!( - self.infcx.probe_ty_var(vid), - None, + self.infcx.opportunistic_resolve_ty_var(vid), + t, "ty vid should have been resolved fully before canonicalization" ); @@ -318,10 +313,24 @@ impl, I: Interner> TypeFolder .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), )) } - ty::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int), - ty::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float), + ty::IntVar(vid) => { + assert_eq!( + self.infcx.opportunistic_resolve_int_var(vid), + t, + "ty vid should have been resolved fully before canonicalization" + ); + CanonicalVarKind::Ty(CanonicalTyVarKind::Int) + } + ty::FloatVar(vid) => { + assert_eq!( + self.infcx.opportunistic_resolve_float_var(vid), + t, + "ty vid should have been resolved fully before canonicalization" + ); + CanonicalVarKind::Ty(CanonicalTyVarKind::Float) + } ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { - todo!() + panic!("fresh vars not expected in canonicalization") } }, ty::Placeholder(placeholder) => match self.canonicalize_mode { @@ -387,14 +396,11 @@ impl, I: Interner> TypeFolder let kind = match c.kind() { ty::ConstKind::Infer(i) => match i { ty::InferConst::Var(vid) => { + // We compare `kind`s here because we've folded the `ty` with `RegionsToStatic` + // so we'll get a mismatch in types if it actually changed any regions. assert_eq!( - self.infcx.root_ct_var(vid), - vid, - "region vid should have been resolved fully before canonicalization" - ); - assert_eq!( - self.infcx.probe_ct_var(vid), - None, + self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(), + c.kind(), "region vid should have been resolved fully before canonicalization" ); CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty) diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs index 4202dc39fb2fb..b913a05095c2b 100644 --- a/compiler/rustc_next_trait_solver/src/lib.rs +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -1,2 +1,3 @@ pub mod canonicalizer; +pub mod resolve; pub mod solve; diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs new file mode 100644 index 0000000000000..1333b4aa7d83a --- /dev/null +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -0,0 +1,83 @@ +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::inherent::*; +use rustc_type_ir::visit::TypeVisitableExt; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; + +/////////////////////////////////////////////////////////////////////////// +// EAGER RESOLUTION + +/// Resolves ty, region, and const vars to their inferred values or their root vars. +pub struct EagerResolver< + 'a, + Infcx: InferCtxtLike, + I: Interner = ::Interner, +> { + infcx: &'a Infcx, +} + +impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> { + pub fn new(infcx: &'a Infcx) -> Self { + EagerResolver { infcx } + } +} + +impl, I: Interner> TypeFolder for EagerResolver<'_, Infcx> { + fn interner(&self) -> I { + self.infcx.interner() + } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + match t.kind() { + ty::Infer(ty::TyVar(vid)) => { + let resolved = self.infcx.opportunistic_resolve_ty_var(vid); + if t != resolved && resolved.has_infer() { + resolved.fold_with(self) + } else { + resolved + } + } + ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid), + ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid), + _ => { + if t.has_infer() { + t.super_fold_with(self) + } else { + t + } + } + } + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid), + _ => r, + } + } + + fn fold_const(&mut self, c: I::Const) -> I::Const { + match c.kind() { + ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { + let ty = c.ty().fold_with(self); + let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty); + if c != resolved && resolved.has_infer() { + resolved.fold_with(self) + } else { + resolved + } + } + ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { + let bool = Ty::new_bool(self.infcx.interner()); + debug_assert_eq!(c.ty(), bool); + self.infcx.opportunistic_resolve_effect_var(vid, bool) + } + _ => { + if c.has_infer() { + c.super_fold_with(self) + } else { + c + } + } + } + } +} diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index a642d0c40fc9d..9590a82c0677f 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -18,7 +18,6 @@ use rustc_index::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; -use rustc_infer::infer::resolve::EagerResolver; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, InferOk}; use rustc_infer::traits::solve::NestedNormalizationGoals; @@ -31,6 +30,7 @@ use rustc_middle::traits::solve::{ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable}; use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer}; +use rustc_next_trait_solver::resolve::EagerResolver; use rustc_span::{Span, DUMMY_SP}; use std::assert_matches::assert_matches; use std::iter; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index e12c66b692850..737d03f73f00b 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -11,7 +11,6 @@ use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; -use rustc_infer::infer::resolve::EagerResolver; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_macros::extension; use rustc_middle::traits::query::NoSolution; @@ -20,6 +19,7 @@ use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{TyCtxt, TypeFoldable}; use rustc_middle::{bug, ty}; +use rustc_next_trait_solver::resolve::EagerResolver; use rustc_span::{Span, DUMMY_SP}; use crate::solve::eval_ctxt::canonical; diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index b89be1332d6ba..4e8be1ee4c285 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -1,4 +1,6 @@ -use crate::{ConstVid, InferCtxtLike, Interner, RegionVid, TyVid, UniverseIndex}; +use crate::{ + ConstVid, EffectVid, FloatVid, InferCtxtLike, IntVid, Interner, RegionVid, TyVid, UniverseIndex, +}; use core::fmt; use std::marker::PhantomData; @@ -24,27 +26,31 @@ impl InferCtxtLike for NoInfcx { None } - fn root_ty_var(&self, vid: TyVid) -> TyVid { - vid + fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> I::Ty { + panic!("cannot resolve {vid:?}") } - fn probe_ty_var(&self, _vid: TyVid) -> Option { - None + fn opportunistic_resolve_int_var(&self, vid: IntVid) -> I::Ty { + panic!("cannot resolve {vid:?}") } - fn opportunistic_resolve_lt_var(&self, _vid: RegionVid) -> Option { - None + fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> I::Ty { + panic!("cannot resolve {vid:?}") } - fn root_ct_var(&self, vid: ConstVid) -> ConstVid { - vid + fn opportunistic_resolve_ct_var(&self, vid: ConstVid, _: I::Ty) -> I::Const { + panic!("cannot resolve {vid:?}") } - fn probe_ct_var(&self, _vid: ConstVid) -> Option { - None + fn opportunistic_resolve_effect_var(&self, vid: EffectVid, _: I::Ty) -> I::Const { + panic!("cannot resolve {vid:?}") + } + + fn opportunistic_resolve_lt_var(&self, vid: crate::RegionVid) -> I::Region { + panic!("cannot resolve {vid:?}") } - fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes { + fn defining_opaque_types(&self) -> I::DefiningOpaqueTypes { Default::default() } } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index 5485ae318ece7..bb5081fb33576 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -1,4 +1,4 @@ -use crate::{ConstVid, Interner, RegionVid, TyVid, UniverseIndex}; +use crate::{ConstVid, EffectVid, FloatVid, IntVid, Interner, RegionVid, TyVid, UniverseIndex}; pub trait InferCtxtLike { type Interner: Interner; @@ -6,34 +6,23 @@ pub trait InferCtxtLike { fn interner(&self) -> Self::Interner; fn universe_of_ty(&self, ty: TyVid) -> Option; - - /// Resolve `TyVid` to its root `TyVid`. - fn root_ty_var(&self, vid: TyVid) -> TyVid; - - /// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type. - fn probe_ty_var(&self, vid: TyVid) -> Option<::Ty>; - fn universe_of_lt(&self, lt: RegionVid) -> Option; - - /// Resolve `InferRegion` to its inferred region, if it has been equated with - /// a non-infer region. - /// - /// FIXME: This has slightly different semantics than `{probe,resolve}_{ty,ct}_var`, - /// that has to do with the fact unlike `Ty` or `Const` vars, in rustc, we may - /// not always be able to *name* the root region var from the universe of the - /// var we're trying to resolve. That's why it's called *opportunistic*. - fn opportunistic_resolve_lt_var( - &self, - vid: RegionVid, - ) -> Option<::Region>; - fn universe_of_ct(&self, ct: ConstVid) -> Option; - /// Resolve `ConstVid` to its root `ConstVid`. - fn root_ct_var(&self, vid: ConstVid) -> ConstVid; - - /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type. - fn probe_ct_var(&self, vid: ConstVid) -> Option<::Const>; + fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> ::Ty; + fn opportunistic_resolve_int_var(&self, vid: IntVid) -> ::Ty; + fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> ::Ty; + fn opportunistic_resolve_ct_var( + &self, + vid: ConstVid, + ty: ::Ty, + ) -> ::Const; + fn opportunistic_resolve_effect_var( + &self, + vid: EffectVid, + ty: ::Ty, + ) -> ::Const; + fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> ::Region; fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes; } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 19c76fb165a03..f66c6e722f7ca 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -7,11 +7,11 @@ use std::fmt::Debug; use std::hash::Hash; use std::ops::Deref; -use crate::fold::TypeSuperFoldable; +use crate::fold::{TypeFoldable, TypeSuperFoldable}; use crate::visit::{Flags, TypeSuperVisitable}; use crate::{ - AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, - TyKind, UnevaluatedConst, UniverseIndex, + AliasTy, AliasTyKind, BoundVar, ConstKind, ConstVid, DebruijnIndex, DebugWithInfcx, InferConst, + InferTy, Interner, RegionKind, TyKind, TyVid, UnevaluatedConst, UniverseIndex, }; pub trait Ty>: @@ -28,6 +28,10 @@ pub trait Ty>: { fn new_bool(interner: I) -> Self; + fn new_infer(interner: I, var: InferTy) -> Self; + + fn new_var(interner: I, var: TyVid) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy) -> Self; @@ -68,6 +72,10 @@ pub trait Const>: + TypeSuperFoldable + Flags { + fn new_infer(interner: I, var: InferConst, ty: I::Ty) -> Self; + + fn new_var(interner: I, var: ConstVid, ty: I::Ty) -> Self; + fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self; fn new_unevaluated(interner: I, uv: UnevaluatedConst, ty: I::Ty) -> Self; @@ -87,6 +95,7 @@ pub trait GenericArgs>: + IntoIterator + Deref> + Default + + TypeFoldable { fn type_at(self, i: usize) -> I::Ty; From 9fa07a4e553222eb511da7631a5a7f2acb007c43 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 May 2024 13:44:50 -0400 Subject: [PATCH 3/3] Uplift TermKind --- compiler/rustc_middle/src/ty/generic_args.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 31 ++++++++++++------- .../rustc_middle/src/ty/structural_impls.rs | 11 +++---- compiler/rustc_type_ir/src/generic_arg.rs | 14 +++++++++ compiler/rustc_type_ir/src/interner.rs | 4 +-- 5 files changed, 41 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 38b2987399a9a..3d263e62de66e 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -27,6 +27,7 @@ use std::ops::Deref; use std::ptr::NonNull; pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind>; +pub type TermKind<'tcx> = rustc_type_ir::TermKind>; /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts). diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 44f09b8ba2173..8bb19bc85acbd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -28,7 +28,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::util::Discr; pub use adt::*; pub use assoc::*; -pub use generic_args::{GenericArgKind, *}; +pub use generic_args::{GenericArgKind, TermKind, *}; pub use generics::*; pub use intrinsic::IntrinsicDef; use rustc_ast as ast; @@ -48,7 +48,8 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res} use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; use rustc_index::IndexVec; use rustc_macros::{ - Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, + extension, Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, + TypeVisitable, }; use rustc_query_system::ich::StableHashingContext; use rustc_serialize::{Decodable, Encodable}; @@ -521,6 +522,14 @@ pub struct Term<'tcx> { marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, } +impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> { + type Kind = TermKind<'tcx>; + + fn kind(self) -> Self::Kind { + self.unpack() + } +} + #[cfg(parallel_compiler)] unsafe impl<'tcx> rustc_data_structures::sync::DynSend for Term<'tcx> where &'tcx (Ty<'tcx>, Const<'tcx>): rustc_data_structures::sync::DynSend @@ -566,13 +575,19 @@ impl<'tcx> TypeFoldable> for Term<'tcx> { self, folder: &mut F, ) -> Result { - Ok(self.unpack().try_fold_with(folder)?.pack()) + match self.unpack() { + ty::TermKind::Ty(ty) => ty.try_fold_with(folder).map(Into::into), + ty::TermKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), + } } } impl<'tcx> TypeVisitable> for Term<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { - self.unpack().visit_with(visitor) + match self.unpack() { + ty::TermKind::Ty(ty) => ty.visit_with(visitor), + ty::TermKind::Const(ct) => ct.visit_with(visitor), + } } } @@ -650,13 +665,7 @@ const TAG_MASK: usize = 0b11; const TYPE_TAG: usize = 0b00; const CONST_TAG: usize = 0b01; -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable)] -pub enum TermKind<'tcx> { - Ty(Ty<'tcx>), - Const(Const<'tcx>), -} - +#[extension(pub trait TermKindPackExt<'tcx>)] impl<'tcx> TermKind<'tcx> { #[inline] fn pack(self) -> Term<'tcx> { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c5be9f46e307d..81d92a2a448e4 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -371,13 +371,10 @@ impl<'tcx, T: Lift>> Lift> for Option { impl<'a, 'tcx> Lift> for Term<'a> { type Lifted = ty::Term<'tcx>; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { - Some( - match self.unpack() { - TermKind::Ty(ty) => TermKind::Ty(tcx.lift(ty)?), - TermKind::Const(c) => TermKind::Const(tcx.lift(c)?), - } - .pack(), - ) + match self.unpack() { + TermKind::Ty(ty) => tcx.lift(ty).map(Into::into), + TermKind::Const(c) => tcx.lift(c).map(Into::into), + } } } diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index 622a40806083b..cc8c44446579f 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -16,3 +16,17 @@ pub enum GenericArgKind { Type(I::Ty), Const(I::Const), } + +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Debug(bound = ""), + Eq(bound = ""), + PartialEq(bound = "") +)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub enum TermKind { + Ty(I::Ty), + Const(I::Const), +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c6dc57718cc3f..6516d5b164540 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,7 +10,7 @@ use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, FnSig, GenericArgKind, - NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, + NormalizesTo, ProjectionPredicate, SubtypePredicate, TermKind, TraitPredicate, TraitRef, }; pub trait Interner: @@ -36,7 +36,7 @@ pub trait Interner: /// not including the args from the parent item (trait or impl). type OwnItemArgs: Copy + Debug + Hash + Eq; type GenericArg: Copy + DebugWithInfcx + Hash + Eq + IntoKind>; - type Term: Copy + Debug + Hash + Eq; + type Term: Copy + Debug + Hash + Eq + IntoKind>; type Binder>: BoundVars + TypeSuperVisitable; type BoundVars: IntoIterator;