Skip to content

Commit e1f3068

Browse files
committed
Auto merge of rust-lang#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
2 parents b131765 + febb3f7 commit e1f3068

File tree

18 files changed

+116
-117
lines changed

18 files changed

+116
-117
lines changed

compiler/rustc_ast/src/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ impl fmt::Debug for ImplPolarity {
26972697
}
26982698

26992699
/// The polarity of a trait bound.
2700-
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
2700+
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)]
27012701
#[derive(HashStable_Generic)]
27022702
pub enum BoundPolarity {
27032703
/// `Type: Trait`
@@ -2719,7 +2719,7 @@ impl BoundPolarity {
27192719
}
27202720

27212721
/// The constness of a trait bound.
2722-
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
2722+
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash)]
27232723
#[derive(HashStable_Generic)]
27242724
pub enum BoundConstness {
27252725
/// `Type: Trait`

compiler/rustc_ast_lowering/src/lib.rs

+4-18
Original file line numberDiff line numberDiff line change
@@ -1956,7 +1956,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
19561956

19571957
hir::GenericBound::Trait(hir::PolyTraitRef {
19581958
bound_generic_params: &[],
1959-
modifiers: hir::TraitBoundModifier::None,
1959+
modifiers: hir::TraitBoundModifiers::NONE,
19601960
trait_ref: hir::TraitRef {
19611961
path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)),
19621962
hir_ref_id: self.next_id(),
@@ -2445,22 +2445,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24452445
fn lower_trait_bound_modifiers(
24462446
&mut self,
24472447
modifiers: TraitBoundModifiers,
2448-
) -> hir::TraitBoundModifier {
2449-
// Invalid modifier combinations will cause an error during AST validation.
2450-
// Arbitrarily pick a placeholder for them to make compilation proceed.
2451-
match (modifiers.constness, modifiers.polarity) {
2452-
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
2453-
(_, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
2454-
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
2455-
if self.tcx.features().negative_bounds {
2456-
hir::TraitBoundModifier::Negative
2457-
} else {
2458-
hir::TraitBoundModifier::None
2459-
}
2460-
}
2461-
(BoundConstness::Always(_), _) => hir::TraitBoundModifier::Const,
2462-
(BoundConstness::Maybe(_), _) => hir::TraitBoundModifier::MaybeConst,
2463-
}
2448+
) -> hir::TraitBoundModifiers {
2449+
hir::TraitBoundModifiers { constness: modifiers.constness, polarity: modifiers.polarity }
24642450
}
24652451

24662452
// Helper methods for building HIR.
@@ -2626,7 +2612,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
26262612
Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => {
26272613
let principal = hir::PolyTraitRef {
26282614
bound_generic_params: &[],
2629-
modifiers: hir::TraitBoundModifier::None,
2615+
modifiers: hir::TraitBoundModifiers::NONE,
26302616
trait_ref: hir::TraitRef { path, hir_ref_id: hir_id },
26312617
span: self.lower_span(span),
26322618
};

compiler/rustc_hir/src/hir.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_ast::{
66
LitKind, TraitObjectSyntax, UintTy,
77
};
88
pub use rustc_ast::{
9-
BinOp, BinOpKind, BindingMode, BorrowKind, ByRef, CaptureBy, ImplPolarity, IsAuto, Movability,
10-
Mutability, UnOp,
9+
BinOp, BinOpKind, BindingMode, BorrowKind, BoundConstness, BoundPolarity, ByRef, CaptureBy,
10+
ImplPolarity, IsAuto, Movability, Mutability, UnOp,
1111
};
1212
use rustc_data_structures::fingerprint::Fingerprint;
1313
use rustc_data_structures::sorted_map::SortedMap;
@@ -502,19 +502,16 @@ pub enum GenericArgsParentheses {
502502
ParenSugar,
503503
}
504504

505-
/// A modifier on a trait bound.
505+
/// The modifiers on a trait bound.
506506
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
507-
pub enum TraitBoundModifier {
508-
/// `Type: Trait`
509-
None,
510-
/// `Type: !Trait`
511-
Negative,
512-
/// `Type: ?Trait`
513-
Maybe,
514-
/// `Type: const Trait`
515-
Const,
516-
/// `Type: ~const Trait`
517-
MaybeConst,
507+
pub struct TraitBoundModifiers {
508+
pub constness: BoundConstness,
509+
pub polarity: BoundPolarity,
510+
}
511+
512+
impl TraitBoundModifiers {
513+
pub const NONE: Self =
514+
TraitBoundModifiers { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
518515
}
519516

520517
#[derive(Clone, Copy, Debug, HashStable_Generic)]
@@ -3180,7 +3177,7 @@ pub struct PolyTraitRef<'hir> {
31803177
/// The constness and polarity of the trait ref.
31813178
///
31823179
/// The `async` modifier is lowered directly into a different trait for now.
3183-
pub modifiers: TraitBoundModifier,
3180+
pub modifiers: TraitBoundModifiers,
31843181

31853182
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
31863183
pub trait_ref: TraitRef<'hir>,
@@ -4085,7 +4082,7 @@ mod size_asserts {
40854082
static_assert_size!(ForeignItem<'_>, 88);
40864083
static_assert_size!(ForeignItemKind<'_>, 56);
40874084
static_assert_size!(GenericArg<'_>, 16);
4088-
static_assert_size!(GenericBound<'_>, 48);
4085+
static_assert_size!(GenericBound<'_>, 64);
40894086
static_assert_size!(Generics<'_>, 56);
40904087
static_assert_size!(Impl<'_>, 80);
40914088
static_assert_size!(ImplItem<'_>, 88);

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
4545
let hir::GenericBound::Trait(ptr) = hir_bound else {
4646
continue;
4747
};
48-
match ptr.modifiers {
49-
hir::TraitBoundModifier::Maybe => unbounds.push(ptr),
50-
hir::TraitBoundModifier::Negative => {
48+
match ptr.modifiers.polarity {
49+
hir::BoundPolarity::Maybe(_) => unbounds.push(ptr),
50+
hir::BoundPolarity::Negative(_) => {
5151
if let Some(sized_def_id) = sized_def_id
5252
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
5353
{
5454
seen_negative_sized_bound = true;
5555
}
5656
}
57-
hir::TraitBoundModifier::None => {
57+
hir::BoundPolarity::Positive => {
5858
if let Some(sized_def_id) = sized_def_id
5959
&& ptr.trait_ref.path.res == Res::Def(DefKind::Trait, sized_def_id)
6060
{
6161
seen_positive_sized_bound = true;
6262
}
6363
}
64-
_ => {}
6564
}
6665
}
6766
};
@@ -169,20 +168,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
169168

170169
match hir_bound {
171170
hir::GenericBound::Trait(poly_trait_ref) => {
172-
let (constness, polarity) = match poly_trait_ref.modifiers {
173-
hir::TraitBoundModifier::Const => {
174-
(Some(ty::BoundConstness::Const), ty::PredicatePolarity::Positive)
175-
}
176-
hir::TraitBoundModifier::MaybeConst => (
177-
Some(ty::BoundConstness::ConstIfConst),
178-
ty::PredicatePolarity::Positive,
179-
),
180-
hir::TraitBoundModifier::None => (None, ty::PredicatePolarity::Positive),
181-
hir::TraitBoundModifier::Negative => {
182-
(None, ty::PredicatePolarity::Negative)
183-
}
184-
hir::TraitBoundModifier::Maybe => continue,
171+
let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
172+
// FIXME: We could pass these directly into `lower_poly_trait_ref`
173+
// so that we could use these spans in diagnostics within that function...
174+
let constness = match constness {
175+
hir::BoundConstness::Never => None,
176+
hir::BoundConstness::Always(_) => Some(ty::BoundConstness::Const),
177+
hir::BoundConstness::Maybe(_) => Some(ty::BoundConstness::ConstIfConst),
185178
};
179+
let polarity = match polarity {
180+
rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
181+
rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
182+
rustc_ast::BoundPolarity::Maybe(_) => continue,
183+
};
184+
186185
let _ = self.lower_poly_trait_ref(
187186
&poly_trait_ref.trait_ref,
188187
poly_trait_ref.span,

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
4040
let mut potential_assoc_types = Vec::new();
4141
let dummy_self = self.tcx().types.trait_object_dummy_self;
4242
for trait_bound in hir_trait_bounds.iter().rev() {
43-
// FIXME: This doesn't handle `? const`.
44-
if trait_bound.modifiers == hir::TraitBoundModifier::Maybe {
43+
if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
4544
continue;
4645
}
4746
if let GenericArgCountResult {

compiler/rustc_hir_pretty/src/lib.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_ast_pretty::pprust::{Comments, PrintState};
1616
use rustc_hir::{
1717
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
1818
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
19-
TraitBoundModifier,
2019
};
2120
use rustc_span::FileName;
2221
use rustc_span::source_map::SourceMap;
@@ -676,9 +675,16 @@ impl<'a> State<'a> {
676675
}
677676

678677
fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) {
679-
// FIXME: This isn't correct!
680-
if t.modifiers == TraitBoundModifier::Maybe {
681-
self.word("?");
678+
let hir::TraitBoundModifiers { constness, polarity } = t.modifiers;
679+
match constness {
680+
hir::BoundConstness::Never => {}
681+
hir::BoundConstness::Always(_) => self.word("const"),
682+
hir::BoundConstness::Maybe(_) => self.word("~const"),
683+
}
684+
match polarity {
685+
hir::BoundPolarity::Positive => {}
686+
hir::BoundPolarity::Negative(_) => self.word("!"),
687+
hir::BoundPolarity::Maybe(_) => self.word("?"),
682688
}
683689
self.print_formal_generic_params(t.bound_generic_params);
684690
self.print_trait_ref(&t.trait_ref);

compiler/rustc_lint/src/traits.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
114114
let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return };
115115
for bound in &bounds[..] {
116116
let def_id = bound.trait_ref.trait_def_id();
117-
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop))
118-
// FIXME: ?Drop is not a thing.
119-
&& bound.modifiers != hir::TraitBoundModifier::Maybe
120-
{
117+
if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) {
121118
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
122119
cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
123120
}

compiler/rustc_middle/src/ty/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ fn suggest_changing_unsized_bound(
193193
.enumerate()
194194
.filter(|(_, bound)| {
195195
if let hir::GenericBound::Trait(poly) = bound
196-
&& poly.modifiers == hir::TraitBoundModifier::Maybe
196+
&& let hir::BoundPolarity::Maybe(_) = poly.modifiers.polarity
197197
&& poly.trait_ref.trait_def_id() == def_id
198198
{
199199
true

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,7 @@ fn foo(&self) -> Self::T { String::new() }
894894
// FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
895895

896896
let trait_bounds = bounds.iter().filter_map(|bound| match bound {
897-
hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifier::None => {
897+
hir::GenericBound::Trait(ptr) if ptr.modifiers == hir::TraitBoundModifiers::NONE => {
898898
Some(ptr)
899899
}
900900
_ => None,

src/librustdoc/clean/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ fn clean_generic_bound<'tcx>(
216216
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
217217
hir::GenericBound::Trait(ref t) => {
218218
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
219-
if t.modifiers == hir::TraitBoundModifier::MaybeConst
219+
if let hir::BoundConstness::Maybe(_) = t.modifiers.constness
220220
&& cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
221221
{
222222
return None;
@@ -263,7 +263,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>(
263263
trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints),
264264
generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
265265
},
266-
hir::TraitBoundModifier::None,
266+
hir::TraitBoundModifiers::NONE,
267267
)
268268
}
269269

src/librustdoc/clean/types.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1257,36 +1257,41 @@ impl Eq for Attributes {}
12571257

12581258
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
12591259
pub(crate) enum GenericBound {
1260-
TraitBound(PolyTrait, hir::TraitBoundModifier),
1260+
TraitBound(PolyTrait, hir::TraitBoundModifiers),
12611261
Outlives(Lifetime),
12621262
/// `use<'a, T>` precise-capturing bound syntax
12631263
Use(Vec<Symbol>),
12641264
}
12651265

12661266
impl GenericBound {
12671267
pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
1268-
Self::sized_with(cx, hir::TraitBoundModifier::None)
1268+
Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
12691269
}
12701270

12711271
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
1272-
Self::sized_with(cx, hir::TraitBoundModifier::Maybe)
1272+
Self::sized_with(cx, hir::TraitBoundModifiers {
1273+
polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
1274+
constness: hir::BoundConstness::Never,
1275+
})
12731276
}
12741277

1275-
fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound {
1278+
fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
12761279
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
12771280
let empty = ty::Binder::dummy(ty::GenericArgs::empty());
12781281
let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
12791282
inline::record_extern_fqn(cx, did, ItemType::Trait);
1280-
GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier)
1283+
GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
12811284
}
12821285

12831286
pub(crate) fn is_trait_bound(&self) -> bool {
12841287
matches!(self, Self::TraitBound(..))
12851288
}
12861289

12871290
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
1288-
use rustc_hir::TraitBoundModifier as TBM;
1289-
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self
1291+
if let GenericBound::TraitBound(
1292+
PolyTrait { ref trait_, .. },
1293+
rustc_hir::TraitBoundModifiers::NONE,
1294+
) = *self
12901295
&& Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
12911296
{
12921297
return true;

src/librustdoc/html/format.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -399,13 +399,13 @@ impl clean::GenericBound {
399399
) -> impl Display + 'a + Captures<'tcx> {
400400
display_fn(move |f| match self {
401401
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
402-
clean::GenericBound::TraitBound(ty, modifier) => {
403-
f.write_str(match modifier {
404-
hir::TraitBoundModifier::None => "",
405-
hir::TraitBoundModifier::Maybe => "?",
406-
hir::TraitBoundModifier::Negative => "!",
407-
// `const` and `~const` trait bounds are experimental; don't render them.
408-
hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "",
402+
clean::GenericBound::TraitBound(ty, modifiers) => {
403+
// `const` and `~const` trait bounds are experimental; don't render them.
404+
let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers;
405+
f.write_str(match polarity {
406+
hir::BoundPolarity::Positive => "",
407+
hir::BoundPolarity::Maybe(_) => "?",
408+
hir::BoundPolarity::Negative(_) => "!",
409409
})?;
410410
ty.print(cx).fmt(f)
411411
}

src/librustdoc/json/conversions.rs

+11-13
Original file line numberDiff line numberDiff line change
@@ -552,20 +552,18 @@ impl FromClean<clean::GenericBound> for GenericBound {
552552
}
553553

554554
pub(crate) fn from_trait_bound_modifier(
555-
modifier: rustc_hir::TraitBoundModifier,
555+
modifiers: rustc_hir::TraitBoundModifiers,
556556
) -> TraitBoundModifier {
557-
use rustc_hir::TraitBoundModifier::*;
558-
match modifier {
559-
None => TraitBoundModifier::None,
560-
Maybe => TraitBoundModifier::Maybe,
561-
MaybeConst => TraitBoundModifier::MaybeConst,
562-
// FIXME(const_trait_impl): Create rjt::TBM::Const and map to it once always-const bounds
563-
// are less experimental.
564-
Const => TraitBoundModifier::None,
565-
// FIXME(negative-bounds): This bound should be rendered negative, but
566-
// since that's experimental, maybe let's not add it to the rustdoc json
567-
// API just now...
568-
Negative => TraitBoundModifier::None,
557+
use rustc_hir as hir;
558+
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
559+
match (constness, polarity) {
560+
(hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None,
561+
(hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe,
562+
(hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => {
563+
TraitBoundModifier::MaybeConst
564+
}
565+
// FIXME: Fill out the rest of this matrix.
566+
_ => TraitBoundModifier::None,
569567
}
570568
}
571569

src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::source::snippet;
33
use rustc_errors::{Applicability, SuggestionStyle};
44
use rustc_hir::def_id::DefId;
55
use rustc_hir::{
6-
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifier, TyKind,
6+
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind,
77
WherePredicate,
88
};
99
use rustc_hir_analysis::lower_ty;
@@ -234,7 +234,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds
234234
.iter()
235235
.filter_map(|bound| {
236236
if let GenericBound::Trait(poly_trait) = bound
237-
&& let TraitBoundModifier::None = poly_trait.modifiers
237+
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
238238
&& let [.., path] = poly_trait.trait_ref.path.segments
239239
&& poly_trait.bound_generic_params.is_empty()
240240
&& let Some(trait_def_id) = path.res.opt_def_id()
@@ -300,7 +300,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
300300
// simply comparing trait `DefId`s won't be enough. We also need to compare the generics.
301301
for (index, bound) in bounds.iter().enumerate() {
302302
if let GenericBound::Trait(poly_trait) = bound
303-
&& let TraitBoundModifier::None = poly_trait.modifiers
303+
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
304304
&& let [.., path] = poly_trait.trait_ref.path.segments
305305
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args)
306306
&& let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints)

0 commit comments

Comments
 (0)