Refactor AST trait bound modifiers

This commit is contained in:
León Orell Valerian Liehr 2023-12-20 15:22:06 +01:00
parent bf9229a2e3
commit 5e4f12b41a
No known key found for this signature in database
GPG Key ID: D17A07215F68E713
16 changed files with 195 additions and 201 deletions

View File

@ -286,41 +286,16 @@ impl ParenthesizedArgs {
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
/// A modifier on a bound, e.g., `?Trait` or `~const Trait`.
///
/// Negative bounds should also be handled here.
/// Modifiers on a trait bound like `~const`, `?` and `!`.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
pub enum TraitBoundModifier {
/// No modifiers
None,
/// `!Trait`
Negative,
/// `?Trait`
Maybe,
/// `~const Trait`
MaybeConst(Span),
/// `~const !Trait`
//
// This parses but will be rejected during AST validation.
MaybeConstNegative,
/// `~const ?Trait`
//
// This parses but will be rejected during AST validation.
MaybeConstMaybe,
pub struct TraitBoundModifiers {
pub constness: BoundConstness,
pub polarity: BoundPolarity,
}
impl TraitBoundModifier {
pub fn to_constness(self) -> Const {
match self {
Self::MaybeConst(span) => Const::Yes(span),
_ => Const::No,
}
}
impl TraitBoundModifiers {
pub const NONE: Self =
Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
}
/// The AST represents all type param bounds as types.
@ -329,7 +304,7 @@ impl TraitBoundModifier {
/// detects `Copy`, `Send` and `Sync`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifier),
Trait(PolyTraitRef, TraitBoundModifiers),
Outlives(Lifetime),
}
@ -1193,7 +1168,7 @@ impl Expr {
match &self.kind {
ExprKind::Path(None, path) => Some(GenericBound::Trait(
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
TraitBoundModifier::None,
TraitBoundModifiers::NONE,
)),
_ => None,
}
@ -2491,6 +2466,15 @@ pub enum Const {
No,
}
impl From<BoundConstness> for Const {
fn from(constness: BoundConstness) -> Self {
match constness {
BoundConstness::Maybe(span) => Self::Yes(span),
BoundConstness::Never => Self::No,
}
}
}
/// Item defaultness.
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
@ -2516,7 +2500,9 @@ impl fmt::Debug for ImplPolarity {
}
}
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
/// The polarity of a trait bound.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum BoundPolarity {
/// `Type: Trait`
Positive,
@ -2526,6 +2512,35 @@ pub enum BoundPolarity {
Maybe(Span),
}
impl BoundPolarity {
pub fn as_str(self) -> &'static str {
match self {
Self::Positive => "",
Self::Negative(_) => "!",
Self::Maybe(_) => "?",
}
}
}
/// The constness of a trait bound.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum BoundConstness {
/// `Type: Trait`
Never,
/// `Type: ~const Trait`
Maybe(Span),
}
impl BoundConstness {
pub fn as_str(self) -> &'static str {
match self {
Self::Never => "",
Self::Maybe(_) => "~const",
}
}
}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FnRetTy {
/// Returns type is not specified.
@ -3255,7 +3270,7 @@ mod size_asserts {
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
static_assert_size!(GenericArg, 24);
static_assert_size!(GenericBound, 64);
static_assert_size!(GenericBound, 72);
static_assert_size!(Generics, 40);
static_assert_size!(Impl, 136);
static_assert_size!(Item, 136);

View File

@ -1371,7 +1371,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
// need to compute this at all unless there is a Maybe bound.
let mut is_param: Option<bool> = None;
for bound in &bound_pred.bounds {
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
if !matches!(
*bound,
GenericBound::Trait(
_,
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }
)
) {
continue;
}
let is_param = *is_param.get_or_insert_with(compute_is_param);

View File

@ -1425,19 +1425,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
GenericBound::Trait(
ty,
modifier @ (TraitBoundModifier::None
| TraitBoundModifier::MaybeConst(_)
| TraitBoundModifier::Negative),
) => {
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
}
// `~const ?Bound` will cause an error during AST validation
// anyways, so treat it like `?Bound` as compilation proceeds.
TraitBoundModifiers {
polarity: BoundPolarity::Positive | BoundPolarity::Negative(_),
constness,
},
) => Some(this.lower_poly_trait_ref(ty, itctx, (*constness).into())),
// We can safely ignore constness here, since AST validation
// will take care of invalid modifier combinations.
GenericBound::Trait(
_,
TraitBoundModifier::Maybe
| TraitBoundModifier::MaybeConstMaybe
| TraitBoundModifier::MaybeConstNegative,
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
) => None,
GenericBound::Outlives(lifetime) => {
if lifetime_bound.is_none() {
@ -2032,9 +2029,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
itctx: &ImplTraitContext,
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
self.lower_trait_bound_modifier(*modifier),
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()),
self.lower_trait_bound_modifiers(*modifiers),
),
GenericBound::Outlives(lifetime) => {
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
@ -2320,25 +2317,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
match f {
TraitBoundModifier::None => hir::TraitBoundModifier::None,
TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst,
TraitBoundModifier::Negative => {
fn lower_trait_bound_modifiers(
&mut self,
modifiers: TraitBoundModifiers,
) -> hir::TraitBoundModifier {
match (modifiers.constness, modifiers.polarity) {
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
(BoundConstness::Never, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
if self.tcx.features().negative_bounds {
hir::TraitBoundModifier::Negative
} else {
hir::TraitBoundModifier::None
}
}
// `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
// placeholder for compilation to proceed.
TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
hir::TraitBoundModifier::Maybe
(BoundConstness::Maybe(_), BoundPolarity::Positive) => {
hir::TraitBoundModifier::MaybeConst
}
// Invalid modifier combinations will cause an error during AST validation.
// Arbitrarily pick a placeholder for compilation to proceed.
(BoundConstness::Maybe(_), BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
(BoundConstness::Maybe(_), BoundPolarity::Negative(_)) => {
hir::TraitBoundModifier::MaybeConst
}
TraitBoundModifier::MaybeConstNegative => hir::TraitBoundModifier::MaybeConst,
}
}

View File

@ -152,6 +152,8 @@ ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features
ast_passes_incompatible_trait_bound_modifiers = `{$left}` and `{$right}` are mutually exclusive
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
.because = {$annotation} because of this
.type = inherent impl for this type
@ -195,8 +197,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
.help = use `auto trait Trait {"{}"}` instead
ast_passes_optional_const_exclusive = `~const` and `{$modifier}` are mutually exclusive
ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits

View File

@ -1196,18 +1196,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
if let GenericBound::Trait(poly, modify) = bound {
match (ctxt, modify) {
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
if let GenericBound::Trait(poly, modifiers) = bound {
match (ctxt, modifiers.constness, modifiers.polarity) {
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
self.dcx().emit_err(errors::OptionalTraitSupertrait {
span: poly.span,
path_str: pprust::path_to_string(&poly.trait_ref.path),
});
}
(BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
}
(_, &TraitBoundModifier::MaybeConst(span))
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
if let Some(reason) = &self.disallow_tilde_const =>
{
let reason = match reason {
@ -1235,16 +1235,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
};
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
self.dcx().emit_err(errors::OptionalConstExclusive {
(
_,
BoundConstness::Maybe(_),
BoundPolarity::Maybe(_) | BoundPolarity::Negative(_),
) => {
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
span: bound.span(),
modifier: "?",
});
}
(_, TraitBoundModifier::MaybeConstNegative) => {
self.dcx().emit_err(errors::OptionalConstExclusive {
span: bound.span(),
modifier: "!",
left: modifiers.constness.as_str(),
right: modifiers.polarity.as_str(),
});
}
_ => {}
@ -1252,7 +1251,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
// Negative trait bounds are not allowed to have associated constraints
if let GenericBound::Trait(trait_ref, TraitBoundModifier::Negative) = bound
if let GenericBound::Trait(trait_ref, modifiers) = bound
&& let BoundPolarity::Negative(_) = modifiers.polarity
&& let Some(segment) = trait_ref.trait_ref.path.segments.last()
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
{
@ -1494,7 +1494,8 @@ fn deny_equality_constraints(
for param in &generics.params {
if param.ident == potential_param.ident {
for bound in &param.bounds {
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
if let ast::GenericBound::Trait(trait_ref, TraitBoundModifiers::NONE) =
bound
{
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
let assoc = pprust::path_to_string(&ast::Path::from_ident(

View File

@ -580,11 +580,12 @@ pub enum TildeConstReason {
}
#[derive(Diagnostic)]
#[diag(ast_passes_optional_const_exclusive)]
pub struct OptionalConstExclusive {
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
pub struct IncompatibleTraitBoundModifiers {
#[primary_span]
pub span: Span,
pub modifier: &'static str,
pub left: &'static str,
pub right: &'static str,
}
#[derive(Diagnostic)]

View File

@ -4,6 +4,7 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(box_patterns)]
#![feature(let_chains)]
#![recursion_limit = "256"]
mod helpers;

View File

@ -17,7 +17,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
use rustc_ast::util::parser;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
use rustc_ast::{GenericArg, GenericBound, SelfKind, TraitBoundModifier};
use rustc_ast::{GenericArg, GenericBound, SelfKind};
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_span::edition::Edition;
@ -1559,26 +1559,20 @@ impl<'a> State<'a> {
match bound {
GenericBound::Trait(tref, modifier) => {
match modifier {
TraitBoundModifier::None => {}
TraitBoundModifier::Negative => {
self.word("!");
}
TraitBoundModifier::Maybe => {
self.word("?");
}
TraitBoundModifier::MaybeConst(_) => {
self.word_space("~const");
}
TraitBoundModifier::MaybeConstNegative => {
self.word_space("~const");
self.word("!");
}
TraitBoundModifier::MaybeConstMaybe => {
self.word_space("~const");
self.word("?");
match modifier.constness {
ast::BoundConstness::Never => {}
ast::BoundConstness::Maybe(_) => {
self.word_space(modifier.constness.as_str());
}
}
match modifier.polarity {
ast::BoundPolarity::Positive => {}
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
self.word(modifier.polarity.as_str());
}
}
self.print_poly_trait_ref(tref);
}
GenericBound::Outlives(lt) => self.print_lifetime(*lt),

View File

@ -339,13 +339,15 @@ impl<'a> State<'a> {
self.print_ident(item.ident);
self.print_generic_params(&generics.params);
let mut real_bounds = Vec::with_capacity(bounds.len());
for b in bounds.iter() {
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
for bound in bounds.iter() {
if let GenericBound::Trait(ptr, modifiers) = bound
&& let ast::BoundPolarity::Maybe(_) = modifiers.polarity
{
self.space();
self.word_space("for ?");
self.print_trait_ref(&ptr.trait_ref);
} else {
real_bounds.push(b.clone());
real_bounds.push(bound.clone());
}
}
if !real_bounds.is_empty() {

View File

@ -134,10 +134,13 @@ impl<'a> ExtCtxt<'a> {
pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
ast::GenericBound::Trait(
self.poly_trait_ref(path.span, path),
if is_const {
ast::TraitBoundModifier::MaybeConst(DUMMY_SP)
ast::TraitBoundModifiers {
polarity: ast::BoundPolarity::Positive,
constness: if is_const {
ast::BoundConstness::Maybe(DUMMY_SP)
} else {
ast::TraitBoundModifier::None
ast::BoundConstness::Never
},
},
)
}

View File

@ -418,8 +418,7 @@ pub enum GenericArgsParentheses {
ParenSugar,
}
/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
/// A modifier on a trait bound.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum TraitBoundModifier {
None,

View File

@ -841,7 +841,7 @@ impl<'a> Parser<'a> {
{
return Ok((false, seg.ident, seg.args.as_deref().cloned()));
} else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind
&& let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)] =
&& let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE)] =
bounds.as_slice()
&& let [seg] = trait_ref.trait_ref.path.segments.as_slice()
{

View File

@ -13,37 +13,15 @@ use rustc_ast::ptr::P;
use rustc_ast::token::{self, Delimiter, Token, TokenKind};
use rustc_ast::util::case::Case;
use rustc_ast::{
self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam,
Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier,
TraitObjectSyntax, Ty, TyKind,
self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds,
GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
};
use rustc_errors::{Applicability, PResult};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{Span, Symbol};
use thin_vec::{thin_vec, ThinVec};
/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound.
struct BoundModifiers {
/// `?Trait`.
bound_polarity: BoundPolarity,
/// `~const Trait`.
maybe_const: Option<Span>,
}
impl BoundModifiers {
fn to_trait_bound_modifier(&self) -> TraitBoundModifier {
match (self.bound_polarity, self.maybe_const) {
(BoundPolarity::Positive, None) => TraitBoundModifier::None,
(BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative,
(BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe,
(BoundPolarity::Positive, Some(sp)) => TraitBoundModifier::MaybeConst(sp),
(BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative,
(BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe,
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub(super) enum AllowPlus {
Yes,
@ -461,7 +439,7 @@ impl<'a> Parser<'a> {
parse_plus: bool,
) -> PResult<'a, TyKind> {
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifiers::NONE)];
self.parse_remaining_bounds(bounds, parse_plus)
}
@ -800,7 +778,7 @@ impl<'a> Parser<'a> {
let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
let inner_lo = self.token.span;
let modifiers = self.parse_ty_bound_modifiers()?;
let modifiers = self.parse_trait_bound_modifiers()?;
let bound = if self.token.is_lifetime() {
self.error_lt_bound_with_modifiers(modifiers);
self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
@ -831,18 +809,21 @@ impl<'a> Parser<'a> {
}
/// Emits an error if any trait bound modifiers were present.
fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
if let Some(span) = modifiers.maybe_const {
fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) {
match modifiers.constness {
BoundConstness::Never => {}
BoundConstness::Maybe(span) => {
self.sess.emit_err(errors::TildeConstLifetime { span });
}
match modifiers.bound_polarity {
BoundPolarity::Positive => {}
BoundPolarity::Negative(span) => {
self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" });
}
BoundPolarity::Maybe(span) => {
self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" });
match modifiers.polarity {
BoundPolarity::Positive => {}
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
self.sess.emit_err(errors::ModifierLifetime {
span,
sigil: modifiers.polarity.as_str(),
});
}
}
}
@ -867,26 +848,26 @@ impl<'a> Parser<'a> {
/// If no modifiers are present, this does not consume any tokens.
///
/// ```ebnf
/// TY_BOUND_MODIFIERS = ["~const"] ["?"]
/// TRAIT_BOUND_MODIFIERS = ["~const"] ["?" | "!"]
/// ```
fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
let maybe_const = if self.eat(&token::Tilde) {
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
let constness = if self.eat(&token::Tilde) {
let tilde = self.prev_token.span;
self.expect_keyword(kw::Const)?;
let span = tilde.to(self.prev_token.span);
self.sess.gated_spans.gate(sym::const_trait_impl, span);
Some(span)
BoundConstness::Maybe(span)
} else if self.eat_keyword(kw::Const) {
let span = self.prev_token.span;
self.sess.gated_spans.gate(sym::const_trait_impl, span);
self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
Some(span)
BoundConstness::Maybe(span)
} else {
None
BoundConstness::Never
};
let bound_polarity = if self.eat(&token::Question) {
let polarity = if self.eat(&token::Question) {
BoundPolarity::Maybe(self.prev_token.span)
} else if self.eat(&token::Not) {
self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
@ -895,13 +876,13 @@ impl<'a> Parser<'a> {
BoundPolarity::Positive
};
Ok(BoundModifiers { bound_polarity, maybe_const })
Ok(TraitBoundModifiers { constness, polarity })
}
/// Parses a type bound according to:
/// ```ebnf
/// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
/// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
/// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH
/// ```
///
/// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
@ -909,7 +890,7 @@ impl<'a> Parser<'a> {
&mut self,
lo: Span,
has_parens: bool,
modifiers: BoundModifiers,
modifiers: TraitBoundModifiers,
leading_token: &Token,
) -> PResult<'a, GenericBound> {
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
@ -991,9 +972,8 @@ impl<'a> Parser<'a> {
}
}
let modifier = modifiers.to_trait_bound_modifier();
let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span));
Ok(GenericBound::Trait(poly_trait, modifier))
Ok(GenericBound::Trait(poly_trait, modifiers))
}
// recovers a `Fn(..)` parenthesized-style path from `fn(..)`

View File

@ -520,7 +520,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
continue;
};
for bound in bounds {
let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None) = bound
let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE) = bound
else {
continue;
};
@ -1242,7 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
if let (
[ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifier::None)],
[ast::GenericBound::Trait(poly_trait_ref, ast::TraitBoundModifiers::NONE)],
) = (&type_param_path.segments[..], &bounds[..])
{
if let [ast::PathSegment { ident, args: None, .. }] =
@ -3276,7 +3276,7 @@ fn mk_where_bound_predicate(
},
span: DUMMY_SP,
},
ast::TraitBoundModifier::None,
ast::TraitBoundModifiers::NONE,
)],
};

View File

@ -537,28 +537,19 @@ impl Rewrite for ast::Lifetime {
impl Rewrite for ast::GenericBound {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match *self {
ast::GenericBound::Trait(ref poly_trait_ref, trait_bound_modifier) => {
ast::GenericBound::Trait(ref poly_trait_ref, modifiers) => {
let snippet = context.snippet(self.span());
let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
let rewrite = match trait_bound_modifier {
ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape),
ast::TraitBoundModifier::Maybe => poly_trait_ref
.rewrite(context, shape.offset_left(1)?)
.map(|s| format!("?{}", s)),
ast::TraitBoundModifier::MaybeConst(_) => poly_trait_ref
.rewrite(context, shape.offset_left(7)?)
.map(|s| format!("~const {}", s)),
ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref
.rewrite(context, shape.offset_left(8)?)
.map(|s| format!("~const ?{}", s)),
ast::TraitBoundModifier::Negative => poly_trait_ref
.rewrite(context, shape.offset_left(1)?)
.map(|s| format!("!{}", s)),
ast::TraitBoundModifier::MaybeConstNegative => poly_trait_ref
.rewrite(context, shape.offset_left(8)?)
.map(|s| format!("~const !{}", s)),
};
rewrite.map(|s| if has_paren { format!("({})", s) } else { s })
let mut constness = modifiers.constness.as_str().to_string();
if !constness.is_empty() {
constness.push(' ');
}
let polarity = modifiers.polarity.as_str();
let shape = shape.offset_left(constness.len() + polarity.len())?;
poly_trait_ref
.rewrite(context, shape)
.map(|s| format!("{constness}{polarity}{s}"))
.map(|s| if has_paren { format!("({})", s) } else { s })
}
ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape),
}

View File

@ -15,20 +15,20 @@ ast-stats-1 Arm 96 ( 1.5%) 2 48
ast-stats-1 ForeignItem 96 ( 1.5%) 1 96
ast-stats-1 - Fn 96 ( 1.5%) 1
ast-stats-1 FnDecl 120 ( 1.8%) 5 24
ast-stats-1 FieldDef 160 ( 2.5%) 2 80
ast-stats-1 Stmt 160 ( 2.5%) 5 32
ast-stats-1 FieldDef 160 ( 2.4%) 2 80
ast-stats-1 Stmt 160 ( 2.4%) 5 32
ast-stats-1 - Local 32 ( 0.5%) 1
ast-stats-1 - MacCall 32 ( 0.5%) 1
ast-stats-1 - Expr 96 ( 1.5%) 3
ast-stats-1 Param 160 ( 2.5%) 4 40
ast-stats-1 Param 160 ( 2.4%) 4 40
ast-stats-1 Block 192 ( 2.9%) 6 32
ast-stats-1 Variant 208 ( 3.2%) 2 104
ast-stats-1 GenericBound 256 ( 3.9%) 4 64
ast-stats-1 - Trait 256 ( 3.9%) 4
ast-stats-1 GenericBound 288 ( 4.4%) 4 72
ast-stats-1 - Trait 288 ( 4.4%) 4
ast-stats-1 AssocItem 352 ( 5.4%) 4 88
ast-stats-1 - Type 176 ( 2.7%) 2
ast-stats-1 - Fn 176 ( 2.7%) 2
ast-stats-1 GenericParam 480 ( 7.4%) 5 96
ast-stats-1 GenericParam 480 ( 7.3%) 5 96
ast-stats-1 Pat 504 ( 7.7%) 7 72
ast-stats-1 - Struct 72 ( 1.1%) 1
ast-stats-1 - Wild 72 ( 1.1%) 1
@ -45,15 +45,15 @@ ast-stats-1 - Ptr 64 ( 1.0%) 1
ast-stats-1 - Ref 64 ( 1.0%) 1
ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2
ast-stats-1 - Path 640 ( 9.8%) 10
ast-stats-1 Item 1_224 (18.8%) 9 136
ast-stats-1 Item 1_224 (18.7%) 9 136
ast-stats-1 - Trait 136 ( 2.1%) 1
ast-stats-1 - Enum 136 ( 2.1%) 1
ast-stats-1 - ForeignMod 136 ( 2.1%) 1
ast-stats-1 - Impl 136 ( 2.1%) 1
ast-stats-1 - Fn 272 ( 4.2%) 2
ast-stats-1 - Use 408 ( 6.3%) 3
ast-stats-1 - Use 408 ( 6.2%) 3
ast-stats-1 ----------------------------------------------------------------
ast-stats-1 Total 6_520
ast-stats-1 Total 6_552
ast-stats-1
ast-stats-2 POST EXPANSION AST STATS
ast-stats-2 Name Accumulated Size Count Item Size
@ -81,16 +81,16 @@ ast-stats-2 - Expr 96 ( 1.3%) 3
ast-stats-2 Param 160 ( 2.2%) 4 40
ast-stats-2 Block 192 ( 2.7%) 6 32
ast-stats-2 Variant 208 ( 2.9%) 2 104
ast-stats-2 GenericBound 256 ( 3.6%) 4 64
ast-stats-2 - Trait 256 ( 3.6%) 4
ast-stats-2 GenericBound 288 ( 4.0%) 4 72
ast-stats-2 - Trait 288 ( 4.0%) 4
ast-stats-2 AssocItem 352 ( 4.9%) 4 88
ast-stats-2 - Type 176 ( 2.5%) 2
ast-stats-2 - Fn 176 ( 2.5%) 2
ast-stats-2 GenericParam 480 ( 6.7%) 5 96
ast-stats-2 Pat 504 ( 7.1%) 7 72
ast-stats-2 Pat 504 ( 7.0%) 7 72
ast-stats-2 - Struct 72 ( 1.0%) 1
ast-stats-2 - Wild 72 ( 1.0%) 1
ast-stats-2 - Ident 360 ( 5.1%) 5
ast-stats-2 - Ident 360 ( 5.0%) 5
ast-stats-2 Expr 648 ( 9.1%) 9 72
ast-stats-2 - Path 72 ( 1.0%) 1
ast-stats-2 - Match 72 ( 1.0%) 1
@ -99,12 +99,12 @@ ast-stats-2 - InlineAsm 72 ( 1.0%) 1
ast-stats-2 - Lit 144 ( 2.0%) 2
ast-stats-2 - Block 216 ( 3.0%) 3
ast-stats-2 PathSegment 792 (11.1%) 33 24
ast-stats-2 Ty 896 (12.6%) 14 64
ast-stats-2 Ty 896 (12.5%) 14 64
ast-stats-2 - Ptr 64 ( 0.9%) 1
ast-stats-2 - Ref 64 ( 0.9%) 1
ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2
ast-stats-2 - Path 640 ( 9.0%) 10
ast-stats-2 Item 1_496 (21.0%) 11 136
ast-stats-2 - Path 640 ( 8.9%) 10
ast-stats-2 Item 1_496 (20.9%) 11 136
ast-stats-2 - Trait 136 ( 1.9%) 1
ast-stats-2 - Enum 136 ( 1.9%) 1
ast-stats-2 - ExternCrate 136 ( 1.9%) 1
@ -113,7 +113,7 @@ ast-stats-2 - Impl 136 ( 1.9%) 1
ast-stats-2 - Fn 272 ( 3.8%) 2
ast-stats-2 - Use 544 ( 7.6%) 4
ast-stats-2 ----------------------------------------------------------------
ast-stats-2 Total 7_120
ast-stats-2 Total 7_152
ast-stats-2
hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size