Refactor AST trait bound modifiers
This commit is contained in:
parent
bf9229a2e3
commit
5e4f12b41a
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ¶m.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(
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
} else {
|
||||
ast::TraitBoundModifier::None
|
||||
ast::TraitBoundModifiers {
|
||||
polarity: ast::BoundPolarity::Positive,
|
||||
constness: if is_const {
|
||||
ast::BoundConstness::Maybe(DUMMY_SP)
|
||||
} else {
|
||||
ast::BoundConstness::Never
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 {
|
||||
self.sess.emit_err(errors::TildeConstLifetime { span });
|
||||
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 {
|
||||
match modifiers.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: "?" });
|
||||
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(..)`
|
||||
|
@ -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,
|
||||
)],
|
||||
};
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user