diff --git a/Cargo.lock b/Cargo.lock index 92e6a22b4b9..5e8d179e536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4686,6 +4686,7 @@ dependencies = [ "rustc_span", "rustc_type_ir_macros", "smallvec", + "tracing", ] [[package]] diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 39ced1c803f..8928711253c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -449,7 +449,7 @@ impl<'tcx> TypeFolder> for RemapLateBound<'_, 'tcx> { pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, impl_m_def_id: LocalDefId, -) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { +) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 40cd65b899e..75e35e7bf50 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1277,7 +1277,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { } #[instrument(level = "debug", skip(tcx))] -fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> { use rustc_hir::Node::*; use rustc_hir::*; diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index dd1d209389d..50c93e9f1d7 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -82,14 +82,14 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::All) } pub(super) fn explicit_item_super_predicates( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::SelfOnly) } @@ -97,7 +97,7 @@ pub(super) fn explicit_item_bounds_with_filter( tcx: TyCtxt<'_>, def_id: LocalDefId, filter: PredicateFilter, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<'_, &'_ [(ty::Clause<'_>, Span)]> { match tcx.opt_rpitit_info(def_id.to_def_id()) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. @@ -166,7 +166,7 @@ pub(super) fn explicit_item_bounds_with_filter( ty::EarlyBinder::bind(bounds) } -pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder> { +pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { tcx.explicit_item_bounds(def_id).map_bound(|bounds| { tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound))) }) @@ -175,7 +175,7 @@ pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder, def_id: DefId, -) -> ty::EarlyBinder> { +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { tcx.explicit_item_super_predicates(def_id).map_bound(|bounds| { tcx.mk_clauses_from_iter( util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)).filter_only_self(), @@ -186,7 +186,7 @@ pub(super) fn item_super_predicates( pub(super) fn item_non_self_assumptions( tcx: TyCtxt<'_>, def_id: DefId, -) -> ty::EarlyBinder> { +) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect(); let own_bounds: FxIndexSet<_> = tcx.item_super_predicates(def_id).skip_binder().iter().collect(); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1475e53c47c..ed942cc50bb 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -309,7 +309,7 @@ fn get_path_containing_arg_in_pat<'hir>( arg_path } -pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> { use rustc_hir::*; use rustc_middle::ty::Ty; @@ -512,7 +512,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder, def_id: DefId, -) -> Result>, CyclePlaceholder> { +) -> Result>, CyclePlaceholder> { if let Some(def_id) = def_id.as_local() { use rustc_hir::*; diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 1de7a0f7bc7..bbfadbb5c30 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -6,7 +6,7 @@ use super::utils::*; #[derive(Debug)] pub struct ExplicitPredicatesMap<'tcx> { - map: FxIndexMap>>, + map: FxIndexMap>>, } impl<'tcx> ExplicitPredicatesMap<'tcx> { @@ -18,7 +18,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { &mut self, tcx: TyCtxt<'tcx>, def_id: DefId, - ) -> &ty::EarlyBinder> { + ) -> &ty::EarlyBinder<'tcx, RequiredPredicates<'tcx>> { self.map.entry(def_id).or_insert_with(|| { let predicates = if def_id.is_local() { tcx.explicit_predicates_of(def_id) diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index e6c582667ba..af08f50f655 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -15,7 +15,7 @@ use super::utils::*; /// now be filled with inferred predicates. pub(super) fn infer_predicates( tcx: TyCtxt<'_>, -) -> FxIndexMap>> { +) -> FxIndexMap>> { debug!("infer_predicates"); let mut explicit_map = ExplicitPredicatesMap::new(); @@ -101,7 +101,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, - global_inferred_outlives: &FxIndexMap>>, + global_inferred_outlives: &FxIndexMap>>, required_predicates: &mut RequiredPredicates<'tcx>, explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { @@ -322,7 +322,7 @@ fn check_inferred_predicates<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, args: ty::GenericArgsRef<'tcx>, - global_inferred_outlives: &FxIndexMap>>, + global_inferred_outlives: &FxIndexMap>>, required_predicates: &mut RequiredPredicates<'tcx>, ) { // Load the current set of inferred and explicit predicates from `global_inferred_outlives` diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index b3e93748a16..87ee5f53628 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -270,7 +270,7 @@ fn impl_trait_ref_has_enough_non_local_candidates<'tcx>( tcx: TyCtxt<'tcx>, infer_span: Span, trait_def_id: DefId, - binder: EarlyBinder>, + binder: EarlyBinder<'tcx, TraitRef<'tcx>>, mut did_has_local_parent: impl FnMut(DefId) -> bool, ) -> bool { let infcx = tcx diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 695525e755d..19bb943e6bc 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1074,7 +1074,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let lazy = self.root.tables.explicit_item_bounds.get(self, index); let output = if lazy.is_default() { &mut [] @@ -1088,7 +1088,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { let lazy = self.root.tables.explicit_item_super_predicates.get(self, index); let output = if lazy.is_default() { &mut [] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 825034cf96a..c2cf5b6b712 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -418,19 +418,19 @@ define_tables! { // As an optimization, we only store this for trait aliases, // since it's identical to super_predicates_of for traits. implied_predicates_of: Table>>, - type_of: Table>>>, + type_of: Table>>>, variances_of: Table>, - fn_sig: Table>>>, + fn_sig: Table>>>, codegen_fn_attrs: Table>, impl_trait_header: Table>>, - const_param_default: Table>>>, + const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, mir_for_ctfe: Table>>, closure_saved_names_of_captured_variables: Table>>, mir_coroutine_witnesses: Table>>, promoted_mir: Table>>>, - thir_abstract_const: Table>>>, + thir_abstract_const: Table>>>, impl_parent: Table, constness: Table, defaultness: Table, @@ -459,7 +459,7 @@ define_tables! { macro_definition: Table>, proc_macro: Table, deduced_param_attrs: Table>, - trait_impl_trait_tys: Table>>>>, + trait_impl_trait_tys: Table>>>>, doc_link_resolutions: Table>, doc_link_traits_in_scope: Table>, assumed_wf_types_for_rpitit: Table, Span)>>, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index b0e72eaf5a4..bf6ab800064 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -108,7 +108,7 @@ macro_rules! arena_types { [decode] trait_impl_trait_tys: rustc_data_structures::unord::UnordMap< rustc_hir::def_id::DefId, - rustc_middle::ty::EarlyBinder> + rustc_middle::ty::EarlyBinder<'tcx, rustc_middle::ty::Ty<'tcx>> >, [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, [] predefined_opaques_in_body: rustc_middle::traits::solve::PredefinedOpaquesData<'tcx>, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 34748afa863..d39422b2b04 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -121,7 +121,7 @@ impl<'tcx> TyCtxt<'tcx> { LocalModDefId::new_unchecked(id) } - pub fn impl_subject(self, def_id: DefId) -> EarlyBinder> { + pub fn impl_subject(self, def_id: DefId) -> EarlyBinder<'tcx, ImplSubject<'tcx>> { match self.impl_trait_ref(def_id) { Some(t) => t.map_bound(ImplSubject::Trait), None => self.type_of(def_id).map_bound(ImplSubject::Inherent), diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index d025dc360a2..e107c2c12bd 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -220,7 +220,10 @@ pub enum Const<'tcx> { } impl<'tcx> Const<'tcx> { - pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder> { + pub fn identity_unevaluated( + tcx: TyCtxt<'tcx>, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { ty::EarlyBinder::bind(Const::Unevaluated( UnevaluatedConst { def: def_id, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 2b2b9392a70..02e5174a715 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -624,7 +624,7 @@ impl<'tcx> Body<'tcx> { /// Returns the return type; it always return first element from `local_decls` array. #[inline] - pub fn bound_return_ty(&self) -> ty::EarlyBinder> { + pub fn bound_return_ty(&self) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty) } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 320d49ea646..1e36f034cc2 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -114,9 +114,11 @@ impl EraseType for Result { type Result = [u8; size_of::>()]; } -impl EraseType for Result>>, rustc_errors::ErrorGuaranteed> { +impl EraseType + for Result>>, rustc_errors::ErrorGuaranteed> +{ type Result = [u8; size_of::< - Result>>, rustc_errors::ErrorGuaranteed>, + Result>>, rustc_errors::ErrorGuaranteed>, >()]; } @@ -165,8 +167,8 @@ impl EraseType for Result<&'_ ty::List>, ty::util::AlwaysRequiresDrop> { [u8; size_of::>, ty::util::AlwaysRequiresDrop>>()]; } -impl EraseType for Result>, CyclePlaceholder> { - type Result = [u8; size_of::>, CyclePlaceholder>>()]; +impl EraseType for Result>, CyclePlaceholder> { + type Result = [u8; size_of::>, CyclePlaceholder>>()]; } impl EraseType for Option<&'_ T> { @@ -185,15 +187,15 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl EraseType for Option>> { + type Result = [u8; size_of::>>>()]; } impl EraseType for rustc_hir::MaybeOwner<'_> { type Result = [u8; size_of::>()]; } -impl EraseType for ty::EarlyBinder { +impl EraseType for ty::EarlyBinder<'_, T> { type Result = T::Result; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8ca7a465c2a..6ad4b7c40fb 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -209,7 +209,7 @@ rustc_queries! { /// Given the def_id of a const-generic parameter, computes the associated default const /// parameter. e.g. `fn example` called on `N` would return `3`. - query const_param_default(param: DefId) -> ty::EarlyBinder> { + query const_param_default(param: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> { desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) } cache_on_disk_if { param.is_local() } separate_provide_extern @@ -219,7 +219,7 @@ rustc_queries! { /// to an alias, it will "skip" this alias to return the aliased type. /// /// [`DefId`]: rustc_hir::def_id::DefId - query type_of(key: DefId) -> ty::EarlyBinder> { + query type_of(key: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { desc { |tcx| "{action} `{path}`", action = { @@ -240,7 +240,7 @@ rustc_queries! { /// Specialized instance of `type_of` that detects cycles that are due to /// revealing opaque because of an auto trait bound. Unless `CyclePlaceholder` needs /// to be handled separately, call `type_of` instead. - query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { + query type_of_opaque(key: DefId) -> Result>, CyclePlaceholder> { desc { |tcx| "computing type of opaque `{path}`", path = tcx.def_path_str(key), @@ -257,7 +257,7 @@ rustc_queries! { } query collect_return_position_impl_trait_in_trait_tys(key: DefId) - -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> + -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } cache_on_disk_if { key.is_local() } @@ -363,7 +363,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -373,7 +373,7 @@ rustc_queries! { /// share the `Self` type of the item. These are a subset of the bounds /// that may explicitly be used for things like closure signature /// deduction. - query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -399,15 +399,15 @@ rustc_queries! { /// ``` /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query item_bounds(key: DefId) -> ty::EarlyBinder> { + query item_bounds(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query item_super_predicates(key: DefId) -> ty::EarlyBinder> { + query item_super_predicates(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } - query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder> { + query item_non_self_assumptions(key: DefId) -> ty::EarlyBinder<'tcx, ty::Clauses<'tcx>> { desc { |tcx| "elaborating item assumptions for `{}`", tcx.def_path_str(key) } } @@ -504,7 +504,7 @@ rustc_queries! { /// Try to build an abstract representation of the given constant. query thir_abstract_const( key: DefId - ) -> Result>>, ErrorGuaranteed> { + ) -> Result>>, ErrorGuaranteed> { desc { |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key), } @@ -704,7 +704,7 @@ rustc_queries! { separate_provide_extern } - query adt_sized_constraint(key: DefId) -> Option>> { + query adt_sized_constraint(key: DefId) -> Option>> { desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) } } @@ -849,7 +849,7 @@ rustc_queries! { query self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( key: DefId - ) -> Option>> { + ) -> Option>> { desc { |tcx| "computing self type wrt issue #33140 `{}`", tcx.def_path_str(key) } } @@ -888,7 +888,7 @@ rustc_queries! { } /// Computes the signature of the function. - query fn_sig(key: DefId) -> ty::EarlyBinder> { + query fn_sig(key: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 941911c2230..ccd0c7cb10c 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -752,7 +752,7 @@ impl<'a, 'tcx> Decodable> for &'tcx UnordSet } impl<'a, 'tcx> Decodable> - for &'tcx UnordMap>> + for &'tcx UnordMap>> { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index dc46b470b6f..7fb5e9aadae 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,7 +30,8 @@ impl From for NotConstEvaluatable { TrivialTypeTraversalImpls! { NotConstEvaluatable } -pub type BoundAbstractConst<'tcx> = Result>>, ErrorGuaranteed>; +pub type BoundAbstractConst<'tcx> = + Result>>, ErrorGuaranteed>; impl<'tcx> TyCtxt<'tcx> { pub fn expand_abstract_consts>>(self, ac: T) -> T { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 48193754077..8e946bc8b31 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -579,7 +579,7 @@ impl<'tcx> AdtDef<'tcx> { /// Returns a type such that `Self: Sized` if and only if that type is `Sized`, /// or `None` if the type is always sized. - pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { + pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None } } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 40a0dbeb2c2..6416bbbe889 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -184,6 +184,15 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_var(tcx, vid, ty) } + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, + ty: Ty<'tcx>, + ) -> Self { + Const::new_bound(interner, debruijn, var, ty) + } + fn new_anon_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, @@ -486,7 +495,10 @@ impl<'tcx> Const<'tcx> { } } -pub fn const_param_default(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder> { +pub fn const_param_default<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> ty::EarlyBinder<'tcx, Const<'tcx>> { let default_def_id = match tcx.hir_node_by_def_id(def_id) { hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { default: Some(ac), .. }, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e618323c810..c09cb95de88 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -149,8 +149,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.generics_of(def_id) } - fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> { - self.type_of(def_id).instantiate(self, args) + fn type_of(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + self.type_of(def_id) } fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { @@ -679,7 +679,7 @@ impl<'tcx> TyCtxt<'tcx> { /// In order to break cycles involving `AnonConst`, we need to set the expected type by side /// effect. However, we do not want this as a general capability, so this interface restricts /// to the only allowed case. - pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder>) { + pub fn feed_anon_const_type(self, key: LocalDefId, value: ty::EarlyBinder<'tcx, Ty<'tcx>>) { debug_assert_eq!(self.def_kind(key), DefKind::AnonConst); TyCtxtFeed { tcx: self, key }.type_of(value) } @@ -2741,7 +2741,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn impl_trait_ref( self, def_id: impl IntoQueryParam, - ) -> Option>> { + ) -> Option>> { Some(self.impl_trait_header(def_id)?.trait_ref) } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index d432aeada2c..b5b36cbd1ba 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -3,7 +3,9 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use tracing::{debug, instrument}; -pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use rustc_type_ir::fold::{ + shift_region, shift_vars, FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, +}; /////////////////////////////////////////////////////////////////////////// // Some sample folders @@ -412,103 +414,3 @@ impl<'tcx> TyCtxt<'tcx> { Binder::bind_with_vars(inner, bound_vars) } } - -/////////////////////////////////////////////////////////////////////////// -// Shifter -// -// Shifts the De Bruijn indices on all escaping bound vars by a -// fixed amount. Useful in instantiation or when otherwise introducing -// a binding level that is not intended to capture the existing bound -// vars. See comment on `shift_vars_through_binders` method in -// `rustc_middle/src/ty/generic_args.rs` for more details. - -struct Shifter<'tcx> { - tcx: TyCtxt<'tcx>, - current_index: ty::DebruijnIndex, - amount: u32, -} - -impl<'tcx> Shifter<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, amount: u32) -> Self { - Shifter { tcx, current_index: ty::INNERMOST, amount } - } -} - -impl<'tcx> TypeFolder> for Shifter<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.current_index.shift_in(1); - let t = t.super_fold_with(self); - self.current_index.shift_out(1); - t - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReBound(debruijn, br) if debruijn >= self.current_index => { - let debruijn = debruijn.shifted_in(self.amount); - ty::Region::new_bound(self.tcx, debruijn, br) - } - _ => r, - } - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { - let debruijn = debruijn.shifted_in(self.amount); - Ty::new_bound(self.tcx, debruijn, bound_ty) - } - - _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), - _ => ty, - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Bound(debruijn, bound_ct) = ct.kind() - && debruijn >= self.current_index - { - let debruijn = debruijn.shifted_in(self.amount); - ty::Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) - } else { - ct.super_fold_with(self) - } - } - - fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { - if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } - } -} - -pub fn shift_region<'tcx>( - tcx: TyCtxt<'tcx>, - region: ty::Region<'tcx>, - amount: u32, -) -> ty::Region<'tcx> { - match *region { - ty::ReBound(debruijn, br) if amount > 0 => { - ty::Region::new_bound(tcx, debruijn.shifted_in(amount), br) - } - _ => region, - } -} - -pub fn shift_vars<'tcx, T>(tcx: TyCtxt<'tcx>, value: T, amount: u32) -> T -where - T: TypeFoldable>, -{ - debug!("shift_vars(value={:?}, amount={})", value, amount); - - if amount == 0 || !value.has_escaping_bound_vars() { - return value; - } - - value.fold_with(&mut Shifter::new(tcx, amount)) -} diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c7b15c64b08..7a516b9f2c8 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -1,10 +1,10 @@ // Generic arguments. use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::sty::{ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs}; -use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; +use crate::ty::visit::{TypeVisitable, TypeVisitor}; +use crate::ty::{self, Lift, List, Ty, TyCtxt}; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::walk_visitable_list; @@ -12,19 +12,15 @@ use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; use rustc_macros::extension; -use rustc_macros::{ - Decodable, Encodable, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, -}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; -use tracing::debug; use core::intrinsics; use std::marker::PhantomData; use std::mem; use std::num::NonZero; -use std::ops::Deref; use std::ptr::NonNull; pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind>; @@ -576,490 +572,6 @@ impl<'tcx, T: TypeVisitable>> TypeVisitable> for &'tcx } } -/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo(T)` -/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call -/// `instantiate`. -/// -/// If you don't have anything to `instantiate`, you may be looking for -/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable)] -pub struct EarlyBinder { - value: T, -} - -/// For early binders, you should first call `instantiate` before using any visitors. -impl<'tcx, T> !TypeFoldable> for ty::EarlyBinder {} -impl<'tcx, T> !TypeVisitable> for ty::EarlyBinder {} - -impl EarlyBinder { - pub fn bind(value: T) -> EarlyBinder { - EarlyBinder { value } - } - - pub fn as_ref(&self) -> EarlyBinder<&T> { - EarlyBinder { value: &self.value } - } - - pub fn map_bound_ref(&self, f: F) -> EarlyBinder - where - F: FnOnce(&T) -> U, - { - self.as_ref().map_bound(f) - } - - pub fn map_bound(self, f: F) -> EarlyBinder - where - F: FnOnce(T) -> U, - { - let value = f(self.value); - EarlyBinder { value } - } - - pub fn try_map_bound(self, f: F) -> Result, E> - where - F: FnOnce(T) -> Result, - { - let value = f(self.value)?; - Ok(EarlyBinder { value }) - } - - pub fn rebind(&self, value: U) -> EarlyBinder { - EarlyBinder { value } - } - - /// Skips the binder and returns the "bound" value. - /// This can be used to extract data that does not depend on generic parameters - /// (e.g., getting the `DefId` of the inner value or getting the number of - /// arguments of an `FnSig`). Otherwise, consider using - /// [`instantiate_identity`](EarlyBinder::instantiate_identity). - /// - /// To skip the binder on `x: &EarlyBinder` to obtain `&T`, leverage - /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. - /// - /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is - /// the analogous operation on [`super::Binder`]. - pub fn skip_binder(self) -> T { - self.value - } -} - -impl EarlyBinder> { - pub fn transpose(self) -> Option> { - self.value.map(|value| EarlyBinder { value }) - } -} - -impl<'tcx, 's, I: IntoIterator> EarlyBinder -where - I::Item: TypeFoldable>, -{ - pub fn iter_instantiated( - self, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], - ) -> IterInstantiated<'s, 'tcx, I> { - IterInstantiated { it: self.value.into_iter(), tcx, args } - } - - /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), - /// but on an iterator of `TypeFoldable` values. - pub fn instantiate_identity_iter(self) -> I::IntoIter { - self.value.into_iter() - } -} - -pub struct IterInstantiated<'s, 'tcx, I: IntoIterator> { - it: I::IntoIter, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], -} - -impl<'tcx, I: IntoIterator> Iterator for IterInstantiated<'_, 'tcx, I> -where - I::Item: TypeFoldable>, -{ - type Item = I::Item; - - fn next(&mut self) -> Option { - Some(EarlyBinder { value: self.it.next()? }.instantiate(self.tcx, self.args)) - } - - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } -} - -impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiated<'_, 'tcx, I> -where - I::IntoIter: DoubleEndedIterator, - I::Item: TypeFoldable>, -{ - fn next_back(&mut self) -> Option { - Some(EarlyBinder { value: self.it.next_back()? }.instantiate(self.tcx, self.args)) - } -} - -impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiated<'_, 'tcx, I> -where - I::IntoIter: ExactSizeIterator, - I::Item: TypeFoldable>, -{ -} - -impl<'tcx, 's, I: IntoIterator> EarlyBinder -where - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - pub fn iter_instantiated_copied( - self, - tcx: TyCtxt<'tcx>, - args: &'s [GenericArg<'tcx>], - ) -> IterInstantiatedCopied<'s, 'tcx, I> { - IterInstantiatedCopied { it: self.value.into_iter(), tcx, args } - } - - /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), - /// but on an iterator of values that deref to a `TypeFoldable`. - pub fn instantiate_identity_iter_copied( - self, - ) -> impl Iterator::Target> { - self.value.into_iter().map(|v| *v) - } -} - -pub struct IterInstantiatedCopied<'a, 'tcx, I: IntoIterator> { - it: I::IntoIter, - tcx: TyCtxt<'tcx>, - args: &'a [GenericArg<'tcx>], -} - -impl<'tcx, I: IntoIterator> Iterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - type Item = ::Target; - - fn next(&mut self) -> Option { - self.it.next().map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) - } - - fn size_hint(&self) -> (usize, Option) { - self.it.size_hint() - } -} - -impl<'tcx, I: IntoIterator> DoubleEndedIterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::IntoIter: DoubleEndedIterator, - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ - fn next_back(&mut self) -> Option { - self.it - .next_back() - .map(|value| EarlyBinder { value: *value }.instantiate(self.tcx, self.args)) - } -} - -impl<'tcx, I: IntoIterator> ExactSizeIterator for IterInstantiatedCopied<'_, 'tcx, I> -where - I::IntoIter: ExactSizeIterator, - I::Item: Deref, - ::Target: Copy + TypeFoldable>, -{ -} - -pub struct EarlyBinderIter { - t: T, -} - -impl EarlyBinder { - pub fn transpose_iter(self) -> EarlyBinderIter { - EarlyBinderIter { t: self.value.into_iter() } - } -} - -impl Iterator for EarlyBinderIter { - type Item = EarlyBinder; - - fn next(&mut self) -> Option { - self.t.next().map(|value| EarlyBinder { value }) - } - - fn size_hint(&self) -> (usize, Option) { - self.t.size_hint() - } -} - -impl<'tcx, T: TypeFoldable>> ty::EarlyBinder { - pub fn instantiate(self, tcx: TyCtxt<'tcx>, args: &[GenericArg<'tcx>]) -> T { - let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; - self.value.fold_with(&mut folder) - } - - /// Makes the identity replacement `T0 => T0, ..., TN => TN`. - /// Conceptually, this converts universally bound variables into placeholders - /// when inside of a given item. - /// - /// For example, consider `for fn foo(){ .. }`: - /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). - /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling - /// `instantiate_identity` to discharge the `EarlyBinder`. - pub fn instantiate_identity(self) -> T { - self.value - } - - /// Returns the inner value, but only if it contains no bound vars. - pub fn no_bound_vars(self) -> Option { - if !self.value.has_param() { Some(self.value) } else { None } - } -} - -/////////////////////////////////////////////////////////////////////////// -// The actual instantiation engine itself is a type folder. - -struct ArgFolder<'a, 'tcx> { - tcx: TyCtxt<'tcx>, - args: &'a [GenericArg<'tcx>], - - /// Number of region binders we have passed through while doing the instantiation - binders_passed: u32, -} - -impl<'a, 'tcx> TypeFolder> for ArgFolder<'a, 'tcx> { - #[inline] - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn fold_binder>>( - &mut self, - t: ty::Binder<'tcx, T>, - ) -> ty::Binder<'tcx, T> { - self.binders_passed += 1; - let t = t.super_fold_with(self); - self.binders_passed -= 1; - t - } - - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - #[cold] - #[inline(never)] - fn region_param_out_of_range(data: ty::EarlyParamRegion, args: &[GenericArg<'_>]) -> ! { - bug!( - "Region parameter out of range when instantiating in region {} (index={}, args = {:?})", - data.name, - data.index, - args, - ) - } - - #[cold] - #[inline(never)] - fn region_param_invalid(data: ty::EarlyParamRegion, other: GenericArgKind<'_>) -> ! { - bug!( - "Unexpected parameter {:?} when instantiating in region {} (index={})", - other, - data.name, - data.index - ) - } - - // Note: This routine only handles regions that are bound on - // type declarations and other outer declarations, not those - // bound in *fn types*. Region instantiation of the bound - // regions that appear in a function signature is done using - // the specialized routine `ty::replace_late_regions()`. - match *r { - ty::ReEarlyParam(data) => { - let rk = self.args.get(data.index as usize).map(|k| k.unpack()); - match rk { - Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), - Some(other) => region_param_invalid(data, other), - None => region_param_out_of_range(data, self.args), - } - } - ty::ReBound(..) - | ty::ReLateParam(_) - | ty::ReStatic - | ty::RePlaceholder(_) - | ty::ReErased - | ty::ReError(_) => r, - ty::ReVar(_) => bug!("unexpected region: {r:?}"), - } - } - - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_param() { - return t; - } - - match *t.kind() { - ty::Param(p) => self.ty_for_param(p, t), - _ => t.super_fold_with(self), - } - } - - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Param(p) = c.kind() { - self.const_for_param(p, c) - } else { - c.super_fold_with(self) - } - } -} - -impl<'a, 'tcx> ArgFolder<'a, 'tcx> { - fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { - // Look up the type in the args. It really should be in there. - let opt_ty = self.args.get(p.index as usize).map(|k| k.unpack()); - let ty = match opt_ty { - Some(GenericArgKind::Type(ty)) => ty, - Some(kind) => self.type_param_expected(p, source_ty, kind), - None => self.type_param_out_of_range(p, source_ty), - }; - - self.shift_vars_through_binders(ty) - } - - #[cold] - #[inline(never)] - fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! { - bug!( - "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", - p, - ty, - p.index, - kind, - self.args, - ) - } - - #[cold] - #[inline(never)] - fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! { - bug!( - "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", - p, - ty, - p.index, - self.args, - ) - } - - fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - // Look up the const in the args. It really should be in there. - let opt_ct = self.args.get(p.index as usize).map(|k| k.unpack()); - let ct = match opt_ct { - Some(GenericArgKind::Const(ct)) => ct, - Some(kind) => self.const_param_expected(p, source_ct, kind), - None => self.const_param_out_of_range(p, source_ct), - }; - - self.shift_vars_through_binders(ct) - } - - #[cold] - #[inline(never)] - fn const_param_expected( - &self, - p: ty::ParamConst, - ct: ty::Const<'tcx>, - kind: GenericArgKind<'tcx>, - ) -> ! { - bug!( - "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", - p, - ct, - p.index, - kind, - self.args, - ) - } - - #[cold] - #[inline(never)] - fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! { - bug!( - "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", - p, - ct, - p.index, - self.args, - ) - } - - /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs - /// when we are instantating a type with escaping bound vars into a context where we have - /// passed through binders. That's quite a mouthful. Let's see an example: - /// - /// ``` - /// type Func = fn(A); - /// type MetaFunc = for<'a> fn(Func<&'a i32>); - /// ``` - /// - /// The type `MetaFunc`, when fully expanded, will be - /// ```ignore (illustrative) - /// for<'a> fn(fn(&'a i32)) - /// // ^~ ^~ ^~~ - /// // | | | - /// // | | DebruijnIndex of 2 - /// // Binders - /// ``` - /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the - /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip - /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the - /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a - /// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the - /// depth by 1 to account for the binder that we passed through. - /// - /// As a second example, consider this twist: - /// - /// ``` - /// type FuncTuple = (A,fn(A)); - /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>); - /// ``` - /// - /// Here the final type will be: - /// ```ignore (illustrative) - /// for<'a> fn((&'a i32, fn(&'a i32))) - /// // ^~~ ^~~ - /// // | | - /// // DebruijnIndex of 1 | - /// // DebruijnIndex of 2 - /// ``` - /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the - /// first case we do not increase the De Bruijn index and in the second case we do. The reason - /// is that only in the second case have we passed through a fn binder. - fn shift_vars_through_binders>>(&self, val: T) -> T { - debug!( - "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", - val, - self.binders_passed, - val.has_escaping_bound_vars() - ); - - if self.binders_passed == 0 || !val.has_escaping_bound_vars() { - return val; - } - - let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); - debug!("shift_vars: shifted result = {:?}", result); - - result - } - - fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { - if self.binders_passed == 0 || !region.has_escaping_bound_vars() { - return region; - } - ty::fold::shift_region(self.tcx, region, self.binders_passed) - } -} - /// Stores the user-given args to reach some fully qualified path /// (e.g., `::Item` or `::Item`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 69a86bda43b..89ba8cd2ad4 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -88,7 +88,7 @@ impl GenericParamDef { pub fn default_value<'tcx>( &self, tcx: TyCtxt<'tcx>, - ) -> Option>> { + ) -> Option>> { match self.kind { GenericParamDefKind::Type { has_default, .. } if has_default => { Some(tcx.type_of(self.def_id).map_bound(|t| t.into())) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 7da7f69a954..a887047f62f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -764,7 +764,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T where T: TypeFoldable> + Copy, { @@ -782,7 +782,7 @@ impl<'tcx> Instance<'tcx> { &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - v: EarlyBinder, + v: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, @@ -800,7 +800,7 @@ impl<'tcx> Instance<'tcx> { &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - v: EarlyBinder, + v: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 79cfeb71d47..f24074cb472 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -114,9 +114,9 @@ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, - CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, - VarianceDiagInfo, + CoroutineClosureArgsParts, CoroutineClosureSignature, EarlyBinder, FnSig, GenSig, + InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, + UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -266,7 +266,7 @@ pub struct ImplHeader<'tcx> { #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ImplTraitHeader<'tcx> { - pub trait_ref: ty::EarlyBinder>, + pub trait_ref: ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>, pub polarity: ImplPolarity, pub safety: hir::Safety, } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e2cfabfdafa..fb16cf5bd36 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -125,7 +125,7 @@ impl<'tcx> TyCtxt<'tcx> { self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: EarlyBinder, + value: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable>, @@ -143,7 +143,7 @@ impl<'tcx> TyCtxt<'tcx> { self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, - value: EarlyBinder, + value: EarlyBinder<'tcx, T>, ) -> Result> where T: TypeFoldable>, diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 571c6e918dc..f394b3c990c 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -33,8 +33,8 @@ impl ParameterizedOverTcx for ty::Binder<'static, T> { type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>; } -impl ParameterizedOverTcx for ty::EarlyBinder { - type Value<'tcx> = ty::EarlyBinder>; +impl ParameterizedOverTcx for ty::EarlyBinder<'static, T> { + type Value<'tcx> = ty::EarlyBinder<'tcx, T::Value<'tcx>>; } #[macro_export] diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 0807cbf91d1..4e85af90170 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -138,6 +138,14 @@ impl<'tcx> Region<'tcx> { } impl<'tcx> rustc_type_ir::inherent::Region> for Region<'tcx> { + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + var: ty::BoundRegion, + ) -> Self { + Region::new_bound(interner, debruijn, var) + } + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }) } @@ -327,6 +335,12 @@ pub struct EarlyParamRegion { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for EarlyParamRegion { + fn index(self) -> u32 { + self.index + } +} + impl std::fmt::Debug for EarlyParamRegion { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/#{}", self.name, self.index) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 40f3db89df5..5cf96d29837 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -40,6 +40,7 @@ pub type TypeAndMut<'tcx> = ir::TypeAndMut>; pub type AliasTy<'tcx> = ir::AliasTy>; pub type FnSig<'tcx> = ir::FnSig>; pub type Binder<'tcx, T> = ir::Binder, T>; +pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub trait Article { fn article(&self) -> &'static str; @@ -954,6 +955,12 @@ pub struct ParamTy { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for ParamTy { + fn index(self) -> u32 { + self.index + } +} + impl<'tcx> ParamTy { pub fn new(index: u32, name: Symbol) -> ParamTy { ParamTy { index, name } @@ -982,6 +989,12 @@ pub struct ParamConst { pub name: Symbol, } +impl rustc_type_ir::inherent::ParamLike for ParamConst { + fn index(self) -> u32 { + self.index + } +} + impl ParamConst { pub fn new(index: u32, name: Symbol) -> ParamConst { ParamConst { index, name } @@ -1423,6 +1436,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_var(tcx, vid) } + fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundTy) -> Self { + Ty::new_bound(interner, debruijn, var) + } + 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 }) } @@ -2055,7 +2072,7 @@ impl<'tcx> Ty<'tcx> { fn async_destructor_combinator( tcx: TyCtxt<'tcx>, lang_item: LangItem, - ) -> ty::EarlyBinder> { + ) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { tcx.fn_sig(tcx.require_lang_item(lang_item, None)) .map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap()) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 5a3d90221eb..cacaa859d52 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -694,7 +694,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn coroutine_hidden_types( self, def_id: DefId, - ) -> impl Iterator>> { + ) -> impl Iterator>> { let coroutine_layout = self.mir_coroutine_witnesses(def_id); coroutine_layout .as_ref() @@ -709,7 +709,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn bound_coroutine_hidden_types( self, def_id: DefId, - ) -> impl Iterator>>> { + ) -> impl Iterator>>> { let coroutine_layout = self.mir_coroutine_witnesses(def_id); coroutine_layout .as_ref() diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 79f36cfe569..4ae475d35d1 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -23,7 +23,7 @@ impl<'tcx> Value> for Ty<'_> { } } -impl<'tcx> Value> for Result>, CyclePlaceholder> { +impl<'tcx> Value> for Result>, CyclePlaceholder> { fn from_cycle_error(_tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self { Err(CyclePlaceholder(guar)) } @@ -111,7 +111,7 @@ impl<'tcx> Value> for Representability { } } -impl<'tcx> Value> for ty::EarlyBinder> { +impl<'tcx> Value> for ty::EarlyBinder<'_, Ty<'_>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, @@ -121,7 +121,7 @@ impl<'tcx> Value> for ty::EarlyBinder> { } } -impl<'tcx> Value> for ty::EarlyBinder>> { +impl<'tcx> Value> for ty::EarlyBinder<'_, ty::Binder<'_, ty::FnSig<'_>>> { fn from_cycle_error( tcx: TyCtxt<'tcx>, cycle_error: &CycleError, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index a511989d972..66708def00f 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -194,7 +194,7 @@ where } } -impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder +impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<'tcx, S> where S: Stable<'tcx, T = V>, { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 77ac4be35ea..87c8b1cda50 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2097,7 +2097,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node); let ty = tcx.type_of(assoc_ty.item.def_id); let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); - let term: ty::EarlyBinder> = if is_const { + let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const { let did = assoc_ty.item.def_id; let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did); let uv = ty::UnevaluatedConst::new(did, identity_args); diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 67ffb8a58b5..58447f6d6a3 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -398,10 +398,10 @@ impl<'a, 'tcx> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> { } /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead. -fn thir_abstract_const( - tcx: TyCtxt<'_>, +fn thir_abstract_const<'tcx>( + tcx: TyCtxt<'tcx>, def: LocalDefId, -) -> Result>>, ErrorGuaranteed> { +) -> Result>>, ErrorGuaranteed> { if !tcx.features().generic_const_exprs { return Ok(None); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 617e8a54365..38950c97c9d 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -77,7 +77,7 @@ fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { fn adt_sized_constraint<'tcx>( tcx: TyCtxt<'tcx>, def_id: DefId, -) -> Option>> { +) -> Option>> { if let Some(def_id) = def_id.as_local() { if let ty::Representability::Infinite(_) = tcx.representability(def_id) { return None; @@ -253,7 +253,7 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE fn self_ty_of_trait_impl_enabling_order_dep_trait_object_hack( tcx: TyCtxt<'_>, def_id: DefId, -) -> Option>> { +) -> Option>> { let impl_ = tcx.impl_trait_header(def_id).unwrap_or_else(|| bug!("called on inherent impl {def_id:?}")); diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index cef3f4e8ce0..18a09067a2c 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -15,6 +15,7 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", default-features = false } +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 5336b915a1d..e50d59ba5f0 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,12 +1,14 @@ use std::fmt::Debug; use std::hash::Hash; +use std::marker::PhantomData; use std::ops::{ControlFlow, Deref}; #[cfg(feature = "nightly")] -use rustc_macros::HashStable_NoContext; +use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_serialize::Decodable; +use tracing::debug; -use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; +use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; use crate::lift::Lift; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; @@ -338,3 +340,516 @@ impl TypeVisitor for ValidateBoundVars { ControlFlow::Continue(()) } } + +/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo(T)` +/// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call +/// `instantiate`. +/// +/// If you don't have anything to `instantiate`, you may be looking for +/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder). +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = "T: Clone"), + Copy(bound = "T: Copy"), + PartialEq(bound = "T: PartialEq"), + Eq(bound = "T: Eq"), + Ord(bound = "T: Ord"), + PartialOrd(bound = "T: Ord"), + Hash(bound = "T: Hash"), + Debug(bound = "T: Debug") +)] +#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +pub struct EarlyBinder { + value: T, + _tcx: PhantomData, +} + +/// For early binders, you should first call `instantiate` before using any visitors. +#[cfg(feature = "nightly")] +impl !TypeFoldable for ty::EarlyBinder {} + +/// For early binders, you should first call `instantiate` before using any visitors. +#[cfg(feature = "nightly")] +impl !TypeVisitable for ty::EarlyBinder {} + +impl EarlyBinder { + pub fn bind(value: T) -> EarlyBinder { + EarlyBinder { value, _tcx: PhantomData } + } + + pub fn as_ref(&self) -> EarlyBinder { + EarlyBinder { value: &self.value, _tcx: PhantomData } + } + + pub fn map_bound_ref(&self, f: F) -> EarlyBinder + where + F: FnOnce(&T) -> U, + { + self.as_ref().map_bound(f) + } + + pub fn map_bound(self, f: F) -> EarlyBinder + where + F: FnOnce(T) -> U, + { + let value = f(self.value); + EarlyBinder { value, _tcx: PhantomData } + } + + pub fn try_map_bound(self, f: F) -> Result, E> + where + F: FnOnce(T) -> Result, + { + let value = f(self.value)?; + Ok(EarlyBinder { value, _tcx: PhantomData }) + } + + pub fn rebind(&self, value: U) -> EarlyBinder { + EarlyBinder { value, _tcx: PhantomData } + } + + /// Skips the binder and returns the "bound" value. + /// This can be used to extract data that does not depend on generic parameters + /// (e.g., getting the `DefId` of the inner value or getting the number of + /// arguments of an `FnSig`). Otherwise, consider using + /// [`instantiate_identity`](EarlyBinder::instantiate_identity). + /// + /// To skip the binder on `x: &EarlyBinder` to obtain `&T`, leverage + /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. + /// + /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is + /// the analogous operation on [`super::Binder`]. + pub fn skip_binder(self) -> T { + self.value + } +} + +impl EarlyBinder> { + pub fn transpose(self) -> Option> { + self.value.map(|value| EarlyBinder { value, _tcx: PhantomData }) + } +} + +impl<'s, I: Interner, Iter: IntoIterator> EarlyBinder +where + Iter::Item: TypeFoldable, +{ + pub fn iter_instantiated( + self, + tcx: I, + args: &'s [I::GenericArg], + ) -> IterInstantiated<'s, I, Iter> { + IterInstantiated { it: self.value.into_iter(), tcx, args } + } + + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), + /// but on an iterator of `TypeFoldable` values. + pub fn instantiate_identity_iter(self) -> Iter::IntoIter { + self.value.into_iter() + } +} + +pub struct IterInstantiated<'s, I: Interner, Iter: IntoIterator> { + it: Iter::IntoIter, + tcx: I, + args: &'s [I::GenericArg], +} + +impl Iterator for IterInstantiated<'_, I, Iter> +where + Iter::Item: TypeFoldable, +{ + type Item = Iter::Item; + + fn next(&mut self) -> Option { + Some( + EarlyBinder { value: self.it.next()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedIterator for IterInstantiated<'_, I, Iter> +where + Iter::IntoIter: DoubleEndedIterator, + Iter::Item: TypeFoldable, +{ + fn next_back(&mut self) -> Option { + Some( + EarlyBinder { value: self.it.next_back()?, _tcx: PhantomData } + .instantiate(self.tcx, self.args), + ) + } +} + +impl ExactSizeIterator for IterInstantiated<'_, I, Iter> +where + Iter::IntoIter: ExactSizeIterator, + Iter::Item: TypeFoldable, +{ +} + +impl<'s, I: Interner, Iter: IntoIterator> EarlyBinder +where + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + pub fn iter_instantiated_copied( + self, + tcx: I, + args: &'s [I::GenericArg], + ) -> IterInstantiatedCopied<'s, I, Iter> { + IterInstantiatedCopied { it: self.value.into_iter(), tcx, args } + } + + /// Similar to [`instantiate_identity`](EarlyBinder::instantiate_identity), + /// but on an iterator of values that deref to a `TypeFoldable`. + pub fn instantiate_identity_iter_copied( + self, + ) -> impl Iterator::Target> { + self.value.into_iter().map(|v| *v) + } +} + +pub struct IterInstantiatedCopied<'a, I: Interner, Iter: IntoIterator> { + it: Iter::IntoIter, + tcx: I, + args: &'a [I::GenericArg], +} + +impl Iterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + type Item = ::Target; + + fn next(&mut self) -> Option { + self.it.next().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) + } + + fn size_hint(&self) -> (usize, Option) { + self.it.size_hint() + } +} + +impl DoubleEndedIterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::IntoIter: DoubleEndedIterator, + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ + fn next_back(&mut self) -> Option { + self.it.next_back().map(|value| { + EarlyBinder { value: *value, _tcx: PhantomData }.instantiate(self.tcx, self.args) + }) + } +} + +impl ExactSizeIterator for IterInstantiatedCopied<'_, I, Iter> +where + Iter::IntoIter: ExactSizeIterator, + Iter::Item: Deref, + ::Target: Copy + TypeFoldable, +{ +} + +pub struct EarlyBinderIter { + t: T, + _tcx: PhantomData, +} + +impl EarlyBinder { + pub fn transpose_iter(self) -> EarlyBinderIter { + EarlyBinderIter { t: self.value.into_iter(), _tcx: PhantomData } + } +} + +impl Iterator for EarlyBinderIter { + type Item = EarlyBinder; + + fn next(&mut self) -> Option { + self.t.next().map(|value| EarlyBinder { value, _tcx: PhantomData }) + } + + fn size_hint(&self) -> (usize, Option) { + self.t.size_hint() + } +} + +impl> ty::EarlyBinder { + pub fn instantiate(self, tcx: I, args: &[I::GenericArg]) -> T { + let mut folder = ArgFolder { tcx, args, binders_passed: 0 }; + self.value.fold_with(&mut folder) + } + + /// Makes the identity replacement `T0 => T0, ..., TN => TN`. + /// Conceptually, this converts universally bound variables into placeholders + /// when inside of a given item. + /// + /// For example, consider `for fn foo(){ .. }`: + /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). + /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling + /// `instantiate_identity` to discharge the `EarlyBinder`. + pub fn instantiate_identity(self) -> T { + self.value + } + + /// Returns the inner value, but only if it contains no bound vars. + pub fn no_bound_vars(self) -> Option { + if !self.value.has_param() { Some(self.value) } else { None } + } +} + +/////////////////////////////////////////////////////////////////////////// +// The actual instantiation engine itself is a type folder. + +struct ArgFolder<'a, I: Interner> { + tcx: I, + args: &'a [I::GenericArg], + + /// Number of region binders we have passed through while doing the instantiation + binders_passed: u32, +} + +impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { + #[inline] + fn interner(&self) -> I { + self.tcx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + self.binders_passed += 1; + let t = t.super_fold_with(self); + self.binders_passed -= 1; + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + // Note: This routine only handles regions that are bound on + // type declarations and other outer declarations, not those + // bound in *fn types*. Region instantiation of the bound + // regions that appear in a function signature is done using + // the specialized routine `ty::replace_late_regions()`. + match r.kind() { + ty::ReEarlyParam(data) => { + let rk = self.args.get(data.index() as usize).map(|k| k.kind()); + match rk { + Some(ty::GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), + Some(other) => self.region_param_expected(data, r, other), + None => self.region_param_out_of_range(data, r), + } + } + ty::ReBound(..) + | ty::ReLateParam(_) + | ty::ReStatic + | ty::RePlaceholder(_) + | ty::ReErased + | ty::ReError(_) => r, + ty::ReVar(_) => panic!("unexpected region: {r:?}"), + } + } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if !t.has_param() { + return t; + } + + match t.kind() { + ty::Param(p) => self.ty_for_param(p, t), + _ => t.super_fold_with(self), + } + } + + fn fold_const(&mut self, c: I::Const) -> I::Const { + if let ty::ConstKind::Param(p) = c.kind() { + self.const_for_param(p, c) + } else { + c.super_fold_with(self) + } + } +} + +impl<'a, I: Interner> ArgFolder<'a, I> { + fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty { + // Look up the type in the args. It really should be in there. + let opt_ty = self.args.get(p.index() as usize).map(|k| k.kind()); + let ty = match opt_ty { + Some(ty::GenericArgKind::Type(ty)) => ty, + Some(kind) => self.type_param_expected(p, source_ty, kind), + None => self.type_param_out_of_range(p, source_ty), + }; + + self.shift_vars_through_binders(ty) + } + + #[cold] + #[inline(never)] + fn type_param_expected(&self, p: I::ParamTy, ty: I::Ty, kind: ty::GenericArgKind) -> ! { + panic!( + "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", + p, + ty, + p.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn type_param_out_of_range(&self, p: I::ParamTy, ty: I::Ty) -> ! { + panic!( + "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", + p, + ty, + p.index(), + self.args, + ) + } + + fn const_for_param(&self, p: I::ParamConst, source_ct: I::Const) -> I::Const { + // Look up the const in the args. It really should be in there. + let opt_ct = self.args.get(p.index() as usize).map(|k| k.kind()); + let ct = match opt_ct { + Some(ty::GenericArgKind::Const(ct)) => ct, + Some(kind) => self.const_param_expected(p, source_ct, kind), + None => self.const_param_out_of_range(p, source_ct), + }; + + self.shift_vars_through_binders(ct) + } + + #[cold] + #[inline(never)] + fn const_param_expected( + &self, + p: I::ParamConst, + ct: I::Const, + kind: ty::GenericArgKind, + ) -> ! { + panic!( + "expected const for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", + p, + ct, + p.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn const_param_out_of_range(&self, p: I::ParamConst, ct: I::Const) -> ! { + panic!( + "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", + p, + ct, + p.index(), + self.args, + ) + } + + #[cold] + #[inline(never)] + fn region_param_expected( + &self, + ebr: I::EarlyParamRegion, + r: I::Region, + kind: ty::GenericArgKind, + ) -> ! { + panic!( + "expected region for `{:?}` ({:?}/{}) but found {:?} when instantiating args={:?}", + ebr, + r, + ebr.index(), + kind, + self.args, + ) + } + + #[cold] + #[inline(never)] + fn region_param_out_of_range(&self, ebr: I::EarlyParamRegion, r: I::Region) -> ! { + panic!( + "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", + ebr, + r, + ebr.index(), + self.args, + ) + } + + /// It is sometimes necessary to adjust the De Bruijn indices during instantiation. This occurs + /// when we are instantating a type with escaping bound vars into a context where we have + /// passed through binders. That's quite a mouthful. Let's see an example: + /// + /// ``` + /// type Func = fn(A); + /// type MetaFunc = for<'a> fn(Func<&'a i32>); + /// ``` + /// + /// The type `MetaFunc`, when fully expanded, will be + /// ```ignore (illustrative) + /// for<'a> fn(fn(&'a i32)) + /// // ^~ ^~ ^~~ + /// // | | | + /// // | | DebruijnIndex of 2 + /// // Binders + /// ``` + /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the + /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip + /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the + /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a + /// De Bruijn index of 1. It's only during the instantiation that we can see we must increase the + /// depth by 1 to account for the binder that we passed through. + /// + /// As a second example, consider this twist: + /// + /// ``` + /// type FuncTuple = (A,fn(A)); + /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>); + /// ``` + /// + /// Here the final type will be: + /// ```ignore (illustrative) + /// for<'a> fn((&'a i32, fn(&'a i32))) + /// // ^~~ ^~~ + /// // | | + /// // DebruijnIndex of 1 | + /// // DebruijnIndex of 2 + /// ``` + /// As indicated in the diagram, here the same type `&'a i32` is instantiated once, but in the + /// first case we do not increase the De Bruijn index and in the second case we do. The reason + /// is that only in the second case have we passed through a fn binder. + fn shift_vars_through_binders>(&self, val: T) -> T { + debug!( + "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", + val, + self.binders_passed, + val.has_escaping_bound_vars() + ); + + if self.binders_passed == 0 || !val.has_escaping_bound_vars() { + return val; + } + + let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); + debug!("shift_vars: shifted result = {:?}", result); + + result + } + + fn shift_region_through_binders(&self, region: I::Region) -> I::Region { + if self.binders_passed == 0 || !region.has_escaping_bound_vars() { + return region; + } + ty::fold::shift_region(self.tcx, region, self.binders_passed) + } +} diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 405aba30241..501311ff72f 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -47,8 +47,10 @@ use rustc_index::{Idx, IndexVec}; use std::mem; +use tracing::debug; -use crate::visit::TypeVisitable; +use crate::inherent::*; +use crate::visit::{TypeVisitable, TypeVisitableExt as _}; use crate::{self as ty, Interner, Lrc}; #[cfg(feature = "nightly")] @@ -325,3 +327,95 @@ impl, Ix: Idx> TypeFoldable for IndexVec { + tcx: I, + current_index: ty::DebruijnIndex, + amount: u32, +} + +impl Shifter { + pub fn new(tcx: I, amount: u32) -> Self { + Shifter { tcx, current_index: ty::INNERMOST, amount } + } +} + +impl TypeFolder for Shifter { + fn interner(&self) -> I { + self.tcx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReBound(debruijn, br) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Region::new_bound(self.tcx, debruijn, br) + } + _ => r, + } + } + + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + match ty.kind() { + ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Ty::new_bound(self.tcx, debruijn, bound_ty) + } + + _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self), + _ => ty, + } + } + + fn fold_const(&mut self, ct: I::Const) -> I::Const { + match ct.kind() { + ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => { + let debruijn = debruijn.shifted_in(self.amount); + Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) + } + _ => ct.super_fold_with(self), + } + } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p } + } +} + +pub fn shift_region(tcx: I, region: I::Region, amount: u32) -> I::Region { + match region.kind() { + ty::ReBound(debruijn, br) if amount > 0 => { + Region::new_bound(tcx, debruijn.shifted_in(amount), br) + } + _ => region, + } +} + +pub fn shift_vars(tcx: I, value: T, amount: u32) -> T +where + T: TypeFoldable, +{ + debug!("shift_vars(value={:?}, amount={})", value, amount); + + if amount == 0 || !value.has_escaping_bound_vars() { + return value; + } + + value.fold_with(&mut Shifter::new(tcx, amount)) +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 77fe30a4660..e7e893f27da 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -29,6 +29,8 @@ pub trait Ty>: fn new_var(interner: I, var: ty::TyVid) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self; + fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; @@ -65,7 +67,10 @@ pub trait Region>: + Into + IntoKind> + Flags + + TypeVisitable { + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self; + fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; fn new_static(interner: I) -> Self; @@ -87,6 +92,8 @@ pub trait Const>: fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst, ty: I::Ty) -> Self; + fn new_anon_bound( interner: I, debruijn: ty::DebruijnIndex, @@ -162,3 +169,7 @@ pub trait BoundVarLike { fn assert_eq(self, var: I::BoundVarKind); } + +pub trait ParamLike { + fn index(self) -> u32; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c77414afc52..e49db171a53 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -7,26 +7,22 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{ - AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, - DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, FnSig, GenericArgKind, - NormalizesTo, ProjectionPredicate, SubtypePredicate, TermKind, TraitPredicate, TraitRef, -}; +use crate::{self as ty, DebugWithInfcx}; pub trait Interner: Sized + Copy - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> - + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> { type DefId: Copy + Debug + Hash + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; @@ -39,9 +35,9 @@ pub trait Interner: + DebugWithInfcx + Hash + Eq - + IntoKind> + + IntoKind> + TypeVisitable; - type Term: Copy + Debug + Hash + Eq + IntoKind> + TypeVisitable; + type Term: Copy + Debug + Hash + Eq + IntoKind> + TypeVisitable; type BoundVarKinds: Copy + Debug @@ -51,7 +47,7 @@ pub trait Interner: + Default; type BoundVarKind: Copy + Debug + Hash + Eq; - type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; + type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; type PredefinedOpaques: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type ExternalConstraints: Copy + Debug + Hash + Eq; @@ -65,7 +61,7 @@ pub trait Interner: type Ty: Ty; type Tys: Tys; type FnInputTys: Copy + Debug + Hash + Eq + Deref + TypeVisitable; - type ParamTy: Copy + Debug + Hash + Eq; + type ParamTy: Copy + Debug + Hash + Eq + ParamLike; type BoundTy: Copy + Debug + Hash + Eq + BoundVarLike; type PlaceholderTy: PlaceholderLike; @@ -81,14 +77,14 @@ pub trait Interner: // Kinds of consts type Const: Const; type PlaceholderConst: PlaceholderLike; - type ParamConst: Copy + Debug + Hash + Eq; + type ParamConst: Copy + Debug + Hash + Eq + ParamLike; type BoundConst: Copy + Debug + Hash + Eq + BoundVarLike; type ValueConst: Copy + Debug + Hash + Eq; type ExprConst: Copy + DebugWithInfcx + Hash + Eq; // Kinds of regions type Region: Region; - type EarlyParamRegion: Copy + Debug + Hash + Eq; + type EarlyParamRegion: Copy + Debug + Hash + Eq + ParamLike; type LateParamRegion: Copy + Debug + Hash + Eq; type BoundRegion: Copy + Debug + Hash + Eq + BoundVarLike; type PlaceholderRegion: PlaceholderLike; @@ -99,23 +95,23 @@ pub trait Interner: type Clause: Clause; type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; - fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo]) -> Self::CanonicalVars; + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars; type GenericsOf: GenericsOf; fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf; // FIXME: Remove after uplifting `EarlyBinder` - fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty; + fn type_of(self, def_id: Self::DefId) -> ty::EarlyBinder; - fn alias_ty_kind(self, alias: AliasTy) -> AliasTyKind; + fn alias_ty_kind(self, alias: ty::AliasTy) -> ty::AliasTyKind; - fn alias_term_kind(self, alias: AliasTerm) -> AliasTermKind; + fn alias_term_kind(self, alias: ty::AliasTerm) -> ty::AliasTermKind; fn trait_ref_and_own_args_for_alias( self, def_id: Self::DefId, args: Self::GenericArgs, - ) -> (TraitRef, Self::OwnItemArgs); + ) -> (ty::TraitRef, Self::OwnItemArgs); fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 4a461b5b5f3..217c056d0ba 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,6 +1,6 @@ #![cfg_attr( feature = "nightly", - feature(associated_type_defaults, min_specialization, never_type, rustc_attrs) + feature(associated_type_defaults, min_specialization, never_type, rustc_attrs, negative_impls) )] #![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 4e12c6b3d67..48a6f79993c 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -567,7 +567,7 @@ impl AliasTerm { I::Const::new_unevaluated( interner, ty::UnevaluatedConst::new(self.def_id, self.args), - interner.type_of_instantiated(self.def_id, self.args), + interner.type_of(self.def_id).instantiate(interner, &self.args), ) .into() }