Auto merge of #119163 - fmease:refactor-ast-trait-bound-modifiers, r=compiler-errors
Refactor AST trait bound modifiers Instead of having two types to represent trait bound modifiers in the parser / the AST (`parser::ty::BoundModifiers` & `ast::TraitBoundModifier`), only to map one to the other later, just use `parser::ty::BoundModifiers` (moved & renamed to `ast::TraitBoundModifiers`). The struct type is more extensible and easier to deal with (see [here](https://github.com/rust-lang/rust/pull/119099/files#r1430749981) and [here](https://github.com/rust-lang/rust/pull/119099/files#r1430752116) for context) since it more closely models what it represents: A compound of two kinds of modifiers, constness and polarity. Modeling this as an enum (the now removed `ast::TraitBoundModifier`) meant one had to add a new variant per *combination* of modifier kind, which simply isn't scalable and which lead to a lot of explicit non-DRY matches. NB: `hir::TraitBoundModifier` being an enum is fine since HIR doesn't need to worry representing invalid modifier kind combinations as those get rejected during AST validation thereby immensely cutting down the number of possibilities.
This commit is contained in:
commit
aaef5fe497
16 changed files with 195 additions and 201 deletions
|
@ -286,41 +286,16 @@ impl ParenthesizedArgs {
|
||||||
|
|
||||||
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
|
pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
|
||||||
|
|
||||||
/// A modifier on a bound, e.g., `?Trait` or `~const Trait`.
|
/// Modifiers on a trait bound like `~const`, `?` and `!`.
|
||||||
///
|
|
||||||
/// Negative bounds should also be handled here.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
|
||||||
pub enum TraitBoundModifier {
|
pub struct TraitBoundModifiers {
|
||||||
/// No modifiers
|
pub constness: BoundConstness,
|
||||||
None,
|
pub polarity: BoundPolarity,
|
||||||
|
|
||||||
/// `!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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TraitBoundModifier {
|
impl TraitBoundModifiers {
|
||||||
pub fn to_constness(self) -> Const {
|
pub const NONE: Self =
|
||||||
match self {
|
Self { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
|
||||||
Self::MaybeConst(span) => Const::Yes(span),
|
|
||||||
_ => Const::No,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The AST represents all type param bounds as types.
|
/// The AST represents all type param bounds as types.
|
||||||
|
@ -329,7 +304,7 @@ impl TraitBoundModifier {
|
||||||
/// detects `Copy`, `Send` and `Sync`.
|
/// detects `Copy`, `Send` and `Sync`.
|
||||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum GenericBound {
|
pub enum GenericBound {
|
||||||
Trait(PolyTraitRef, TraitBoundModifier),
|
Trait(PolyTraitRef, TraitBoundModifiers),
|
||||||
Outlives(Lifetime),
|
Outlives(Lifetime),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1193,7 +1168,7 @@ impl Expr {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
ExprKind::Path(None, path) => Some(GenericBound::Trait(
|
||||||
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
|
PolyTraitRef::new(ThinVec::new(), path.clone(), self.span),
|
||||||
TraitBoundModifier::None,
|
TraitBoundModifiers::NONE,
|
||||||
)),
|
)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -2491,6 +2466,15 @@ pub enum Const {
|
||||||
No,
|
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.
|
/// Item defaultness.
|
||||||
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
|
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
|
||||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
#[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 {
|
pub enum BoundPolarity {
|
||||||
/// `Type: Trait`
|
/// `Type: Trait`
|
||||||
Positive,
|
Positive,
|
||||||
|
@ -2526,6 +2512,35 @@ pub enum BoundPolarity {
|
||||||
Maybe(Span),
|
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)]
|
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||||
pub enum FnRetTy {
|
pub enum FnRetTy {
|
||||||
/// Returns type is not specified.
|
/// Returns type is not specified.
|
||||||
|
@ -3259,7 +3274,7 @@ mod size_asserts {
|
||||||
static_assert_size!(ForeignItem, 96);
|
static_assert_size!(ForeignItem, 96);
|
||||||
static_assert_size!(ForeignItemKind, 24);
|
static_assert_size!(ForeignItemKind, 24);
|
||||||
static_assert_size!(GenericArg, 24);
|
static_assert_size!(GenericArg, 24);
|
||||||
static_assert_size!(GenericBound, 64);
|
static_assert_size!(GenericBound, 72);
|
||||||
static_assert_size!(Generics, 40);
|
static_assert_size!(Generics, 40);
|
||||||
static_assert_size!(Impl, 136);
|
static_assert_size!(Impl, 136);
|
||||||
static_assert_size!(Item, 136);
|
static_assert_size!(Item, 136);
|
||||||
|
|
|
@ -1372,7 +1372,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// need to compute this at all unless there is a Maybe bound.
|
// need to compute this at all unless there is a Maybe bound.
|
||||||
let mut is_param: Option<bool> = None;
|
let mut is_param: Option<bool> = None;
|
||||||
for bound in &bound_pred.bounds {
|
for bound in &bound_pred.bounds {
|
||||||
if !matches!(*bound, GenericBound::Trait(_, TraitBoundModifier::Maybe)) {
|
if !matches!(
|
||||||
|
*bound,
|
||||||
|
GenericBound::Trait(
|
||||||
|
_,
|
||||||
|
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }
|
||||||
|
)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
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 {
|
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
||||||
GenericBound::Trait(
|
GenericBound::Trait(
|
||||||
ty,
|
ty,
|
||||||
modifier @ (TraitBoundModifier::None
|
TraitBoundModifiers {
|
||||||
| TraitBoundModifier::MaybeConst(_)
|
polarity: BoundPolarity::Positive | BoundPolarity::Negative(_),
|
||||||
| TraitBoundModifier::Negative),
|
constness,
|
||||||
) => {
|
},
|
||||||
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
|
) => Some(this.lower_poly_trait_ref(ty, itctx, (*constness).into())),
|
||||||
}
|
// We can safely ignore constness here, since AST validation
|
||||||
// `~const ?Bound` will cause an error during AST validation
|
// will take care of invalid modifier combinations.
|
||||||
// anyways, so treat it like `?Bound` as compilation proceeds.
|
|
||||||
GenericBound::Trait(
|
GenericBound::Trait(
|
||||||
_,
|
_,
|
||||||
TraitBoundModifier::Maybe
|
TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. },
|
||||||
| TraitBoundModifier::MaybeConstMaybe
|
|
||||||
| TraitBoundModifier::MaybeConstNegative,
|
|
||||||
) => None,
|
) => None,
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
if lifetime_bound.is_none() {
|
if lifetime_bound.is_none() {
|
||||||
|
@ -2028,9 +2025,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
) -> hir::GenericBound<'hir> {
|
) -> hir::GenericBound<'hir> {
|
||||||
match tpb {
|
match tpb {
|
||||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
|
||||||
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
|
self.lower_poly_trait_ref(p, itctx, modifiers.constness.into()),
|
||||||
self.lower_trait_bound_modifier(*modifier),
|
self.lower_trait_bound_modifiers(*modifiers),
|
||||||
),
|
),
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
hir::GenericBound::Outlives(self.lower_lifetime(lifetime))
|
||||||
|
@ -2316,25 +2313,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier {
|
fn lower_trait_bound_modifiers(
|
||||||
match f {
|
&mut self,
|
||||||
TraitBoundModifier::None => hir::TraitBoundModifier::None,
|
modifiers: TraitBoundModifiers,
|
||||||
TraitBoundModifier::MaybeConst(_) => hir::TraitBoundModifier::MaybeConst,
|
) -> hir::TraitBoundModifier {
|
||||||
|
match (modifiers.constness, modifiers.polarity) {
|
||||||
TraitBoundModifier::Negative => {
|
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
|
||||||
|
(BoundConstness::Never, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||||
|
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
|
||||||
if self.tcx.features().negative_bounds {
|
if self.tcx.features().negative_bounds {
|
||||||
hir::TraitBoundModifier::Negative
|
hir::TraitBoundModifier::Negative
|
||||||
} else {
|
} else {
|
||||||
hir::TraitBoundModifier::None
|
hir::TraitBoundModifier::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(BoundConstness::Maybe(_), BoundPolarity::Positive) => {
|
||||||
// `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a
|
hir::TraitBoundModifier::MaybeConst
|
||||||
// placeholder for compilation to proceed.
|
}
|
||||||
TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => {
|
// Invalid modifier combinations will cause an error during AST validation.
|
||||||
hir::TraitBoundModifier::Maybe
|
// 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
|
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
|
||||||
.help = remove one of these features
|
.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}
|
ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation}
|
||||||
.because = {$annotation} because of this
|
.because = {$annotation} because of this
|
||||||
.type = inherent impl for this type
|
.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
|
ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax
|
||||||
.help = use `auto trait Trait {"{}"}` instead
|
.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_object = `?Trait` is not permitted in trait object types
|
||||||
|
|
||||||
ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits
|
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) {
|
fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
||||||
if let GenericBound::Trait(poly, modify) = bound {
|
if let GenericBound::Trait(poly, modifiers) = bound {
|
||||||
match (ctxt, modify) {
|
match (ctxt, modifiers.constness, modifiers.polarity) {
|
||||||
(BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
|
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||||
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
self.dcx().emit_err(errors::OptionalTraitSupertrait {
|
||||||
span: poly.span,
|
span: poly.span,
|
||||||
path_str: pprust::path_to_string(&poly.trait_ref.path),
|
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 });
|
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 =>
|
if let Some(reason) = &self.disallow_tilde_const =>
|
||||||
{
|
{
|
||||||
let reason = match reason {
|
let reason = match reason {
|
||||||
|
@ -1235,16 +1235,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
};
|
};
|
||||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
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(),
|
span: bound.span(),
|
||||||
modifier: "?",
|
left: modifiers.constness.as_str(),
|
||||||
});
|
right: modifiers.polarity.as_str(),
|
||||||
}
|
|
||||||
(_, TraitBoundModifier::MaybeConstNegative) => {
|
|
||||||
self.dcx().emit_err(errors::OptionalConstExclusive {
|
|
||||||
span: bound.span(),
|
|
||||||
modifier: "!",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1252,7 +1251,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Negative trait bounds are not allowed to have associated constraints
|
// 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(segment) = trait_ref.trait_ref.path.segments.last()
|
||||||
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
|
&& let Some(ast::GenericArgs::AngleBracketed(args)) = segment.args.as_deref()
|
||||||
{
|
{
|
||||||
|
@ -1494,7 +1494,8 @@ fn deny_equality_constraints(
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if param.ident == potential_param.ident {
|
if param.ident == potential_param.ident {
|
||||||
for bound in ¶m.bounds {
|
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[..] {
|
if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
|
||||||
let assoc = pprust::path_to_string(&ast::Path::from_ident(
|
let assoc = pprust::path_to_string(&ast::Path::from_ident(
|
||||||
|
|
|
@ -580,11 +580,12 @@ pub enum TildeConstReason {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_optional_const_exclusive)]
|
#[diag(ast_passes_incompatible_trait_bound_modifiers)]
|
||||||
pub struct OptionalConstExclusive {
|
pub struct IncompatibleTraitBoundModifiers {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub modifier: &'static str,
|
pub left: &'static str,
|
||||||
|
pub right: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(let_chains)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
|
@ -17,7 +17,7 @@ use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
|
||||||
use rustc_ast::util::parser;
|
use rustc_ast::util::parser;
|
||||||
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
|
||||||
use rustc_ast::{attr, BindingAnnotation, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
|
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::{InlineAsmOperand, InlineAsmRegOrRegClass};
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
|
@ -1559,26 +1559,20 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
match bound {
|
match bound {
|
||||||
GenericBound::Trait(tref, modifier) => {
|
GenericBound::Trait(tref, modifier) => {
|
||||||
match modifier {
|
match modifier.constness {
|
||||||
TraitBoundModifier::None => {}
|
ast::BoundConstness::Never => {}
|
||||||
TraitBoundModifier::Negative => {
|
ast::BoundConstness::Maybe(_) => {
|
||||||
self.word("!");
|
self.word_space(modifier.constness.as_str());
|
||||||
}
|
|
||||||
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.polarity {
|
||||||
|
ast::BoundPolarity::Positive => {}
|
||||||
|
ast::BoundPolarity::Negative(_) | ast::BoundPolarity::Maybe(_) => {
|
||||||
|
self.word(modifier.polarity.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.print_poly_trait_ref(tref);
|
self.print_poly_trait_ref(tref);
|
||||||
}
|
}
|
||||||
GenericBound::Outlives(lt) => self.print_lifetime(*lt),
|
GenericBound::Outlives(lt) => self.print_lifetime(*lt),
|
||||||
|
|
|
@ -339,13 +339,15 @@ impl<'a> State<'a> {
|
||||||
self.print_ident(item.ident);
|
self.print_ident(item.ident);
|
||||||
self.print_generic_params(&generics.params);
|
self.print_generic_params(&generics.params);
|
||||||
let mut real_bounds = Vec::with_capacity(bounds.len());
|
let mut real_bounds = Vec::with_capacity(bounds.len());
|
||||||
for b in bounds.iter() {
|
for bound in bounds.iter() {
|
||||||
if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
|
if let GenericBound::Trait(ptr, modifiers) = bound
|
||||||
|
&& let ast::BoundPolarity::Maybe(_) = modifiers.polarity
|
||||||
|
{
|
||||||
self.space();
|
self.space();
|
||||||
self.word_space("for ?");
|
self.word_space("for ?");
|
||||||
self.print_trait_ref(&ptr.trait_ref);
|
self.print_trait_ref(&ptr.trait_ref);
|
||||||
} else {
|
} else {
|
||||||
real_bounds.push(b.clone());
|
real_bounds.push(bound.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !real_bounds.is_empty() {
|
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 {
|
pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
|
||||||
ast::GenericBound::Trait(
|
ast::GenericBound::Trait(
|
||||||
self.poly_trait_ref(path.span, path),
|
self.poly_trait_ref(path.span, path),
|
||||||
if is_const {
|
ast::TraitBoundModifiers {
|
||||||
ast::TraitBoundModifier::MaybeConst(DUMMY_SP)
|
polarity: ast::BoundPolarity::Positive,
|
||||||
|
constness: if is_const {
|
||||||
|
ast::BoundConstness::Maybe(DUMMY_SP)
|
||||||
} else {
|
} else {
|
||||||
ast::TraitBoundModifier::None
|
ast::BoundConstness::Never
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -417,8 +417,7 @@ pub enum GenericArgsParentheses {
|
||||||
ParenSugar,
|
ParenSugar,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A modifier on a bound, currently this is only used for `?Sized`, where the
|
/// A modifier on a trait bound.
|
||||||
/// modifier is `Maybe`. Negative bounds should also be handled here.
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||||
pub enum TraitBoundModifier {
|
pub enum TraitBoundModifier {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -840,7 +840,7 @@ impl<'a> Parser<'a> {
|
||||||
{
|
{
|
||||||
return Ok((false, seg.ident, seg.args.as_deref().cloned()));
|
return Ok((false, seg.ident, seg.args.as_deref().cloned()));
|
||||||
} else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind
|
} 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()
|
bounds.as_slice()
|
||||||
&& let [seg] = trait_ref.trait_ref.path.segments.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::token::{self, Delimiter, Token, TokenKind};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam,
|
self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds,
|
||||||
Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier,
|
GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef,
|
||||||
TraitObjectSyntax, Ty, TyKind,
|
TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind,
|
||||||
};
|
};
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
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)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub(super) enum AllowPlus {
|
pub(super) enum AllowPlus {
|
||||||
Yes,
|
Yes,
|
||||||
|
@ -461,7 +439,7 @@ impl<'a> Parser<'a> {
|
||||||
parse_plus: bool,
|
parse_plus: bool,
|
||||||
) -> PResult<'a, TyKind> {
|
) -> PResult<'a, TyKind> {
|
||||||
let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span));
|
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)
|
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 has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
|
||||||
let inner_lo = self.token.span;
|
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() {
|
let bound = if self.token.is_lifetime() {
|
||||||
self.error_lt_bound_with_modifiers(modifiers);
|
self.error_lt_bound_with_modifiers(modifiers);
|
||||||
self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
|
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.
|
/// Emits an error if any trait bound modifiers were present.
|
||||||
fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) {
|
fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) {
|
||||||
if let Some(span) = modifiers.maybe_const {
|
match modifiers.constness {
|
||||||
|
BoundConstness::Never => {}
|
||||||
|
BoundConstness::Maybe(span) => {
|
||||||
self.sess.emit_err(errors::TildeConstLifetime { 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.
|
/// If no modifiers are present, this does not consume any tokens.
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// TY_BOUND_MODIFIERS = ["~const"] ["?"]
|
/// TRAIT_BOUND_MODIFIERS = ["~const"] ["?" | "!"]
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> {
|
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
|
||||||
let maybe_const = if self.eat(&token::Tilde) {
|
let constness = if self.eat(&token::Tilde) {
|
||||||
let tilde = self.prev_token.span;
|
let tilde = self.prev_token.span;
|
||||||
self.expect_keyword(kw::Const)?;
|
self.expect_keyword(kw::Const)?;
|
||||||
let span = tilde.to(self.prev_token.span);
|
let span = tilde.to(self.prev_token.span);
|
||||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
||||||
Some(span)
|
BoundConstness::Maybe(span)
|
||||||
} else if self.eat_keyword(kw::Const) {
|
} else if self.eat_keyword(kw::Const) {
|
||||||
let span = self.prev_token.span;
|
let span = self.prev_token.span;
|
||||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
||||||
self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
|
self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
|
||||||
|
|
||||||
Some(span)
|
BoundConstness::Maybe(span)
|
||||||
} else {
|
} 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)
|
BoundPolarity::Maybe(self.prev_token.span)
|
||||||
} else if self.eat(&token::Not) {
|
} else if self.eat(&token::Not) {
|
||||||
self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
|
self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span);
|
||||||
|
@ -895,13 +876,13 @@ impl<'a> Parser<'a> {
|
||||||
BoundPolarity::Positive
|
BoundPolarity::Positive
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(BoundModifiers { bound_polarity, maybe_const })
|
Ok(TraitBoundModifiers { constness, polarity })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a type bound according to:
|
/// Parses a type bound according to:
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
|
/// 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>`.
|
/// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`.
|
||||||
|
@ -909,7 +890,7 @@ impl<'a> Parser<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
has_parens: bool,
|
has_parens: bool,
|
||||||
modifiers: BoundModifiers,
|
modifiers: TraitBoundModifiers,
|
||||||
leading_token: &Token,
|
leading_token: &Token,
|
||||||
) -> PResult<'a, GenericBound> {
|
) -> PResult<'a, GenericBound> {
|
||||||
let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
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));
|
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(..)`
|
// recovers a `Fn(..)` parenthesized-style path from `fn(..)`
|
||||||
|
|
|
@ -520,7 +520,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
for bound in bounds {
|
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 {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -1242,7 +1242,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||||
}
|
}
|
||||||
if let (
|
if let (
|
||||||
[ast::PathSegment { args: None, .. }],
|
[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[..])
|
) = (&type_param_path.segments[..], &bounds[..])
|
||||||
{
|
{
|
||||||
if let [ast::PathSegment { ident, args: None, .. }] =
|
if let [ast::PathSegment { ident, args: None, .. }] =
|
||||||
|
@ -3276,7 +3276,7 @@ fn mk_where_bound_predicate(
|
||||||
},
|
},
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
},
|
},
|
||||||
ast::TraitBoundModifier::None,
|
ast::TraitBoundModifiers::NONE,
|
||||||
)],
|
)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -537,28 +537,19 @@ impl Rewrite for ast::Lifetime {
|
||||||
impl Rewrite for ast::GenericBound {
|
impl Rewrite for ast::GenericBound {
|
||||||
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
|
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
|
||||||
match *self {
|
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 snippet = context.snippet(self.span());
|
||||||
let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
|
let has_paren = snippet.starts_with('(') && snippet.ends_with(')');
|
||||||
let rewrite = match trait_bound_modifier {
|
let mut constness = modifiers.constness.as_str().to_string();
|
||||||
ast::TraitBoundModifier::None => poly_trait_ref.rewrite(context, shape),
|
if !constness.is_empty() {
|
||||||
ast::TraitBoundModifier::Maybe => poly_trait_ref
|
constness.push(' ');
|
||||||
.rewrite(context, shape.offset_left(1)?)
|
}
|
||||||
.map(|s| format!("?{}", s)),
|
let polarity = modifiers.polarity.as_str();
|
||||||
ast::TraitBoundModifier::MaybeConst(_) => poly_trait_ref
|
let shape = shape.offset_left(constness.len() + polarity.len())?;
|
||||||
.rewrite(context, shape.offset_left(7)?)
|
poly_trait_ref
|
||||||
.map(|s| format!("~const {}", s)),
|
.rewrite(context, shape)
|
||||||
ast::TraitBoundModifier::MaybeConstMaybe => poly_trait_ref
|
.map(|s| format!("{constness}{polarity}{s}"))
|
||||||
.rewrite(context, shape.offset_left(8)?)
|
.map(|s| if has_paren { format!("({})", s) } else { s })
|
||||||
.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 })
|
|
||||||
}
|
}
|
||||||
ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape),
|
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 ForeignItem 96 ( 1.5%) 1 96
|
||||||
ast-stats-1 - Fn 96 ( 1.5%) 1
|
ast-stats-1 - Fn 96 ( 1.5%) 1
|
||||||
ast-stats-1 FnDecl 120 ( 1.8%) 5 24
|
ast-stats-1 FnDecl 120 ( 1.8%) 5 24
|
||||||
ast-stats-1 FieldDef 160 ( 2.5%) 2 80
|
ast-stats-1 FieldDef 160 ( 2.4%) 2 80
|
||||||
ast-stats-1 Stmt 160 ( 2.5%) 5 32
|
ast-stats-1 Stmt 160 ( 2.4%) 5 32
|
||||||
ast-stats-1 - Local 32 ( 0.5%) 1
|
ast-stats-1 - Local 32 ( 0.5%) 1
|
||||||
ast-stats-1 - MacCall 32 ( 0.5%) 1
|
ast-stats-1 - MacCall 32 ( 0.5%) 1
|
||||||
ast-stats-1 - Expr 96 ( 1.5%) 3
|
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 Block 192 ( 2.9%) 6 32
|
||||||
ast-stats-1 Variant 208 ( 3.2%) 2 104
|
ast-stats-1 Variant 208 ( 3.2%) 2 104
|
||||||
ast-stats-1 GenericBound 256 ( 3.9%) 4 64
|
ast-stats-1 GenericBound 288 ( 4.4%) 4 72
|
||||||
ast-stats-1 - Trait 256 ( 3.9%) 4
|
ast-stats-1 - Trait 288 ( 4.4%) 4
|
||||||
ast-stats-1 AssocItem 352 ( 5.4%) 4 88
|
ast-stats-1 AssocItem 352 ( 5.4%) 4 88
|
||||||
ast-stats-1 - Type 176 ( 2.7%) 2
|
ast-stats-1 - Type 176 ( 2.7%) 2
|
||||||
ast-stats-1 - Fn 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 Pat 504 ( 7.7%) 7 72
|
||||||
ast-stats-1 - Struct 72 ( 1.1%) 1
|
ast-stats-1 - Struct 72 ( 1.1%) 1
|
||||||
ast-stats-1 - Wild 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 - Ref 64 ( 1.0%) 1
|
||||||
ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2
|
ast-stats-1 - ImplicitSelf 128 ( 2.0%) 2
|
||||||
ast-stats-1 - Path 640 ( 9.8%) 10
|
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 - Trait 136 ( 2.1%) 1
|
||||||
ast-stats-1 - Enum 136 ( 2.1%) 1
|
ast-stats-1 - Enum 136 ( 2.1%) 1
|
||||||
ast-stats-1 - ForeignMod 136 ( 2.1%) 1
|
ast-stats-1 - ForeignMod 136 ( 2.1%) 1
|
||||||
ast-stats-1 - Impl 136 ( 2.1%) 1
|
ast-stats-1 - Impl 136 ( 2.1%) 1
|
||||||
ast-stats-1 - Fn 272 ( 4.2%) 2
|
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 ----------------------------------------------------------------
|
||||||
ast-stats-1 Total 6_520
|
ast-stats-1 Total 6_552
|
||||||
ast-stats-1
|
ast-stats-1
|
||||||
ast-stats-2 POST EXPANSION AST STATS
|
ast-stats-2 POST EXPANSION AST STATS
|
||||||
ast-stats-2 Name Accumulated Size Count Item Size
|
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 Param 160 ( 2.2%) 4 40
|
||||||
ast-stats-2 Block 192 ( 2.7%) 6 32
|
ast-stats-2 Block 192 ( 2.7%) 6 32
|
||||||
ast-stats-2 Variant 208 ( 2.9%) 2 104
|
ast-stats-2 Variant 208 ( 2.9%) 2 104
|
||||||
ast-stats-2 GenericBound 256 ( 3.6%) 4 64
|
ast-stats-2 GenericBound 288 ( 4.0%) 4 72
|
||||||
ast-stats-2 - Trait 256 ( 3.6%) 4
|
ast-stats-2 - Trait 288 ( 4.0%) 4
|
||||||
ast-stats-2 AssocItem 352 ( 4.9%) 4 88
|
ast-stats-2 AssocItem 352 ( 4.9%) 4 88
|
||||||
ast-stats-2 - Type 176 ( 2.5%) 2
|
ast-stats-2 - Type 176 ( 2.5%) 2
|
||||||
ast-stats-2 - Fn 176 ( 2.5%) 2
|
ast-stats-2 - Fn 176 ( 2.5%) 2
|
||||||
ast-stats-2 GenericParam 480 ( 6.7%) 5 96
|
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 - Struct 72 ( 1.0%) 1
|
||||||
ast-stats-2 - Wild 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 Expr 648 ( 9.1%) 9 72
|
||||||
ast-stats-2 - Path 72 ( 1.0%) 1
|
ast-stats-2 - Path 72 ( 1.0%) 1
|
||||||
ast-stats-2 - Match 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 - Lit 144 ( 2.0%) 2
|
||||||
ast-stats-2 - Block 216 ( 3.0%) 3
|
ast-stats-2 - Block 216 ( 3.0%) 3
|
||||||
ast-stats-2 PathSegment 792 (11.1%) 33 24
|
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 - Ptr 64 ( 0.9%) 1
|
||||||
ast-stats-2 - Ref 64 ( 0.9%) 1
|
ast-stats-2 - Ref 64 ( 0.9%) 1
|
||||||
ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2
|
ast-stats-2 - ImplicitSelf 128 ( 1.8%) 2
|
||||||
ast-stats-2 - Path 640 ( 9.0%) 10
|
ast-stats-2 - Path 640 ( 8.9%) 10
|
||||||
ast-stats-2 Item 1_496 (21.0%) 11 136
|
ast-stats-2 Item 1_496 (20.9%) 11 136
|
||||||
ast-stats-2 - Trait 136 ( 1.9%) 1
|
ast-stats-2 - Trait 136 ( 1.9%) 1
|
||||||
ast-stats-2 - Enum 136 ( 1.9%) 1
|
ast-stats-2 - Enum 136 ( 1.9%) 1
|
||||||
ast-stats-2 - ExternCrate 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 - Fn 272 ( 3.8%) 2
|
||||||
ast-stats-2 - Use 544 ( 7.6%) 4
|
ast-stats-2 - Use 544 ( 7.6%) 4
|
||||||
ast-stats-2 ----------------------------------------------------------------
|
ast-stats-2 ----------------------------------------------------------------
|
||||||
ast-stats-2 Total 7_120
|
ast-stats-2 Total 7_152
|
||||||
ast-stats-2
|
ast-stats-2
|
||||||
hir-stats HIR STATS
|
hir-stats HIR STATS
|
||||||
hir-stats Name Accumulated Size Count Item Size
|
hir-stats Name Accumulated Size Count Item Size
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue