mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #131982 - compiler-errors:split-trait-bound-modifiers, r=fmease
Represent `hir::TraitBoundModifiers` as distinct parts in HIR Stop squashing distinct `polarity` and `constness` into a single `hir::TraitBoundModifier`. This PR doesn't attempt to handle all the corner cases correctly, since the old code certainly did not either; but it should be much easier for, e.g., rustc devs working on diagnostics, or clippy devs, to actually handle constness and polarity correctly. try-job: x86_64-gnu-stable
This commit is contained in:
commit
e1f3068995
@ -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`
|
||||
|
@ -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),
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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 });
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 => "!",
|
||||
clean::GenericBound::TraitBound(ty, modifiers) => {
|
||||
// `const` and `~const` trait bounds are experimental; don't render them.
|
||||
hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "",
|
||||
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)
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user