From febb3f7c8814432f5905ecf31137a804c8a5cb1a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 20 Oct 2024 20:35:18 +0000 Subject: [PATCH] Represent TraitBoundModifiers as distinct parts in HIR --- compiler/rustc_ast/src/ast.rs | 4 +-- compiler/rustc_ast_lowering/src/lib.rs | 22 +++--------- compiler/rustc_hir/src/hir.rs | 29 +++++++-------- .../src/hir_ty_lowering/bounds.rs | 35 +++++++++---------- .../src/hir_ty_lowering/dyn_compatibility.rs | 3 +- compiler/rustc_hir_pretty/src/lib.rs | 14 +++++--- compiler/rustc_lint/src/traits.rs | 5 +-- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- .../error_reporting/infer/note_and_explain.rs | 2 +- src/librustdoc/clean/mod.rs | 4 +-- src/librustdoc/clean/types.rs | 19 ++++++---- src/librustdoc/html/format.rs | 14 ++++---- src/librustdoc/json/conversions.rs | 24 ++++++------- .../src/implied_bounds_in_impls.rs | 6 ++-- .../clippy_lints/src/needless_maybe_sized.rs | 6 ++-- .../clippy/clippy_lints/src/trait_bounds.rs | 14 ++++---- .../clippy/clippy_utils/src/hir_utils.rs | 14 +++++++- tests/ui/stats/hir-stats.stderr | 16 ++++----- 18 files changed, 116 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 02cb6f188a718..8e4f4c8e71a2e 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2697,7 +2697,7 @@ impl fmt::Debug for ImplPolarity { } /// The polarity of a trait bound. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)] #[derive(HashStable_Generic)] pub enum BoundPolarity { /// `Type: Trait` @@ -2719,7 +2719,7 @@ impl BoundPolarity { } /// The constness of a trait bound. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)] #[derive(HashStable_Generic)] pub enum BoundConstness { /// `Type: Trait` diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4d8d22e09d922..28523bcb3bf7b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1956,7 +1956,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::GenericBound::Trait(hir::PolyTraitRef { bound_generic_params: &[], - modifiers: hir::TraitBoundModifier::None, + modifiers: hir::TraitBoundModifiers::NONE, trait_ref: hir::TraitRef { path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)), hir_ref_id: self.next_id(), @@ -2445,22 +2445,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_bound_modifiers( &mut self, modifiers: TraitBoundModifiers, - ) -> hir::TraitBoundModifier { - // Invalid modifier combinations will cause an error during AST validation. - // Arbitrarily pick a placeholder for them to make compilation proceed. - match (modifiers.constness, modifiers.polarity) { - (BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None, - (_, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe, - (BoundConstness::Never, BoundPolarity::Negative(_)) => { - if self.tcx.features().negative_bounds { - hir::TraitBoundModifier::Negative - } else { - hir::TraitBoundModifier::None - } - } - (BoundConstness::Always(_), _) => hir::TraitBoundModifier::Const, - (BoundConstness::Maybe(_), _) => hir::TraitBoundModifier::MaybeConst, - } + ) -> hir::TraitBoundModifiers { + hir::TraitBoundModifiers { constness: modifiers.constness, polarity: modifiers.polarity } } // Helper methods for building HIR. @@ -2626,7 +2612,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { let principal = hir::PolyTraitRef { bound_generic_params: &[], - modifiers: hir::TraitBoundModifier::None, + modifiers: hir::TraitBoundModifiers::NONE, trait_ref: hir::TraitRef { path, hir_ref_id: hir_id }, span: self.lower_span(span), }; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 009c6c4aea558..45be04c6db9ce 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -6,8 +6,8 @@ use rustc_ast::{ LitKind, TraitObjectSyntax, UintTy, }; pub use rustc_ast::{ - BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability, - Mutability, UnOp, + BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy, + ImplPolarity, IsAuto, Movability, Mutability, UnOp, }; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; @@ -502,19 +502,16 @@ pub enum GenericArgsParentheses { ParenSugar, } -/// A modifier on a trait bound. +/// The modifiers on a trait bound. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum TraitBoundModifier { - /// `Type: Trait` - None, - /// `Type: !Trait` - Negative, - /// `Type: ?Trait` - Maybe, - /// `Type: const Trait` - Const, - /// `Type: ~const Trait` - MaybeConst, +pub struct TraitBoundModifiers { + pub constness: BoundConstness, + pub polarity: BoundPolarity, +} + +impl TraitBoundModifiers { + pub const NONE: Self = + TraitBoundModifiers { constness: BoundConstness::Never, polarity: BoundPolarity::Positive }; } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -3180,7 +3177,7 @@ pub struct PolyTraitRef<'hir> { /// The constness and polarity of the trait ref. /// /// The `async` modifier is lowered directly into a different trait for now. - pub modifiers: TraitBoundModifier, + pub modifiers: TraitBoundModifiers, /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`. pub trait_ref: TraitRef<'hir>, @@ -4085,7 +4082,7 @@ mod size_asserts { static_assert_size!(ForeignItem<'_>, 88); static_assert_size!(ForeignItemKind<'_>, 56); static_assert_size!(GenericArg<'_>, 16); - static_assert_size!(GenericBound<'_>, 48); + static_assert_size!(GenericBound<'_>, 64); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); static_assert_size!(ImplItem<'_>, 88); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 4721a3a0cf5ad..a8b2b9b7c0ac3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -45,23 +45,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let hir::GenericBound::Trait(ptr) = hir_bound else { continue; }; - match ptr.modifiers { - hir::TraitBoundModifier::Maybe => unbounds.push(ptr), - hir::TraitBoundModifier::Negative => { + match ptr.modifiers.polarity { + hir::BoundPolarity::Maybe(_) => unbounds.push(ptr), + hir::BoundPolarity::Negative(_) => { if let Some(sized_def_id) = sized_def_id && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) { seen_negative_sized_bound = true; } } - hir::TraitBoundModifier::None => { + hir::BoundPolarity::Positive => { if let Some(sized_def_id) = sized_def_id && ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id) { seen_positive_sized_bound = true; } } - _ => {} } } }; @@ -169,20 +168,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match hir_bound { hir::GenericBound::Trait(poly_trait_ref) => { - let (constness, polarity) = match poly_trait_ref.modifiers { - hir::TraitBoundModifier::Const => { - (Some(ty::BoundConstness::Const), ty::PredicatePolarity::Positive) - } - hir::TraitBoundModifier::MaybeConst => ( - Some(ty::BoundConstness::ConstIfConst), - ty::PredicatePolarity::Positive, - ), - hir::TraitBoundModifier::None => (None, ty::PredicatePolarity::Positive), - hir::TraitBoundModifier::Negative => { - (None, ty::PredicatePolarity::Negative) - } - hir::TraitBoundModifier::Maybe => continue, + let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers; + // FIXME: We could pass these directly into `lower_poly_trait_ref` + // so that we could use these spans in diagnostics within that function... + let constness = match constness { + hir::BoundConstness::Never => None, + hir::BoundConstness::Always(_) => Some(ty::BoundConstness::Const), + hir::BoundConstness::Maybe(_) => Some(ty::BoundConstness::ConstIfConst), }; + let polarity = match polarity { + rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive, + rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, + rustc_ast::BoundPolarity::Maybe(_) => continue, + }; + let _ = self.lower_poly_trait_ref( &poly_trait_ref.trait_ref, poly_trait_ref.span, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 4cb55ec8c890c..2cee7c77aa538 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -40,8 +40,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; for trait_bound in hir_trait_bounds.iter().rev() { - // FIXME: This doesn't handle `? const`. - if trait_bound.modifiers == hir::TraitBoundModifier::Maybe { + if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { continue; } if let GenericArgCountResult { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9ebfd4f15abd3..3ba9c76bcee3a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -16,7 +16,6 @@ use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir::{ BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, - TraitBoundModifier, }; use rustc_span::FileName; use rustc_span::source_map::SourceMap; @@ -676,9 +675,16 @@ impl<'a> State<'a> { } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) { - // FIXME: This isn't correct! - if t.modifiers == TraitBoundModifier::Maybe { - self.word("?"); + let hir::TraitBoundModifiers { constness, polarity } = t.modifiers; + match constness { + hir::BoundConstness::Never => {} + hir::BoundConstness::Always(_) => self.word("const"), + hir::BoundConstness::Maybe(_) => self.word("~const"), + } + match polarity { + hir::BoundPolarity::Positive => {} + hir::BoundPolarity::Negative(_) => self.word("!"), + hir::BoundPolarity::Maybe(_) => self.word("?"), } self.print_formal_generic_params(t.bound_generic_params); self.print_trait_ref(&t.trait_ref); diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 5a3666dcbd432..b793ec6a4939e 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -114,10 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); - if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) - // FIXME: ?Drop is not a thing. - && bound.modifiers != hir::TraitBoundModifier::Maybe - { + if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) { let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id }); } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 4f408ee157481..8bd2ae9128f7c 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -193,7 +193,7 @@ fn suggest_changing_unsized_bound( .enumerate() .filter(|(_, bound)| { if let hir::GenericBound::Trait(poly) = bound - && poly.modifiers == hir::TraitBoundModifier::Maybe + && let hir::BoundPolarity::Maybe(_) = poly.modifiers.polarity && poly.trait_ref.trait_def_id() == def_id { true diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 62204f63dd09a..0cf7c43beb541 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -894,7 +894,7 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. let trait_bounds = bounds.iter().filter_map(|bound| match bound { - hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifier::None => { + hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifiers::NONE => { Some(ptr) } _ => None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7d4d8d8941dcb..848f2abe6a9f0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -216,7 +216,7 @@ fn clean_generic_bound<'tcx>( hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)), hir::GenericBound::Trait(ref t) => { // `T: ~const Destruct` is hidden because `T: Destruct` is a no-op. - if t.modifiers == hir::TraitBoundModifier::MaybeConst + if let hir::BoundConstness::Maybe(_) = t.modifiers.constness && cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap()) { return None; @@ -263,7 +263,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>( trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints), generic_params: clean_bound_vars(poly_trait_ref.bound_vars()), }, - hir::TraitBoundModifier::None, + hir::TraitBoundModifiers::NONE, ) } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 675507a44c9cc..2e3050eee2fb0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1257,7 +1257,7 @@ impl Eq for Attributes {} #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericBound { - TraitBound(PolyTrait, hir::TraitBoundModifier), + TraitBound(PolyTrait, hir::TraitBoundModifiers), Outlives(Lifetime), /// `use<'a, T>` precise-capturing bound syntax Use(Vec), @@ -1265,19 +1265,22 @@ pub(crate) enum GenericBound { impl GenericBound { pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound { - Self::sized_with(cx, hir::TraitBoundModifier::None) + Self::sized_with(cx, hir::TraitBoundModifiers::NONE) } pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound { - Self::sized_with(cx, hir::TraitBoundModifier::Maybe) + Self::sized_with(cx, hir::TraitBoundModifiers { + polarity: hir::BoundPolarity::Maybe(DUMMY_SP), + constness: hir::BoundConstness::Never, + }) } - fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound { + fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); let empty = ty::Binder::dummy(ty::GenericArgs::empty()); let path = clean_middle_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier) + GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers) } pub(crate) fn is_trait_bound(&self) -> bool { @@ -1285,8 +1288,10 @@ impl GenericBound { } pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { - use rustc_hir::TraitBoundModifier as TBM; - if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self + if let GenericBound::TraitBound( + PolyTrait { ref trait_, .. }, + rustc_hir::TraitBoundModifiers::NONE, + ) = *self && Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait() { return true; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 2e70a8c080de0..5c599f20f9fdb 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -399,13 +399,13 @@ impl clean::GenericBound { ) -> impl Display + 'a + Captures<'tcx> { display_fn(move |f| match self { clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()), - clean::GenericBound::TraitBound(ty, modifier) => { - f.write_str(match modifier { - hir::TraitBoundModifier::None => "", - hir::TraitBoundModifier::Maybe => "?", - hir::TraitBoundModifier::Negative => "!", - // `const` and `~const` trait bounds are experimental; don't render them. - hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "", + clean::GenericBound::TraitBound(ty, modifiers) => { + // `const` and `~const` trait bounds are experimental; don't render them. + let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers; + f.write_str(match polarity { + hir::BoundPolarity::Positive => "", + hir::BoundPolarity::Maybe(_) => "?", + hir::BoundPolarity::Negative(_) => "!", })?; ty.print(cx).fmt(f) } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 0130f2ce517bf..7270f170780a2 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -552,20 +552,18 @@ impl FromClean for GenericBound { } pub(crate) fn from_trait_bound_modifier( - modifier: rustc_hir::TraitBoundModifier, + modifiers: rustc_hir::TraitBoundModifiers, ) -> TraitBoundModifier { - use rustc_hir::TraitBoundModifier::*; - match modifier { - None => TraitBoundModifier::None, - Maybe => TraitBoundModifier::Maybe, - MaybeConst => TraitBoundModifier::MaybeConst, - // FIXME(const_trait_impl): Create rjt::TBM::Const and map to it once always-const bounds - // are less experimental. - Const => TraitBoundModifier::None, - // FIXME(negative-bounds): This bound should be rendered negative, but - // since that's experimental, maybe let's not add it to the rustdoc json - // API just now... - Negative => TraitBoundModifier::None, + use rustc_hir as hir; + let hir::TraitBoundModifiers { constness, polarity } = modifiers; + match (constness, polarity) { + (hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None, + (hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe, + (hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => { + TraitBoundModifier::MaybeConst + } + // FIXME: Fill out the rest of this matrix. + _ => TraitBoundModifier::None, } } diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 00f832372248e..65fdc93e0ed99 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::def_id::DefId; use rustc_hir::{ - AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifier, TyKind, + AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind, WherePredicate, }; use rustc_hir_analysis::lower_ty; @@ -234,7 +234,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds .iter() .filter_map(|bound| { if let GenericBound::Trait(poly_trait) = bound - && let TraitBoundModifier::None = poly_trait.modifiers + && let TraitBoundModifiers::NONE = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && poly_trait.bound_generic_params.is_empty() && let Some(trait_def_id) = path.res.opt_def_id() @@ -300,7 +300,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) { // simply comparing trait `DefId`s won't be enough. We also need to compare the generics. for (index, bound) in bounds.iter().enumerate() { if let GenericBound::Trait(poly_trait) = bound - && let TraitBoundModifier::None = poly_trait.modifiers + && let TraitBoundModifiers::NONE = poly_trait.modifiers && let [.., path] = poly_trait.trait_ref.path.segments && let implied_args = path.args.map_or([].as_slice(), |a| a.args) && let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints) diff --git a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs index 68c9af07465d3..9a1c397b5b237 100644 --- a/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs +++ b/src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifier, WherePredicate}; +use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, BoundPolarity, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ClauseKind, PredicatePolarity}; use rustc_session::declare_lint_pass; @@ -118,13 +118,13 @@ impl LateLintPass<'_> for NeedlessMaybeSized { let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics) .filter(|bound| { bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait) - && bound.trait_bound.modifiers == TraitBoundModifier::Maybe + && matches!(bound.trait_bound.modifiers.polarity, BoundPolarity::Maybe(_)) }) .map(|bound| (bound.param, bound)) .collect(); for bound in type_param_bounds(generics) { - if bound.trait_bound.modifiers == TraitBoundModifier::None + if bound.trait_bound.modifiers == TraitBoundModifiers::NONE && let Some(sized_bound) = maybe_sized_params.get(&bound.param) && let Some(path) = path_to_sized_bound(cx, bound.trait_bound) { diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 7f528b9d17b80..3da4bf67558dd 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -11,7 +11,7 @@ use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, - TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate, + TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicate, BoundPolarity, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -233,7 +233,7 @@ impl TraitBounds { fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool { if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE) && let GenericBound::Trait(tr) = bound - && let TraitBoundModifier::Maybe = tr.modifiers + && let BoundPolarity::Maybe(_) = tr.modifiers.polarity { cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id() } else { @@ -374,12 +374,12 @@ fn check_trait_bound_duplication<'tcx>(cx: &LateContext<'tcx>, generics: &'_ Gen struct ComparableTraitRef<'a, 'tcx> { cx: &'a LateContext<'tcx>, trait_ref: &'tcx TraitRef<'tcx>, - modifier: TraitBoundModifier, + modifiers: TraitBoundModifiers, } impl PartialEq for ComparableTraitRef<'_, '_> { fn eq(&self, other: &Self) -> bool { - self.modifier == other.modifier + SpanlessEq::new(self.cx).eq_modifiers(self.modifiers, other.modifiers) && SpanlessEq::new(self.cx) .paths_by_resolution() .eq_path(self.trait_ref.path, other.trait_ref.path) @@ -390,8 +390,8 @@ impl Hash for ComparableTraitRef<'_, '_> { fn hash(&self, state: &mut H) { let mut s = SpanlessHash::new(self.cx).paths_by_resolution(); s.hash_path(self.trait_ref.path); + s.hash_modifiers(self.modifiers); state.write_u64(s.finish()); - self.modifier.hash(state); } } @@ -400,7 +400,7 @@ fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &' let trait_path = t.trait_ref.path; let trait_span = { let path_span = trait_path.span; - if let TraitBoundModifier::Maybe = t.modifiers { + if let BoundPolarity::Maybe(_) = t.modifiers.polarity { path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?` } else { path_span @@ -427,7 +427,7 @@ fn rollup_traits<'cx, 'tcx>( ComparableTraitRef { cx, trait_ref: &t.trait_ref, - modifier: t.modifiers, + modifiers: t.modifiers, }, t.span, )) diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 27c57808ecea8..181d414cbbded 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -9,7 +9,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::{ ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, - LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, + LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty, + TyKind, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::LateContext; @@ -126,6 +127,11 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { pub fn eq_path_segments(&mut self, left: &[PathSegment<'_>], right: &[PathSegment<'_>]) -> bool { self.inter_expr().eq_path_segments(left, right) } + + pub fn eq_modifiers(&mut self, left: TraitBoundModifiers, right: TraitBoundModifiers) -> bool { + std::mem::discriminant(&left.constness) == std::mem::discriminant(&right.constness) + && std::mem::discriminant(&left.polarity) == std::mem::discriminant(&right.polarity) + } } pub struct HirEqInterExpr<'a, 'b, 'tcx> { @@ -1143,6 +1149,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } + pub fn hash_modifiers(&mut self, modifiers: TraitBoundModifiers) { + let TraitBoundModifiers { constness, polarity } = modifiers; + std::mem::discriminant(&polarity).hash(&mut self.s); + std::mem::discriminant(&constness).hash(&mut self.s); + } + pub fn hash_stmt(&mut self, b: &Stmt<'_>) { std::mem::discriminant(&b.kind).hash(&mut self.s); diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 3a2d4df3bee6d..bd0c8cbc3b12b 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -141,10 +141,10 @@ hir-stats FnDecl 120 ( 1.3%) 3 40 hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats GenericArgs 144 ( 1.6%) 3 48 hir-stats Variant 144 ( 1.6%) 2 72 -hir-stats GenericBound 192 ( 2.1%) 4 48 -hir-stats - Trait 192 ( 2.1%) 4 hir-stats WherePredicate 192 ( 2.1%) 3 64 hir-stats - BoundPredicate 192 ( 2.1%) 3 +hir-stats GenericBound 256 ( 2.8%) 4 64 +hir-stats - Trait 256 ( 2.8%) 4 hir-stats Block 288 ( 3.2%) 6 48 hir-stats GenericParam 360 ( 4.0%) 5 72 hir-stats Pat 360 ( 4.0%) 5 72 @@ -155,15 +155,15 @@ hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Ptr 48 ( 0.5%) 1 -hir-stats - Path 624 ( 7.0%) 13 -hir-stats Expr 768 ( 8.6%) 12 64 +hir-stats - Path 624 ( 6.9%) 13 +hir-stats Expr 768 ( 8.5%) 12 64 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Lit 128 ( 1.4%) 2 hir-stats - Block 384 ( 4.3%) 6 -hir-stats Item 968 (10.8%) 11 88 +hir-stats Item 968 (10.7%) 11 88 hir-stats - Enum 88 ( 1.0%) 1 hir-stats - Trait 88 ( 1.0%) 1 hir-stats - Impl 88 ( 1.0%) 1 @@ -171,8 +171,8 @@ hir-stats - ExternCrate 88 ( 1.0%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1 hir-stats - Fn 176 ( 2.0%) 2 hir-stats - Use 352 ( 3.9%) 4 -hir-stats Path 1_240 (13.8%) 31 40 -hir-stats PathSegment 1_920 (21.4%) 40 48 +hir-stats Path 1_240 (13.7%) 31 40 +hir-stats PathSegment 1_920 (21.3%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_960 +hir-stats Total 9_024 hir-stats