From 77c83c09653f5c4437717e2e8aa7f10c1ff94fe4 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 20 Apr 2023 16:23:13 +0000 Subject: [PATCH 01/15] Add `impl_tag!` macro to implement `Tag` for tagged pointer easily --- .../rustc_data_structures/src/tagged_ptr.rs | 41 ++++- .../src/tagged_ptr/impl_tag.rs | 170 ++++++++++++++++++ .../src/tagged_ptr/impl_tag/tests.rs | 33 ++++ compiler/rustc_middle/src/ty/mod.rs | 29 +-- 4 files changed, 244 insertions(+), 29 deletions(-) create mode 100644 compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs create mode 100644 compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs index 8568aac67c08c..a25046986cc59 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr.rs @@ -24,6 +24,7 @@ use crate::aligned::Aligned; mod copy; mod drop; +mod impl_tag; pub use copy::CopyTaggedPtr; pub use drop::TaggedPtr; @@ -141,6 +142,40 @@ pub unsafe trait Tag: Copy { unsafe fn from_usize(tag: usize) -> Self; } +/// Returns the number of bits available for use for tags in a pointer to `T` +/// (this is based on `T`'s alignment). +pub const fn bits_for() -> u32 { + crate::aligned::align_of::().as_nonzero().trailing_zeros() +} + +/// Returns the correct [`Tag::BITS`] constant for a set of tag values. +pub const fn bits_for_tags(mut tags: &[usize]) -> u32 { + let mut bits = 0; + + while let &[tag, ref rest @ ..] = tags { + tags = rest; + + let b = bits_for_tag(tag); + if b > bits { + bits = b; + } + } + + bits +} + +/// Returns `(size_of::() * 8) - tag.leading_zeros()` +const fn bits_for_tag(mut tag: usize) -> u32 { + let mut bits = 0; + + while tag > 0 { + bits += 1; + tag >>= 1; + } + + bits +} + unsafe impl Pointer for Box { const BITS: u32 = bits_for::(); @@ -221,12 +256,6 @@ unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T { } } -/// Returns the number of bits available for use for tags in a pointer to `T` -/// (this is based on `T`'s alignment). -pub const fn bits_for() -> u32 { - crate::aligned::align_of::().as_nonzero().trailing_zeros() -} - /// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs new file mode 100644 index 0000000000000..deaaee4cc1728 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -0,0 +1,170 @@ +/// Implements [`Tag`] for a given type. +/// +/// You can use `impl_tag` on structs and enums. +/// You need to specify the type and all its possible values, +/// which can only be paths with optional fields. +/// +/// [`Tag`]: crate::tagged_ptr::Tag +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; +/// +/// #[derive(Copy, Clone, PartialEq, Debug)] +/// enum SomeTag { +/// A, +/// B, +/// X { v: bool }, +/// Y(bool, bool), +/// } +/// +/// impl_tag! { +/// // The type for which the `Tag` will be implemented +/// for SomeTag; +/// // You need to specify the `{value_of_the_type} <=> {tag}` relationship +/// SomeTag::A <=> 0, +/// SomeTag::B <=> 1, +/// // For variants with fields, you need to specify the fields: +/// SomeTag::X { v: true } <=> 2, +/// SomeTag::X { v: false } <=> 3, +/// // For tuple variants use named syntax: +/// SomeTag::Y { 0: true, 1: true } <=> 4, +/// SomeTag::Y { 0: false, 1: true } <=> 5, +/// SomeTag::Y { 0: true, 1: false } <=> 6, +/// SomeTag::Y { 0: false, 1: false } <=> 7, +/// } +/// +/// assert_eq!(SomeTag::A.into_usize(), 0); +/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); +/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); +/// +/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B); +/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true }); +/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false)); +/// ``` +/// +/// Structs are supported: +/// +/// ``` +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// struct Flags { a: bool, b: bool } +/// +/// impl_tag! { +/// for Flags; +/// Flags { a: true, b: true } <=> 3, +/// Flags { a: false, b: true } <=> 2, +/// Flags { a: true, b: false } <=> 1, +/// Flags { a: false, b: false } <=> 0, +/// } +/// ``` +/// +// This is supposed to produce a compile error, but does not, +// see for more information. +// +// Using the same pattern twice results in a compile error: +// +// ```compile_fail +// # use rustc_data_structures::impl_tag; +// #[derive(Copy, Clone)] +// struct Unit; +// +// impl_tag! { +// for Unit; +// Unit <=> 0, +// Unit <=> 1, +// } +// ``` +// +// Using the same tag twice results in a compile error: +// +// ```compile_fail +// # use rustc_data_structures::impl_tag; +// #[derive(Copy, Clone)] +// enum E { A, B }; +// +// impl_tag! { +// for E; +// E::A <=> 0, +// E::B <=> 0, +// } +// ``` +// +/// Not specifying all values results in a compile error: +/// +/// ```compile_fail,E0004 +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// enum E { +/// A, +/// B, +/// } +/// +/// impl_tag! { +/// for E; +/// E::A <=> 0, +/// } +/// ``` +#[macro_export] +macro_rules! impl_tag { + ( + for $Self:ty; + $( + $($path:ident)::* $( { $( $fields:tt )* })? <=> $tag:literal, + )* + ) => { + // Safety: + // `into_usize` only returns one of `$tag`s, + // `bits_for_tags` is called on all `$tag`s, + // thus `BITS` constant is correct. + unsafe impl $crate::tagged_ptr::Tag for $Self { + const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ + $( $tag, )* + ]); + + fn into_usize(self) -> usize { + // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) + // (or at least it should, see ) + #[forbid(unreachable_patterns)] + match self { + // `match` is doing heavy lifting here, by requiring exhaustiveness + $( + $($path)::* $( { $( $fields )* } )? => $tag, + )* + } + } + + unsafe fn from_usize(tag: usize) -> Self { + // Similarly to the above, this forbids repeating tags + // (or at least it should, see ) + #[forbid(unreachable_patterns)] + match tag { + $( + $tag => $($path)::* $( { $( $fields )* } )?, + )* + + // Safety: + // `into_usize` only returns one of `$tag`s, + // all `$tag`s are filtered up above, + // thus if this is reached, the safety contract of this + // function was already breached. + _ => unsafe { + debug_assert!( + false, + "invalid tag: {tag}\ + (this is a bug in the caller of `from_usize`)" + ); + std::hint::unreachable_unchecked() + }, + } + } + + } + }; +} + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs new file mode 100644 index 0000000000000..26d1cf3b45422 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs @@ -0,0 +1,33 @@ +#[test] +fn bits_constant() { + use crate::tagged_ptr::Tag; + + #[derive(Copy, Clone)] + struct Unit; + impl_tag! { for Unit; Unit <=> 0, } + assert_eq!(Unit::BITS, 0); + + #[derive(Copy, Clone)] + struct Unit1; + impl_tag! { for Unit1; Unit1 <=> 1, } + assert_eq!(Unit1::BITS, 1); + + #[derive(Copy, Clone)] + struct Unit2; + impl_tag! { for Unit2; Unit2 <=> 0b10, } + assert_eq!(Unit2::BITS, 2); + + #[derive(Copy, Clone)] + struct Unit3; + impl_tag! { for Unit3; Unit3 <=> 0b100, } + assert_eq!(Unit3::BITS, 3); + + #[derive(Copy, Clone)] + enum Enum { + A, + B, + C, + } + impl_tag! { for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, } + assert_eq!(Enum::BITS, 4); +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1061c32079305..f520faa6a6154 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1626,29 +1626,12 @@ struct ParamTag { constness: hir::Constness, } -unsafe impl rustc_data_structures::tagged_ptr::Tag for ParamTag { - const BITS: u32 = 2; - - #[inline] - fn into_usize(self) -> usize { - match self { - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } => 0, - Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } => 1, - Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } => 2, - Self { reveal: traits::Reveal::All, constness: hir::Constness::Const } => 3, - } - } - - #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - match ptr { - 0 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, - 1 => Self { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, - 2 => Self { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, - 3 => Self { reveal: traits::Reveal::All, constness: hir::Constness::Const }, - _ => std::hint::unreachable_unchecked(), - } - } +impl_tag! { + for ParamTag; + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } <=> 0, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } <=> 1, + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } <=> 2, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const } <=> 3, } impl<'tcx> fmt::Debug for ParamEnv<'tcx> { From 0892a7380b1bde39b979a00de1d11cef3357a717 Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 15:57:29 -0600 Subject: [PATCH 02/15] change usages of explicit_item_bounds to bound_explicit_item_bounds --- .../rustc_hir_analysis/src/check/check.rs | 9 +++-- .../rustc_hir_analysis/src/check/wfcheck.rs | 10 +++-- .../src/collect/item_bounds.rs | 11 ++--- .../src/generator_interior/mod.rs | 3 +- .../src/opaque_hidden_inferred_bound.rs | 4 +- compiler/rustc_lint/src/unused.rs | 40 +++++++++++-------- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 7 +++- .../src/traits/object_safety.rs | 5 ++- src/librustdoc/clean/mod.rs | 19 +++++---- .../clippy_lints/src/future_not_send.rs | 7 ++-- src/tools/clippy/clippy_utils/src/ty.rs | 5 ++- 13 files changed, 76 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 0c54fd70c9b5e..680562ccf6229 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -319,9 +319,12 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( selftys: vec![], }; let prohibit_opaque = tcx - .explicit_item_bounds(def_id) - .iter() - .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); + .bound_explicit_item_bounds(def_id.to_def_id()) + .transpose_iter() + .try_for_each(|bound| { + let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); + predicate.visit_with(&mut visitor) + }); if let Some(ty) = prohibit_opaque.break_value() { visitor.visit_item(&item); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 53197bc849106..9b89e51bacfc9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -360,7 +360,10 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe tcx, param_env, item_def_id, - tcx.explicit_item_bounds(item_def_id).to_vec(), + tcx.bound_explicit_item_bounds(item_def_id.to_def_id()) + .transpose_iter() + .map(|bound| bound.map_bound(|b| *b).subst_identity()) + .collect::>(), &FxIndexSet::default(), gat_def_id.def_id, gat_generics, @@ -1122,10 +1125,11 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// Assuming the defaults are used, check that all predicates (bounds on the /// assoc type and where clauses on the trait) hold. fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, span: Span) { - let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); + let bounds = wfcx.tcx().bound_explicit_item_bounds(item.def_id); debug!("check_associated_type_bounds: bounds={:?}", bounds); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let wf_obligations = bounds.transpose_iter().flat_map(|b| { + let (bound, bound_span) = b.map_bound(|b| *b).subst_identity(); let normalized_bound = wfcx.normalize(span, None, bound); traits::wf::predicate_obligations( wfcx.infcx, diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 2e56d24638cdb..5b2f1419a6921 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -130,9 +130,10 @@ pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { - let bounds = tcx.mk_predicates_from_iter(util::elaborate( - tcx, - tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), - )); - ty::EarlyBinder(bounds) + tcx.bound_explicit_item_bounds(def_id).map_bound(|bounds| { + tcx.mk_predicates_from_iter(util::elaborate( + tcx, + bounds.iter().map(|&(bound, _span)| bound), + )) + }) } diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 8feef332de8a7..1d17af8da8538 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -571,7 +571,8 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) { + for bound in fcx.tcx.bound_explicit_item_bounds(def).transpose_iter() { + let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index f9d43fe220036..5c408c749456b 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -74,7 +74,9 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. - for &(pred, pred_span) in cx.tcx.explicit_item_bounds(def_id) { + for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + let (pred, pred_span) = bound.map_bound(|b| *b).subst_identity(); + // Liberate bound regions in the predicate since we // don't actually care about lifetimes in this check. let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index d677d51881e0e..7e4852e3d3bf0 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -254,23 +254,29 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned()) - // We only care about self bounds for the impl-trait - .filter_only_self() - .find_map(|(pred, _span)| { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ref poly_trait_predicate, - )) = pred.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - - is_def_must_use(cx, def_id, span) - } else { - None - } - }) - .map(|inner| MustUsePath::Opaque(Box::new(inner))) + elaborate( + cx.tcx, + cx.tcx + .bound_explicit_item_bounds(def) + .transpose_iter() + .map(|bound| bound.map_bound(|b| *b).subst_identity()), + ) + // We only care about self bounds for the impl-trait + .filter_only_self() + .find_map(|(pred, _span)| { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Clause(ty::Clause::Trait( + ref poly_trait_predicate, + )) = pred.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + + is_def_must_use(cx, def_id, span) + } else { + None + } + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) } ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f9d3ffc8f0063..f65117f4934d7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { + self.bound_explicit_item_bounds(*def_id).skip_binder().iter().any(|(predicate, _)| { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 507e12d723894..c2c3d2dda3f4c 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1800,7 +1800,9 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in tcx.explicit_item_bounds(def) { + for bound in tcx.bound_explicit_item_bounds(def).transpose_iter() { + let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity(); + // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9567329192d52..cd48280526f8c 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -269,7 +269,7 @@ where // and are visited by shallow visitors. self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: tcx.explicit_item_bounds(def_id), + predicates: tcx.bound_explicit_item_bounds(def_id).skip_binder(), })?; } } @@ -1784,7 +1784,10 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn bounds(&mut self) -> &mut Self { self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: self.tcx.explicit_item_bounds(self.item_def_id), + predicates: self + .tcx + .bound_explicit_item_bounds(self.item_def_id.to_def_id()) + .skip_binder(), }); self } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b8ad1925e4eaa..b7ca37c058ccb 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -297,8 +297,9 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span tcx.associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) - .flat_map(|item| tcx.explicit_item_bounds(item.def_id)) - .filter_map(|pred_span| predicate_references_self(tcx, *pred_span)) + .flat_map(|item| tcx.bound_explicit_item_bounds(item.def_id).transpose_iter()) + .map(|bound| bound.map_bound(|b| *b).subst_identity()) + .filter_map(|pred_span| predicate_references_self(tcx, pred_span)) .collect() } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 04379c2bca97d..25031b0102243 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -421,9 +421,9 @@ fn clean_projection<'tcx>( if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) { let bounds = cx .tcx - .explicit_item_bounds(ty.skip_binder().def_id) - .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs)) + .bound_explicit_item_bounds(ty.skip_binder().def_id) + .subst_iter_copied(cx.tcx, ty.skip_binder().substs) + .map(|(pred, _)| pred) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); } @@ -1315,10 +1315,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - let bounds = tcx.explicit_item_bounds(assoc_item.def_id); + let bounds = tcx + .bound_explicit_item_bounds(assoc_item.def_id) + .transpose_iter() + .map(|bound| bound.map_bound(|b| *b).subst_identity()); let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; let predicates = - tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied()); + tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); let mut generics = clean_ty_generics( cx, tcx.generics_of(assoc_item.def_id), @@ -1844,9 +1847,9 @@ pub(crate) fn clean_middle_ty<'tcx>( // by looking up the bounds associated with the def_id. let bounds = cx .tcx - .explicit_item_bounds(def_id) - .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs)) + .bound_explicit_item_bounds(def_id) + .subst_iter_copied(cx.tcx, substs) + .map(|(bound, _)| bound) .collect::>(); clean_middle_opaque_bounds(cx, bounds) } diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index ed0bd58c770c7..73ae2406f9dbc 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, AliasTy, Clause, EarlyBinder, PredicateKind}; +use rustc_middle::ty::{self, AliasTy, Clause, PredicateKind}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::def_id::LocalDefId; use rustc_span::{sym, Span}; @@ -64,10 +64,9 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { - let preds = cx.tcx.explicit_item_bounds(def_id); + let preds = cx.tcx.bound_explicit_item_bounds(def_id); let mut is_future = false; - for &(p, _span) in preds { - let p = EarlyBinder(p).subst(cx.tcx, substs); + for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { if let Some(trait_pred) = p.to_opt_poly_trait_pred() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 8b996c188161d..058f6b0306dcf 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -90,7 +90,8 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { + for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. @@ -267,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { + for (predicate, _) in cx.tcx.bound_explicit_item_bounds(*def_id).skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; From f3b279fcc54eea8e4fb094d1672a3907489aa66b Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 16:43:46 -0600 Subject: [PATCH 03/15] add EarlyBinder to output of explicit_item_bounds; replace bound_explicit_item_bounds usages; remove bound_explicit_item_bounds query --- .../src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_hir_analysis/src/check/check.rs | 6 ++---- .../src/check/compare_impl_item.rs | 4 ++-- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 6 +++--- .../rustc_hir_analysis/src/collect/item_bounds.rs | 13 +++++++------ compiler/rustc_hir_analysis/src/variance/mod.rs | 2 +- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 6 +++--- .../rustc_hir_typeck/src/generator_interior/mod.rs | 4 ++-- .../rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_infer/src/infer/opaque_types.rs | 2 +- .../rustc_lint/src/opaque_hidden_inferred_bound.rs | 4 ++-- compiler/rustc_lint/src/unused.rs | 2 +- .../rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 6 +++++- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 7 ------- compiler/rustc_mir_transform/src/generator.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 7 ++----- .../src/traits/object_safety.rs | 2 +- compiler/rustc_traits/src/chalk/db.rs | 4 ++-- src/librustdoc/clean/mod.rs | 6 +++--- .../clippy/clippy_lints/src/future_not_send.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 6 +++--- 26 files changed, 49 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 49e74a1b000d4..7ad9de0572090 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -706,7 +706,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .copied() .find_map(find_fn_kind_from_did), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(tcx, substs) .find_map(find_fn_kind_from_did), ty::Closure(_, substs) => match substs.as_closure().kind() { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 680562ccf6229..1dfffafd1d329 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -318,10 +318,8 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( tcx, selftys: vec![], }; - let prohibit_opaque = tcx - .bound_explicit_item_bounds(def_id.to_def_id()) - .transpose_iter() - .try_for_each(|bound| { + let prohibit_opaque = + tcx.explicit_item_bounds(def_id).transpose_iter().try_for_each(|bound| { let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); predicate.visit_with(&mut visitor) }); 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 fe87aae8ed111..48214b899a4b8 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -839,7 +839,7 @@ impl<'tcx> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx> { }); self.types.insert(proj.def_id, (infer_ty, proj.substs)); // Recurse into bounds - for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { + for (pred, pred_span) in self.interner().explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { let pred = pred.fold_with(self); let pred = self.ocx.normalize( &ObligationCause::misc(self.span, self.body_id), @@ -2023,7 +2023,7 @@ pub(super) fn check_type_bounds<'tcx>( }; let obligations: Vec<_> = tcx - .bound_explicit_item_bounds(trait_ty.def_id) + .explicit_item_bounds(trait_ty.def_id) .subst_iter_copied(tcx, rebased_substs) .map(|(concrete_ty_bound, span)| { debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 9b89e51bacfc9..fc40916f8fead 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -360,7 +360,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe tcx, param_env, item_def_id, - tcx.bound_explicit_item_bounds(item_def_id.to_def_id()) + tcx.explicit_item_bounds(item_def_id) .transpose_iter() .map(|bound| bound.map_bound(|b| *b).subst_identity()) .collect::>(), @@ -1125,7 +1125,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// Assuming the defaults are used, check that all predicates (bounds on the /// assoc type and where clauses on the trait) hold. fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocItem, span: Span) { - let bounds = wfcx.tcx().bound_explicit_item_bounds(item.def_id); + let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); debug!("check_associated_type_bounds: bounds={:?}", bounds); let wf_obligations = bounds.transpose_iter().flat_map(|b| { @@ -1592,7 +1592,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { } }); for (bound, bound_span) in tcx - .bound_explicit_item_bounds(opaque_ty.def_id) + .explicit_item_bounds(opaque_ty.def_id) .subst_iter_copied(tcx, opaque_ty.substs) { let bound = self.wfcx.normalize(bound_span, None, bound); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 5b2f1419a6921..80d6bc7db9e8f 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -79,14 +79,14 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> &'_ [(ty::Predicate<'_>, Span)] { +) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, 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. Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); let opaque_ty = item.expect_opaque_ty(); - return opaque_type_bounds( + return ty::EarlyBinder(opaque_type_bounds( tcx, opaque_def_id.expect_local(), opaque_ty.bounds, @@ -95,7 +95,7 @@ pub(super) fn explicit_item_bounds( ty::InternalSubsts::identity_for_item(tcx, def_id), ), item.span, - ); + )); } // These should have been fed! Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(), @@ -103,7 +103,7 @@ pub(super) fn explicit_item_bounds( } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - match tcx.hir().get(hir_id) { + let bounds = match tcx.hir().get(hir_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), span, @@ -123,14 +123,15 @@ pub(super) fn explicit_item_bounds( opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } _ => bug!("item_bounds called on {:?}", def_id), - } + }; + ty::EarlyBinder(bounds) } pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { - tcx.bound_explicit_item_bounds(def_id).map_bound(|bounds| { + tcx.explicit_item_bounds(def_id).map_bound(|bounds| { tcx.mk_predicates_from_iter(util::elaborate( tcx, bounds.iter().map(|&(bound, _span)| bound), diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 4d240e90b143d..d8625bd21e8eb 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -153,7 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id); - for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() { + for pred in tcx.explicit_item_bounds(item_def_id).transpose_iter() { let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); debug!(?pred); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 6c2ce62722a54..aefde8109a07a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -530,7 +530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ty in [first_ty, second_ty] { for (pred, _) in self .tcx - .bound_explicit_item_bounds(rpit_def_id) + .explicit_item_bounds(rpit_def_id) .subst_iter_copied(self.tcx, substs) { let pred = pred.kind().rebind(match pred.kind().skip_binder() { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 8c2495e1dd8c5..7046269c2de22 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -172,7 +172,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self .deduce_closure_signature_from_predicates( expected_ty, - self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), + self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), ), ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { @@ -713,13 +713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self .tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(self.tcx, substs) .find_map(|(p, s)| get_future_output(p, s))?, ty::Error(_) => return None, ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self .tcx - .bound_explicit_item_bounds(proj.def_id) + .explicit_item_bounds(proj.def_id) .subst_iter_copied(self.tcx, proj.substs) .find_map(|(p, s)| get_future_output(p, s))?, _ => span_bug!( diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 1d17af8da8538..5af824e0f5748 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -571,8 +571,8 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for bound in fcx.tcx.bound_explicit_item_bounds(def).transpose_iter() { - let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); + for bound in fcx.tcx.explicit_item_bounds(def).transpose_iter() { + let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity(); // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b0c376a26f614..547f851526f0a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -402,7 +402,7 @@ impl<'tcx> InferCtxt<'tcx> { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; - self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map( + self.tcx.explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map( |(predicate, _)| { predicate .kind() diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 680465bdab690..334395945ea96 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -540,7 +540,7 @@ impl<'tcx> InferCtxt<'tcx> { .obligations; } - let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); + let item_bounds = tcx.explicit_item_bounds(def_id); for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { let predicate = predicate.fold_with(&mut BottomUpFolder { diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 5c408c749456b..1d41021140315 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. - for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { let (pred, pred_span) = bound.map_bound(|b| *b).subst_identity(); // Liberate bound regions in the predicate since we @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // with `impl Send: OtherTrait`. for (assoc_pred, assoc_pred_span) in cx .tcx - .bound_explicit_item_bounds(proj.projection_ty.def_id) + .explicit_item_bounds(proj.projection_ty.def_id) .subst_iter_copied(cx.tcx, &proj.projection_ty.substs) { let assoc_pred = assoc_pred.fold_with(proj_replacer); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 7e4852e3d3bf0..8de358cf8ab11 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -257,7 +257,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { elaborate( cx.tcx, cx.tcx - .bound_explicit_item_bounds(def) + .explicit_item_bounds(def) .transpose_iter() .map(|bound| bound.map_bound(|b| *b).subst_identity()), ) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 31798afb852c5..0ca1d9ac6ff82 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -203,7 +203,11 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } provide! { tcx, def_id, other, cdata, - explicit_item_bounds => { table_defaulted_array } + explicit_item_bounds => { + let lazy = cdata.root.tables.explicit_item_bounds.get(cdata, def_id.index); + let output = if lazy.is_default() { &mut [] } else { tcx.arena.alloc_from_iter(lazy.decode((cdata, tcx))) }; + ty::EarlyBinder(&*output) + } explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d6500cd93a7d0..fd308d5cad152 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1425,7 +1425,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_explicit_item_bounds(&mut self, def_id: DefId) { debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id); - let bounds = self.tcx.explicit_item_bounds(def_id); + let bounds = self.tcx.explicit_item_bounds(def_id).skip_binder(); record_defaulted_array!(self.tables.explicit_item_bounds[def_id] <- bounds); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7e26e05025ff1..f024ba46b6410 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -274,7 +274,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) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, Span)]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f65117f4934d7..68c5b205fa047 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.bound_explicit_item_bounds(*def_id).skip_binder().iter().any(|(predicate, _)| { + self.explicit_item_bounds(def_id).skip_binder().iter().any(|(predicate, _)| { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index af76cf7cc4e0d..0d4f69a27cf24 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -911,7 +911,7 @@ pub trait PrettyPrinter<'tcx>: // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = tcx.bound_explicit_item_bounds(def_id); + let bounds = tcx.explicit_item_bounds(def_id); let mut traits = FxIndexMap::default(); let mut fn_traits = FxIndexMap::default(); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index dbe2eebe33604..d0bcad0d02360 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -694,13 +694,6 @@ impl<'tcx> TyCtxt<'tcx> { if visitor.found_recursion { Err(expanded_type) } else { Ok(expanded_type) } } - pub fn bound_explicit_item_bounds( - self, - def_id: DefId, - ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { - ty::EarlyBinder(self.explicit_item_bounds(def_id)) - } - /// Returns names of captured upvars for closures and generators. /// /// Here are some examples: diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index c2c3d2dda3f4c..e4396d70b7e5d 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1800,7 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for bound in tcx.bound_explicit_item_bounds(def).transpose_iter() { + for bound in tcx.explicit_item_bounds(def).transpose_iter() { let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity(); // We only look at the `DefId`, so it is safe to skip the binder here. diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cd48280526f8c..c607c7fd5f4a7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -269,7 +269,7 @@ where // and are visited by shallow visitors. self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: tcx.bound_explicit_item_bounds(def_id).skip_binder(), + predicates: tcx.explicit_item_bounds(def_id).skip_binder(), })?; } } @@ -1784,10 +1784,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { fn bounds(&mut self) -> &mut Self { self.visit_predicates(ty::GenericPredicates { parent: None, - predicates: self - .tcx - .bound_explicit_item_bounds(self.item_def_id.to_def_id()) - .skip_binder(), + predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(), }); self } diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index b7ca37c058ccb..c09658cd4e158 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -297,7 +297,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span tcx.associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) - .flat_map(|item| tcx.bound_explicit_item_bounds(item.def_id).transpose_iter()) + .flat_map(|item| tcx.explicit_item_bounds(item.def_id).transpose_iter()) .map(|bound| bound.map_bound(|b| *b).subst_identity()) .filter_map(|pred_span| predicate_references_self(tcx, pred_span)) .collect() diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 9683e48478edc..0974c5ffaa25a 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -50,7 +50,7 @@ impl<'tcx> RustIrDatabase<'tcx> { where ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option>, { - let bounds = self.interner.tcx.bound_explicit_item_bounds(def_id); + let bounds = self.interner.tcx.explicit_item_bounds(def_id); bounds .0 .iter() @@ -506,7 +506,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0); - let explicit_item_bounds = self.interner.tcx.bound_explicit_item_bounds(opaque_ty_id.0); + let explicit_item_bounds = self.interner.tcx.explicit_item_bounds(opaque_ty_id.0); let bounds = explicit_item_bounds .0 diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 25031b0102243..00932c59cca9c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -421,7 +421,7 @@ fn clean_projection<'tcx>( if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) { let bounds = cx .tcx - .bound_explicit_item_bounds(ty.skip_binder().def_id) + .explicit_item_bounds(ty.skip_binder().def_id) .subst_iter_copied(cx.tcx, ty.skip_binder().substs) .map(|(pred, _)| pred) .collect::>(); @@ -1316,7 +1316,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( if let ty::TraitContainer = assoc_item.container { let bounds = tcx - .bound_explicit_item_bounds(assoc_item.def_id) + .explicit_item_bounds(assoc_item.def_id) .transpose_iter() .map(|bound| bound.map_bound(|b| *b).subst_identity()); let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; @@ -1847,7 +1847,7 @@ pub(crate) fn clean_middle_ty<'tcx>( // by looking up the bounds associated with the def_id. let bounds = cx .tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(cx.tcx, substs) .map(|(bound, _)| bound) .collect::>(); diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 73ae2406f9dbc..ff838c2d56e43 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { } let ret_ty = return_ty(cx, cx.tcx.hir().local_def_id_to_hir_id(fn_def_id).expect_owner()); if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { - let preds = cx.tcx.bound_explicit_item_bounds(def_id); + let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; for (p, _span) in preds.subst_iter_copied(cx.tcx, substs) { if let Some(trait_pred) = p.to_opt_poly_trait_pred() { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 058f6b0306dcf..5f768928adf05 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -90,7 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for bound in cx.tcx.bound_explicit_item_bounds(def_id).transpose_iter() { + for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through @@ -268,7 +268,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.bound_explicit_item_bounds(*def_id).skip_binder() { + for (predicate, _) in cx.tcx.explicit_item_bounds(def_id).skip_binder() { if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; @@ -744,7 +744,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option for (pred, _) in cx .tcx - .bound_explicit_item_bounds(ty.def_id) + .explicit_item_bounds(ty.def_id) .subst_iter_copied(cx.tcx, ty.substs) { match pred.kind().skip_binder() { From e54854f6a93f4121ac55d895830414d33bd3aa8e Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Mon, 17 Apr 2023 17:19:08 -0600 Subject: [PATCH 04/15] add subst_identity_iter and subst_identity_iter_copied methods on EarlyBinder; use this to simplify some EarlyBinder noise around explicit_item_bounds calls --- .../rustc_hir_analysis/src/check/check.rs | 9 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 +-- .../rustc_hir_analysis/src/variance/mod.rs | 3 +- .../src/generator_interior/mod.rs | 3 +- .../src/opaque_hidden_inferred_bound.rs | 4 +- compiler/rustc_lint/src/unused.rs | 40 ++++++++----------- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/subst.rs | 12 ++++++ compiler/rustc_mir_transform/src/generator.rs | 4 +- .../src/traits/object_safety.rs | 3 +- src/librustdoc/clean/mod.rs | 6 +-- src/tools/clippy/clippy_utils/src/ty.rs | 3 +- 12 files changed, 44 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 1dfffafd1d329..d84e7b5881cfe 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -318,11 +318,10 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( tcx, selftys: vec![], }; - let prohibit_opaque = - tcx.explicit_item_bounds(def_id).transpose_iter().try_for_each(|bound| { - let predicate = bound.map_bound(|&(predicate, _)| predicate).subst_identity(); - predicate.visit_with(&mut visitor) - }); + let prohibit_opaque = tcx + .explicit_item_bounds(def_id) + .subst_identity_iter_copied() + .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); if let Some(ty) = prohibit_opaque.break_value() { visitor.visit_item(&item); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index fc40916f8fead..80ab711c15c0e 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -361,8 +361,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe param_env, item_def_id, tcx.explicit_item_bounds(item_def_id) - .transpose_iter() - .map(|bound| bound.map_bound(|b| *b).subst_identity()) + .subst_identity_iter_copied() .collect::>(), &FxIndexSet::default(), gat_def_id.def_id, @@ -1128,8 +1127,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); debug!("check_associated_type_bounds: bounds={:?}", bounds); - let wf_obligations = bounds.transpose_iter().flat_map(|b| { - let (bound, bound_span) = b.map_bound(|b| *b).subst_identity(); + let wf_obligations = bounds.subst_identity_iter_copied().flat_map(|(bound, bound_span)| { let normalized_bound = wfcx.normalize(span, None, bound); traits::wf::predicate_obligations( wfcx.infcx, diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index d8625bd21e8eb..e735b048d7343 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -153,8 +153,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id); - for pred in tcx.explicit_item_bounds(item_def_id).transpose_iter() { - let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); + for (pred, _) in tcx.explicit_item_bounds(item_def_id).subst_iter_copied(tcx, id_substs) { debug!(?pred); // We only ignore opaque type substs if the opaque type is the outermost type. diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 5af824e0f5748..d23fe9650805d 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -571,8 +571,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for bound in fcx.tcx.explicit_item_bounds(def).transpose_iter() { - let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity(); + for (predicate, _) in fcx.tcx.explicit_item_bounds(def).subst_identity_iter_copied() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 1d41021140315..15715c8fca039 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -74,9 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. - for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { - let (pred, pred_span) = bound.map_bound(|b| *b).subst_identity(); - + for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() { // Liberate bound regions in the predicate since we // don't actually care about lifetimes in this check. let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 8de358cf8ab11..eb175e96997b3 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -254,29 +254,23 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - elaborate( - cx.tcx, - cx.tcx - .explicit_item_bounds(def) - .transpose_iter() - .map(|bound| bound.map_bound(|b| *b).subst_identity()), - ) - // We only care about self bounds for the impl-trait - .filter_only_self() - .find_map(|(pred, _span)| { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ref poly_trait_predicate, - )) = pred.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - - is_def_must_use(cx, def_id, span) - } else { - None - } - }) - .map(|inner| MustUsePath::Opaque(Box::new(inner))) + elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).subst_identity_iter_copied()) + // We only care about self bounds for the impl-trait + .filter_only_self() + .find_map(|(pred, _span)| { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Clause(ty::Clause::Trait( + ref poly_trait_predicate, + )) = pred.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + + is_def_must_use(cx, def_id, span) + } else { + None + } + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) } ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 68c5b205fa047..a5e98fe6224dc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_bounds(def_id).skip_binder().iter().any(|(predicate, _)| { + self.explicit_item_bounds(def_id).subst_identity_iter_copied().any(|(predicate, _)| { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 3e1b0706f6688..6361789d3973b 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -625,6 +625,12 @@ where ) -> SubstIter<'s, 'tcx, I> { SubstIter { it: self.0.into_iter(), tcx, substs } } + + /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// but on an iterator of `TypeFoldable` values. + pub fn subst_identity_iter(self) -> I::IntoIter { + self.0.into_iter() + } } pub struct SubstIter<'s, 'tcx, I: IntoIterator> { @@ -677,6 +683,12 @@ where ) -> SubstIterCopied<'s, 'tcx, I> { SubstIterCopied { it: self.0.into_iter(), tcx, substs } } + + /// Similar to [`subst_identity`](EarlyBinder::subst_identity), + /// but on an iterator of values that deref to a `TypeFoldable`. + pub fn subst_identity_iter_copied(self) -> impl Iterator::Target> { + self.0.into_iter().map(|v| *v) + } } pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index e4396d70b7e5d..4cfb2e1fffa88 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1800,9 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for bound in tcx.explicit_item_bounds(def).transpose_iter() { - let predicate = bound.map_bound(|&(pred, _)| pred).subst_identity(); - + for (predicate, _) in tcx.explicit_item_bounds(def).subst_identity_iter_copied() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index c09658cd4e158..73e2efc3b000e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -297,8 +297,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span tcx.associated_items(trait_def_id) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) - .flat_map(|item| tcx.explicit_item_bounds(item.def_id).transpose_iter()) - .map(|bound| bound.map_bound(|b| *b).subst_identity()) + .flat_map(|item| tcx.explicit_item_bounds(item.def_id).subst_identity_iter_copied()) .filter_map(|pred_span| predicate_references_self(tcx, pred_span)) .collect() } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 00932c59cca9c..c992a5388d199 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1315,10 +1315,8 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( } if let ty::TraitContainer = assoc_item.container { - let bounds = tcx - .explicit_item_bounds(assoc_item.def_id) - .transpose_iter() - .map(|bound| bound.map_bound(|b| *b).subst_identity()); + let bounds = + tcx.explicit_item_bounds(assoc_item.def_id).subst_identity_iter_copied(); let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates; let predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied())); diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 5f768928adf05..cb700126c2bd5 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -90,8 +90,7 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for bound in cx.tcx.explicit_item_bounds(def_id).transpose_iter() { - let (predicate, _span) = bound.map_bound(|b| *b).subst_identity(); + for (predicate, _span) in cx.tcx.explicit_item_bounds(def_id).subst_identity_iter_copied() { match predicate.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. From 96905d568a6f1db806d43047a6392c5e2766009e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 20 Apr 2023 18:49:40 +0000 Subject: [PATCH 05/15] Use `impl Tag for $T` syntax for `impl_tag!` --- .../rustc_data_structures/src/tagged_ptr/impl_tag.rs | 12 ++++++------ .../src/tagged_ptr/impl_tag/tests.rs | 10 +++++----- compiler/rustc_middle/src/ty/mod.rs | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs index deaaee4cc1728..c996895936866 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -23,7 +23,7 @@ /// /// impl_tag! { /// // The type for which the `Tag` will be implemented -/// for SomeTag; +/// impl Tag for SomeTag; /// // You need to specify the `{value_of_the_type} <=> {tag}` relationship /// SomeTag::A <=> 0, /// SomeTag::B <=> 1, @@ -54,7 +54,7 @@ /// struct Flags { a: bool, b: bool } /// /// impl_tag! { -/// for Flags; +/// impl Tag for Flags; /// Flags { a: true, b: true } <=> 3, /// Flags { a: false, b: true } <=> 2, /// Flags { a: true, b: false } <=> 1, @@ -73,7 +73,7 @@ // struct Unit; // // impl_tag! { -// for Unit; +// impl Tag for Unit; // Unit <=> 0, // Unit <=> 1, // } @@ -87,7 +87,7 @@ // enum E { A, B }; // // impl_tag! { -// for E; +// impl Tag for E; // E::A <=> 0, // E::B <=> 0, // } @@ -104,14 +104,14 @@ /// } /// /// impl_tag! { -/// for E; +/// impl Tag for E; /// E::A <=> 0, /// } /// ``` #[macro_export] macro_rules! impl_tag { ( - for $Self:ty; + impl Tag for $Self:ty; $( $($path:ident)::* $( { $( $fields:tt )* })? <=> $tag:literal, )* diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs index 26d1cf3b45422..cd19b30ff5340 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs @@ -4,22 +4,22 @@ fn bits_constant() { #[derive(Copy, Clone)] struct Unit; - impl_tag! { for Unit; Unit <=> 0, } + impl_tag! { impl Tag for Unit; Unit <=> 0, } assert_eq!(Unit::BITS, 0); #[derive(Copy, Clone)] struct Unit1; - impl_tag! { for Unit1; Unit1 <=> 1, } + impl_tag! { impl Tag for Unit1; Unit1 <=> 1, } assert_eq!(Unit1::BITS, 1); #[derive(Copy, Clone)] struct Unit2; - impl_tag! { for Unit2; Unit2 <=> 0b10, } + impl_tag! { impl Tag for Unit2; Unit2 <=> 0b10, } assert_eq!(Unit2::BITS, 2); #[derive(Copy, Clone)] struct Unit3; - impl_tag! { for Unit3; Unit3 <=> 0b100, } + impl_tag! { impl Tag for Unit3; Unit3 <=> 0b100, } assert_eq!(Unit3::BITS, 3); #[derive(Copy, Clone)] @@ -28,6 +28,6 @@ fn bits_constant() { B, C, } - impl_tag! { for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, } + impl_tag! { impl Tag for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, } assert_eq!(Enum::BITS, 4); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f520faa6a6154..d13c71b78e466 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1627,7 +1627,7 @@ struct ParamTag { } impl_tag! { - for ParamTag; + impl Tag for ParamTag; ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } <=> 0, ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } <=> 1, ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } <=> 2, From 7cfecf26f77f0d2c3d83be946d4da6ab997c939e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 20 Apr 2023 19:07:57 +0000 Subject: [PATCH 06/15] Remove confusing comment --- .../src/tagged_ptr/impl_tag.rs | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs index c996895936866..d263bed9581ad 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -62,37 +62,6 @@ /// } /// ``` /// -// This is supposed to produce a compile error, but does not, -// see for more information. -// -// Using the same pattern twice results in a compile error: -// -// ```compile_fail -// # use rustc_data_structures::impl_tag; -// #[derive(Copy, Clone)] -// struct Unit; -// -// impl_tag! { -// impl Tag for Unit; -// Unit <=> 0, -// Unit <=> 1, -// } -// ``` -// -// Using the same tag twice results in a compile error: -// -// ```compile_fail -// # use rustc_data_structures::impl_tag; -// #[derive(Copy, Clone)] -// enum E { A, B }; -// -// impl_tag! { -// impl Tag for E; -// E::A <=> 0, -// E::B <=> 0, -// } -// ``` -// /// Not specifying all values results in a compile error: /// /// ```compile_fail,E0004 From ad8c7b6705d94bdf9293fbfe0c4d386d5f7e81a2 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 20 Apr 2023 19:24:04 +0000 Subject: [PATCH 07/15] Simplify `bits_for_tags` impl --- compiler/rustc_data_structures/src/tagged_ptr.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs index a25046986cc59..2914eece6796b 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr.rs @@ -155,7 +155,9 @@ pub const fn bits_for_tags(mut tags: &[usize]) -> u32 { while let &[tag, ref rest @ ..] = tags { tags = rest; - let b = bits_for_tag(tag); + // bits required to represent `tag`, + // position of the most significant 1 + let b = usize::BITS - tag.leading_zeros(); if b > bits { bits = b; } @@ -164,18 +166,6 @@ pub const fn bits_for_tags(mut tags: &[usize]) -> u32 { bits } -/// Returns `(size_of::() * 8) - tag.leading_zeros()` -const fn bits_for_tag(mut tag: usize) -> u32 { - let mut bits = 0; - - while tag > 0 { - bits += 1; - tag >>= 1; - } - - bits -} - unsafe impl Pointer for Box { const BITS: u32 = bits_for::(); From 57316559e4d6161ee1ac66d1c8db68562bdd0eaa Mon Sep 17 00:00:00 2001 From: Arlo Siemsen Date: Fri, 21 Apr 2023 10:45:06 -0500 Subject: [PATCH 08/15] Fix no_global_oom_handling build `provide_sorted_batch` in core is incorrectly marked with `#[cfg(not(no_global_oom_handling))]` which prevents core from building with the cfg enabled. Nothing in core allocates memory including this function, so the `cfg` gate is incorrect. --- library/core/src/slice/sort.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 07fd96f929586..e6e3b55efa9ae 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -1456,7 +1456,6 @@ pub struct TimSortRun { /// Takes a range as denoted by start and end, that is already sorted and extends it to the right if /// necessary with sorts optimized for smaller ranges such as insertion sort. -#[cfg(not(no_global_oom_handling))] fn provide_sorted_batch(v: &mut [T], start: usize, mut end: usize, is_less: &mut F) -> usize where F: FnMut(&T, &T) -> bool, From 5a69b5d0f9753a7e780849ec930b1bb48653588b Mon Sep 17 00:00:00 2001 From: Kyle Matsuda Date: Thu, 20 Apr 2023 12:33:32 -0600 Subject: [PATCH 09/15] Changes from review --- .../src/generator_interior/mod.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 16 +++++++++++++++- .../src/rmeta/decoder/cstore_impl.rs | 6 +----- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 2 +- compiler/rustc_traits/src/chalk/db.rs | 17 ++++++----------- 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index d23fe9650805d..5b432475fc384 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -571,7 +571,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for (predicate, _) in fcx.tcx.explicit_item_bounds(def).subst_identity_iter_copied() { + for &(predicate, _) in fcx.tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 951fb303e3cf9..44e3ccf7e4b8f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -23,7 +23,7 @@ use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc_middle::ty::codec::TyDecoder; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::GeneratorDiagnosticData; -use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility}; +use rustc_middle::ty::{self, ParameterizedOverTcx, Predicate, Ty, TyCtxt, Visibility}; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::{Decodable, Decoder}; use rustc_session::cstore::{ @@ -857,6 +857,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { ) } + fn get_explicit_item_bounds( + self, + index: DefIndex, + tcx: TyCtxt<'tcx>, + ) -> ty::EarlyBinder<&'tcx [(Predicate<'tcx>, Span)]> { + let lazy = self.root.tables.explicit_item_bounds.get(self, index); + let output = if lazy.is_default() { + &mut [] + } else { + tcx.arena.alloc_from_iter(lazy.decode((self, tcx))) + }; + ty::EarlyBinder(&*output) + } + fn get_variant(self, kind: &DefKind, index: DefIndex, parent_did: DefId) -> ty::VariantDef { let adt_kind = match kind { DefKind::Variant => ty::AdtKind::Enum, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0ca1d9ac6ff82..92d69aeb771fb 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -203,11 +203,7 @@ impl IntoArgs for (CrateNum, SimplifiedType) { } provide! { tcx, def_id, other, cdata, - explicit_item_bounds => { - let lazy = cdata.root.tables.explicit_item_bounds.get(cdata, def_id.index); - let output = if lazy.is_default() { &mut [] } else { tcx.arena.alloc_from_iter(lazy.decode((cdata, tcx))) }; - ty::EarlyBinder(&*output) - } + explicit_item_bounds => { cdata.get_explicit_item_bounds(def_id.index, tcx) } explicit_predicates_of => { table } generics_of => { table } inferred_outlives_of => { table_defaulted_array } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a5e98fe6224dc..7ac87cc80fddb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1611,7 +1611,7 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_bounds(def_id).subst_identity_iter_copied().any(|(predicate, _)| { + self.explicit_item_bounds(def_id).skip_binder().iter().any(|&(predicate, _)| { let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { return false; }; diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 4cfb2e1fffa88..a75d3108575fd 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1800,7 +1800,7 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for (predicate, _) in tcx.explicit_item_bounds(def).subst_identity_iter_copied() { + for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = predicate.kind().skip_binder() diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 0974c5ffaa25a..c319b2e31c7e6 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -50,12 +50,11 @@ impl<'tcx> RustIrDatabase<'tcx> { where ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option>, { - let bounds = self.interner.tcx.explicit_item_bounds(def_id); - bounds - .0 - .iter() - .map(|(bound, _)| bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars)) - .filter_map(|bound| LowerInto::>::lower_into(bound, self.interner)) + self.interner + .tcx + .explicit_item_bounds(def_id) + .subst_iter_copied(self.interner.tcx, &bound_vars) + .filter_map(|(bound, _)| LowerInto::>::lower_into(bound, self.interner)) .collect() } } @@ -509,12 +508,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let explicit_item_bounds = self.interner.tcx.explicit_item_bounds(opaque_ty_id.0); let bounds = explicit_item_bounds - .0 - .iter() + .subst_iter_copied(self.interner.tcx, &bound_vars) .map(|(bound, _)| { - explicit_item_bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars) - }) - .map(|bound| { bound.fold_with(&mut ReplaceOpaqueTyFolder { tcx: self.interner.tcx, opaque_ty_id, From 2b8d27b402b621d20c7c29c500852c727d4cc8cd Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 24 Apr 2023 16:48:37 +0000 Subject: [PATCH 10/15] Switch `impl_tag!` from explicit tags to `${index()}` --- compiler/rustc_data_structures/src/lib.rs | 1 + .../src/tagged_ptr/impl_tag.rs | 59 ++++++++++--------- .../src/tagged_ptr/impl_tag/tests.rs | 39 ++++++------ compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 8 +-- 5 files changed, 57 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 426d2c4034bd8..004017ec5f31a 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -31,6 +31,7 @@ #![feature(unwrap_infallible)] #![feature(strict_provenance)] #![feature(ptr_alignment_type)] +#![feature(macro_metavar_expr)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs index d263bed9581ad..0b0c152cc4db4 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -11,6 +11,7 @@ /// Basic usage: /// /// ``` +/// #![feature(macro_metavar_expr)] /// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; /// /// #[derive(Copy, Clone, PartialEq, Debug)] @@ -24,19 +25,20 @@ /// impl_tag! { /// // The type for which the `Tag` will be implemented /// impl Tag for SomeTag; -/// // You need to specify the `{value_of_the_type} <=> {tag}` relationship -/// SomeTag::A <=> 0, -/// SomeTag::B <=> 1, +/// // You need to specify all possible tag values: +/// SomeTag::A, // 0 +/// SomeTag::B, // 1 /// // For variants with fields, you need to specify the fields: -/// SomeTag::X { v: true } <=> 2, -/// SomeTag::X { v: false } <=> 3, +/// SomeTag::X { v: true }, // 2 +/// SomeTag::X { v: false }, // 3 /// // For tuple variants use named syntax: -/// SomeTag::Y { 0: true, 1: true } <=> 4, -/// SomeTag::Y { 0: false, 1: true } <=> 5, -/// SomeTag::Y { 0: true, 1: false } <=> 6, -/// SomeTag::Y { 0: false, 1: false } <=> 7, +/// SomeTag::Y { 0: true, 1: true }, // 4 +/// SomeTag::Y { 0: false, 1: true }, // 5 +/// SomeTag::Y { 0: true, 1: false }, // 6 +/// SomeTag::Y { 0: false, 1: false }, // 7 /// } /// +/// // Tag values are assigned in order: /// assert_eq!(SomeTag::A.into_usize(), 0); /// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); /// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); @@ -49,22 +51,24 @@ /// Structs are supported: /// /// ``` +/// #![feature(macro_metavar_expr)] /// # use rustc_data_structures::impl_tag; /// #[derive(Copy, Clone)] /// struct Flags { a: bool, b: bool } /// /// impl_tag! { /// impl Tag for Flags; -/// Flags { a: true, b: true } <=> 3, -/// Flags { a: false, b: true } <=> 2, -/// Flags { a: true, b: false } <=> 1, -/// Flags { a: false, b: false } <=> 0, +/// Flags { a: true, b: true }, +/// Flags { a: false, b: true }, +/// Flags { a: true, b: false }, +/// Flags { a: false, b: false }, /// } /// ``` /// /// Not specifying all values results in a compile error: /// /// ```compile_fail,E0004 +/// #![feature(macro_metavar_expr)] /// # use rustc_data_structures::impl_tag; /// #[derive(Copy, Clone)] /// enum E { @@ -74,7 +78,7 @@ /// /// impl_tag! { /// impl Tag for E; -/// E::A <=> 0, +/// E::A, /// } /// ``` #[macro_export] @@ -82,16 +86,18 @@ macro_rules! impl_tag { ( impl Tag for $Self:ty; $( - $($path:ident)::* $( { $( $fields:tt )* })? <=> $tag:literal, + $($path:ident)::* $( { $( $fields:tt )* })?, )* ) => { // Safety: - // `into_usize` only returns one of `$tag`s, - // `bits_for_tags` is called on all `$tag`s, - // thus `BITS` constant is correct. + // `bits_for_tags` is called on the same `${index()}`-es as + // `into_usize` returns, thus `BITS` constant is correct. unsafe impl $crate::tagged_ptr::Tag for $Self { const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ - $( $tag, )* + $( + ${index()}, + $( ${ignore(path)} )* + )* ]); fn into_usize(self) -> usize { @@ -101,25 +107,22 @@ macro_rules! impl_tag { match self { // `match` is doing heavy lifting here, by requiring exhaustiveness $( - $($path)::* $( { $( $fields )* } )? => $tag, + $($path)::* $( { $( $fields )* } )? => ${index()}, )* } } unsafe fn from_usize(tag: usize) -> Self { - // Similarly to the above, this forbids repeating tags - // (or at least it should, see ) - #[forbid(unreachable_patterns)] match tag { $( - $tag => $($path)::* $( { $( $fields )* } )?, + ${index()} => $($path)::* $( { $( $fields )* } )?, )* // Safety: - // `into_usize` only returns one of `$tag`s, - // all `$tag`s are filtered up above, - // thus if this is reached, the safety contract of this - // function was already breached. + // `into_usize` only returns `${index()}` of the same + // repetition as we are filtering above, thus if this is + // reached, the safety contract of this function was + // already breached. _ => unsafe { debug_assert!( false, diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs index cd19b30ff5340..62c926153e1e9 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs @@ -4,30 +4,31 @@ fn bits_constant() { #[derive(Copy, Clone)] struct Unit; - impl_tag! { impl Tag for Unit; Unit <=> 0, } + impl_tag! { impl Tag for Unit; Unit, } assert_eq!(Unit::BITS, 0); #[derive(Copy, Clone)] - struct Unit1; - impl_tag! { impl Tag for Unit1; Unit1 <=> 1, } - assert_eq!(Unit1::BITS, 1); - - #[derive(Copy, Clone)] - struct Unit2; - impl_tag! { impl Tag for Unit2; Unit2 <=> 0b10, } - assert_eq!(Unit2::BITS, 2); - - #[derive(Copy, Clone)] - struct Unit3; - impl_tag! { impl Tag for Unit3; Unit3 <=> 0b100, } - assert_eq!(Unit3::BITS, 3); - - #[derive(Copy, Clone)] - enum Enum { + enum Enum3 { A, B, C, } - impl_tag! { impl Tag for Enum; Enum::A <=> 0b1, Enum::B <=> 0b1000, Enum::C <=> 0b10, } - assert_eq!(Enum::BITS, 4); + impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, } + assert_eq!(Enum3::BITS, 2); + + #[derive(Copy, Clone)] + struct Eight(bool, bool, bool); + impl_tag! { + impl Tag for Eight; + Eight { 0: true, 1: true, 2: true }, + Eight { 0: true, 1: true, 2: false }, + Eight { 0: true, 1: false, 2: true }, + Eight { 0: true, 1: false, 2: false }, + Eight { 0: false, 1: true, 2: true }, + Eight { 0: false, 1: true, 2: false }, + Eight { 0: false, 1: false, 2: true }, + Eight { 0: false, 1: false, 2: false }, + } + + assert_eq!(Eight::BITS, 3); } diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 76a8367b2c460..e9172e767e036 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -60,6 +60,7 @@ #![feature(const_option)] #![feature(trait_alias)] #![feature(ptr_alignment_type)] +#![feature(macro_metavar_expr)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d13c71b78e466..88de43478b886 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1628,10 +1628,10 @@ struct ParamTag { impl_tag! { impl Tag for ParamTag; - ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst } <=> 0, - ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst } <=> 1, - ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const } <=> 2, - ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const } <=> 3, + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::NotConst }, + ParamTag { reveal: traits::Reveal::UserFacing, constness: hir::Constness::Const }, + ParamTag { reveal: traits::Reveal::All, constness: hir::Constness::Const }, } impl<'tcx> fmt::Debug for ParamEnv<'tcx> { From 794cb890dee2df982403d85a951f9414f86b6daf Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 22 Apr 2023 03:54:33 +0000 Subject: [PATCH 11/15] Consider polarity in new solver --- compiler/rustc_middle/src/ty/mod.rs | 5 ++ .../src/solve/trait_goals.rs | 72 ++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 42b98540ac7db..8025697d6d1e0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -861,6 +861,11 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub fn is_const_if_const(self) -> bool { self.skip_binder().is_const_if_const() } + + #[inline] + pub fn polarity(self) -> ImplPolarity { + self.skip_binder().polarity + } } /// `A: B` diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 8e7097ce4a779..c97473e6241f2 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -86,8 +86,9 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { - // FIXME: Constness and polarity + // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = ecx.instantiate_binder_with_infer(poly_trait_pred); @@ -111,6 +112,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ) -> QueryResult<'tcx> { if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() && poly_trait_pred.def_id() == goal.predicate.def_id() + && poly_trait_pred.polarity() == goal.predicate.polarity { // FIXME: Constness and polarity ecx.probe(|ecx| { @@ -147,6 +149,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let Some(result) = ecx.disqualify_auto_trait_candidate_due_to_possible_impl(goal) { return result; } @@ -161,6 +167,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); ecx.probe(|ecx| { @@ -176,6 +186,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_sized_trait, @@ -186,6 +200,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.probe_and_evaluate_goal_for_constituent_tys( goal, structural_traits::instantiate_constituent_tys_for_copy_clone_trait, @@ -196,6 +214,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if goal.predicate.self_ty().has_non_region_infer() { return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } @@ -217,6 +239,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::FnPtr(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -229,6 +255,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { goal: Goal<'tcx, Self>, goal_kind: ty::ClosureKind, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); let tupled_inputs_and_output = match structural_traits::extract_tupled_inputs_and_output_from_callable( @@ -259,6 +289,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if let ty::Tuple(..) = goal.predicate.self_ty().kind() { ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { @@ -268,8 +302,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_pointee_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -277,6 +315,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let ty::Generator(def_id, _, _) = *goal.predicate.self_ty().kind() else { return Err(NoSolution); }; @@ -297,6 +339,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let self_ty = goal.predicate.self_ty(); let ty::Generator(def_id, substs, _) = *self_ty.kind() else { return Err(NoSolution); @@ -326,6 +372,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + let tcx = ecx.tcx(); let a_ty = goal.predicate.self_ty(); let b_ty = goal.predicate.trait_ref.substs.type_at(1); @@ -447,6 +497,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> Vec> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return vec![]; + } + let tcx = ecx.tcx(); let a_ty = goal.predicate.self_ty(); @@ -521,8 +575,12 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn consider_builtin_discriminant_kind_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, - _goal: Goal<'tcx, Self>, + goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `DiscriminantKind` is automatically implemented for every type. ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } @@ -531,6 +589,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + if !goal.param_env.is_const() { // `Destruct` is automatically implemented for every type in // non-const environments. @@ -545,6 +607,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { + if goal.predicate.polarity != ty::ImplPolarity::Positive { + return Err(NoSolution); + } + // `rustc_transmute` does not have support for type or const params if goal.has_non_region_placeholders() { return Err(NoSolution); From bb2cb89ead84128441472ffec7e5c9174ce204e7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 24 Apr 2023 17:30:55 +0000 Subject: [PATCH 12/15] Negative coherence test --- .../new-solver/negative-coherence-bounds.rs | 40 +++++++++++++++++++ .../negative-coherence-bounds.stderr | 12 ++++++ 2 files changed, 52 insertions(+) create mode 100644 tests/ui/traits/new-solver/negative-coherence-bounds.rs create mode 100644 tests/ui/traits/new-solver/negative-coherence-bounds.stderr diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.rs b/tests/ui/traits/new-solver/negative-coherence-bounds.rs new file mode 100644 index 0000000000000..5436b02c3ded2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.rs @@ -0,0 +1,40 @@ +// check-pass + +// This test verifies that negative trait predicate cannot be satisfied from a +// positive param-env candidate. + +// Negative coherence is one of the only places where we actually construct and +// evaluate negative predicates. Specifically, when verifying whether the first +// and second impls below overlap, we do not want to consider them disjoint, +// otherwise the second impl would be missing an associated type `type Item` +// which is provided by the first impl that it is specializing. + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete +#![feature(with_negative_coherence)] + +trait BoxIter { + type Item; + + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + + default fn last(self) -> Option { + todo!() + } +} + +// When checking that this impl does/doesn't overlap the one above, we evaluate +// a negative version of all of the where-clause predicates of the impl below. +// For `I: !Iterator`, we should make sure that the param-env clause `I: Iterator` +// from above doesn't satisfy this predicate. +impl BoxIter for Box { + fn last(self) -> Option { + (*self).last() + } +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/negative-coherence-bounds.stderr b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr new file mode 100644 index 0000000000000..4127f51f56da2 --- /dev/null +++ b/tests/ui/traits/new-solver/negative-coherence-bounds.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/negative-coherence-bounds.rs:12:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + From 3b196fb391ea9c869a798005e0fd7c84214518f4 Mon Sep 17 00:00:00 2001 From: Mads Ravn Date: Tue, 25 Apr 2023 13:50:50 +0200 Subject: [PATCH 13/15] Updating Wake example to use new 'pin!' macro --- library/alloc/src/task.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 9d8e309a978d9..5d9772b878b03 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -39,6 +39,7 @@ use crate::sync::Arc; /// use std::sync::Arc; /// use std::task::{Context, Poll, Wake}; /// use std::thread::{self, Thread}; +/// use core::pin::pin; /// /// /// A waker that wakes up the current thread when called. /// struct ThreadWaker(Thread); @@ -52,7 +53,7 @@ use crate::sync::Arc; /// /// Run a future to completion on the current thread. /// fn block_on(fut: impl Future) -> T { /// // Pin the future so it can be polled. -/// let mut fut = Box::pin(fut); +/// let mut fut = pin!(fut); /// /// // Create a new context to be passed to the future. /// let t = thread::current(); From 040e1b6b5fccc4c9e084ce620f95ebf8fd13ed8d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 24 Apr 2023 17:04:26 -0700 Subject: [PATCH 14/15] Fix ICE on --print=... i/o errors --- compiler/rustc_driver_impl/src/lib.rs | 88 ++++++++++++++----------- compiler/rustc_driver_impl/src/print.rs | 20 ++++++ 2 files changed, 68 insertions(+), 40 deletions(-) create mode 100644 compiler/rustc_driver_impl/src/print.rs diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 1a80b4fc3140d..5fac485de6417 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -58,8 +58,16 @@ use std::str; use std::sync::LazyLock; use std::time::Instant; +// This import blocks the use of panicking `print` and `println` in all the code +// below. Please use `safe_print` and `safe_println` to avoid ICE when +// encountering an I/O error during print. +#[allow(unused_imports)] +use std::{compile_error as print, compile_error as println}; + pub mod args; pub mod pretty; +#[macro_use] +mod print; mod session_diagnostics; use crate::session_diagnostics::{ @@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { if io::stdout().is_terminal() { show_content_with_pager(&text); } else { - print!("{text}"); + safe_print!("{text}"); } } Err(InvalidErrorCode) => { @@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - print!("{content}"); + safe_print!("{content}"); } } @@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co let path = &(*ifile); let mut v = Vec::new(); locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap(); - println!("{}", String::from_utf8(v).unwrap()); + safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); @@ -642,12 +650,12 @@ fn print_crate_info( TargetList => { let mut targets = rustc_target::spec::TARGETS.to_vec(); targets.sort_unstable(); - println!("{}", targets.join("\n")); + safe_println!("{}", targets.join("\n")); } - Sysroot => println!("{}", sess.sysroot.display()), - TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()), + Sysroot => safe_println!("{}", sess.sysroot.display()), + TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()), TargetSpec => { - println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } AllTargetSpecs => { let mut targets = BTreeMap::new(); @@ -656,7 +664,7 @@ fn print_crate_info( let target = Target::expect_builtin(&triple); targets.insert(name, target.to_json()); } - println!("{}", serde_json::to_string_pretty(&targets).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap()); } FileNames | CrateName => { let Some(attrs) = attrs.as_ref() else { @@ -666,14 +674,14 @@ fn print_crate_info( let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let id = rustc_session::output::find_crate_name(sess, attrs); if *req == PrintRequest::CrateName { - println!("{id}"); + safe_println!("{id}"); continue; } let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_session::output::filename_for_input(sess, style, id, &t_outputs); - println!("{}", fname.file_name().unwrap().to_string_lossy()); + safe_println!("{}", fname.file_name().unwrap().to_string_lossy()); } } Cfg => { @@ -707,13 +715,13 @@ fn print_crate_info( cfgs.sort(); for cfg in cfgs { - println!("{cfg}"); + safe_println!("{cfg}"); } } CallingConventions => { let mut calling_conventions = rustc_target::spec::abi::all_names(); calling_conventions.sort_unstable(); - println!("{}", calling_conventions.join("\n")); + safe_println!("{}", calling_conventions.join("\n")); } RelocationModels | CodeModels @@ -733,7 +741,7 @@ fn print_crate_info( let stable = sess.target.options.supported_split_debuginfo.contains(split); let unstable_ok = sess.unstable_options(); if stable || unstable_ok { - println!("{split}"); + safe_println!("{split}"); } } } @@ -770,14 +778,14 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); - println!("{binary} {version}"); + safe_println!("{binary} {version}"); if verbose { - println!("binary: {binary}"); - println!("commit-hash: {commit_hash}"); - println!("commit-date: {commit_date}"); - println!("host: {}", config::host_triple()); - println!("release: {release}"); + safe_println!("binary: {binary}"); + safe_println!("commit-hash: {commit_hash}"); + safe_println!("commit-date: {commit_date}"); + safe_println!("host: {}", config::host_triple()); + safe_println!("release: {release}"); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } else { "" }; - println!( + safe_println!( "{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ @@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } fn print_wall_help() { - println!( + safe_println!( " The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by default. Use `rustc -W help` to see all available lints. It's more common to put @@ -832,7 +840,7 @@ the command line flag directly. /// Write to stdout lint command options, together with a list of all available lints pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { - println!( + safe_println!( " Available lint options: -W Warn about @@ -877,21 +885,21 @@ Available lint options: s }; - println!("Lint checks provided by rustc:\n"); + safe_println!("Lint checks provided by rustc:\n"); let print_lints = |lints: Vec<&Lint>| { - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); + safe_println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + safe_println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); - println!( + safe_println!( " {} {:7.7} {}", padded(&name), lint.default_level(sess.edition()).as_str(), lint.desc ); } - println!("\n"); + safe_println!("\n"); }; print_lints(builtin); @@ -912,14 +920,14 @@ Available lint options: s }; - println!("Lint groups provided by rustc:\n"); + safe_println!("Lint groups provided by rustc:\n"); let print_lint_groups = |lints: Vec<(&'static str, Vec)>, all_warnings| { - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); + safe_println!(" {} sub-lints", padded("name")); + safe_println!(" {} ---------", padded("----")); if all_warnings { - println!(" {} all lints that are set to issue warnings", padded("warnings")); + safe_println!(" {} all lints that are set to issue warnings", padded("warnings")); } for (name, to) in lints { @@ -929,26 +937,26 @@ Available lint options: .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); - println!(" {} {}", padded(&name), desc); + safe_println!(" {} {}", padded(&name), desc); } - println!("\n"); + safe_println!("\n"); }; print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { - println!("Lint tools like Clippy can provide additional lints and lint groups."); + safe_println!("Lint tools like Clippy can provide additional lints and lint groups."); } (false, ..) => panic!("didn't load lint plugins but got them anyway!"), - (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."), + (true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."), (true, l, g) => { if l > 0 { - println!("Lint checks provided by plugins loaded by this crate:\n"); + safe_println!("Lint checks provided by plugins loaded by this crate:\n"); print_lints(plugin); } if g > 0 { - println!("Lint groups provided by plugins loaded by this crate:\n"); + safe_println!("Lint groups provided by plugins loaded by this crate:\n"); print_lint_groups(plugin_groups, false); } } @@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } fn describe_debug_flags() { - println!("\nAvailable options:\n"); + safe_println!("\nAvailable options:\n"); print_flag_list("-Z", config::Z_OPTIONS); } fn describe_codegen_flags() { - println!("\nAvailable codegen options:\n"); + safe_println!("\nAvailable codegen options:\n"); print_flag_list("-C", config::CG_OPTIONS); } @@ -1012,7 +1020,7 @@ fn print_flag_list( let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0); for &(name, _, _, desc) in flag_list { - println!( + safe_println!( " {} {:>width$}=val -- {}", cmdline_opt, name.replace('_', "-"), diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs new file mode 100644 index 0000000000000..70de55320f7ae --- /dev/null +++ b/compiler/rustc_driver_impl/src/print.rs @@ -0,0 +1,20 @@ +use std::fmt; +use std::io::{self, Write as _}; + +macro_rules! safe_print { + ($($arg:tt)*) => {{ + $crate::print::print(std::format_args!($($arg)*)); + }}; +} + +macro_rules! safe_println { + ($($arg:tt)*) => { + safe_print!("{}\n", std::format_args!($($arg)*)) + }; +} + +pub(crate) fn print(args: fmt::Arguments<'_>) { + if let Err(_) = io::stdout().write_fmt(args) { + rustc_errors::FatalError.raise(); + } +} From bec7ce482458429471c1a4c1b50bcc3728297e5e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 25 Apr 2023 17:37:12 +0000 Subject: [PATCH 15/15] Add `#[inline]` in `impl_tag` --- compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs index 0b0c152cc4db4..cb7f7d318dc41 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -100,6 +100,7 @@ macro_rules! impl_tag { )* ]); + #[inline] fn into_usize(self) -> usize { // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) // (or at least it should, see ) @@ -112,6 +113,7 @@ macro_rules! impl_tag { } } + #[inline] unsafe fn from_usize(tag: usize) -> Self { match tag { $(