diff options
| author | Michael Goulet <michael@errs.io> | 2024-10-20 20:35:18 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-10-22 19:48:44 +0000 |
| commit | febb3f7c8814432f5905ecf31137a804c8a5cb1a (patch) | |
| tree | 7d5915d22761a1d5e79e94bc2abdbba17b365ab3 /src | |
| parent | 86d69c705a552236a622eee3fdea94bf13c5f102 (diff) | |
| download | rust-febb3f7c8814432f5905ecf31137a804c8a5cb1a.tar.gz rust-febb3f7c8814432f5905ecf31137a804c8a5cb1a.zip | |
Represent TraitBoundModifiers as distinct parts in HIR
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 4 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 19 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 14 | ||||
| -rw-r--r-- | src/librustdoc/json/conversions.rs | 24 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs | 6 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_lints/src/needless_maybe_sized.rs | 6 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_lints/src/trait_bounds.rs | 14 | ||||
| -rw-r--r-- | src/tools/clippy/clippy_utils/src/hir_utils.rs | 14 |
8 files changed, 58 insertions, 43 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7d4d8d8941d..848f2abe6a9 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 675507a44c9..2e3050eee2f 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<Symbol>), @@ -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 2e70a8c080d..5c599f20f9f 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 0130f2ce517..7270f170780 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -552,20 +552,18 @@ impl FromClean<clean::GenericBound> 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 00f83237224..65fdc93e0ed 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 68c9af07465..9a1c397b5b2 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 7f528b9d17b..3da4bf67558 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<H: Hasher>(&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 27c57808ece..181d414cbbd 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); |
