]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #60630 - nnethercote:use-Symbol-more, r=petrochenkov
authorbors <bors@rust-lang.org>
Mon, 13 May 2019 00:28:38 +0000 (00:28 +0000)
committerbors <bors@rust-lang.org>
Mon, 13 May 2019 00:28:38 +0000 (00:28 +0000)
Use `Symbol` more

A `Symbol` can be equated with a string (e.g. `&str`). This involves a
TLS lookup to get the chars (and a Mutex lock in a parallel compiler)
and then a char-by-char comparison. This functionality is convenient but
avoids one of the main benefits of `Symbol`s, which is fast equality
comparisons.

This PR removes the `Symbol`/string equality operations, forcing a lot
of existing string occurrences to become `Symbol`s. Fortunately, these
are almost all static strings (many are attribute names) and we can add
static `Symbol`s as necessary, and very little extra interning occurs.
The benefits are (a) a slight speedup (possibly greater in a parallel
compiler), and (b) the code is a lot more principled about `Symbol` use.
The main downside is verbosity, particularly with more `use
syntax::symbol::symbols` items.

r? @Zoxc

1  2 
src/librustc_passes/ast_validation.rs
src/libsyntax/parse/parser.rs

index 16935796d4ba71838b26c9b373d32d9e8908c6ac,7adf0af31c66191d151f585a3353e47ed131af22..2bea1db841ae918db916e9e2ba15f6f67255ddf9
@@@ -15,7 -15,7 +15,7 @@@ use rustc_data_structures::fx::FxHashMa
  use syntax::ast::*;
  use syntax::attr;
  use syntax::source_map::Spanned;
- use syntax::symbol::keywords;
+ use syntax::symbol::{keywords, sym};
  use syntax::ptr::P;
  use syntax::visit::{self, Visitor};
  use syntax::{span_err, struct_span_err, walk_list};
@@@ -54,21 -54,21 +54,21 @@@ struct AstValidator<'a> 
      has_proc_macro_decls: bool,
      has_global_allocator: bool,
  
 -    // Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
 -    // Nested `impl Trait` _is_ allowed in associated type position,
 -    // e.g `impl Iterator<Item=impl Debug>`
 +    /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
 +    /// Nested `impl Trait` _is_ allowed in associated type position,
 +    /// e.g `impl Iterator<Item=impl Debug>`
      outer_impl_trait: Option<OuterImplTrait>,
  
 -    // Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
 -    // or `Foo::Bar<impl Trait>`
 +    /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
 +    /// or `Foo::Bar<impl Trait>`
      is_impl_trait_banned: bool,
  
 -    // rust-lang/rust#57979: the ban of nested `impl Trait` was buggy
 -    // until PRs #57730 and #57981 landed: it would jump directly to
 -    // walk_ty rather than visit_ty (or skip recurring entirely for
 -    // impl trait in projections), and thus miss some cases. We track
 -    // whether we should downgrade to a warning for short-term via
 -    // these booleans.
 +    /// rust-lang/rust#57979: the ban of nested `impl Trait` was buggy
 +    /// until PRs #57730 and #57981 landed: it would jump directly to
 +    /// walk_ty rather than visit_ty (or skip recurring entirely for
 +    /// impl trait in projections), and thus miss some cases. We track
 +    /// whether we should downgrade to a warning for short-term via
 +    /// these booleans.
      warning_period_57979_didnt_record_next_impl_trait: bool,
      warning_period_57979_impl_trait_in_proj: bool,
  }
@@@ -565,7 -565,7 +565,7 @@@ impl<'a> Visitor<'a> for AstValidator<'
              self.has_proc_macro_decls = true;
          }
  
-         if attr::contains_name(&item.attrs, "global_allocator") {
+         if attr::contains_name(&item.attrs, sym::global_allocator) {
              self.has_global_allocator = true;
          }
  
              }
              ItemKind::Mod(_) => {
                  // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
-                 attr::first_attr_value_str_by_name(&item.attrs, "path");
-                 if attr::contains_name(&item.attrs, "warn_directory_ownership") {
+                 attr::first_attr_value_str_by_name(&item.attrs, sym::path);
+                 if attr::contains_name(&item.attrs, sym::warn_directory_ownership) {
                      let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
                      let msg = "cannot declare a new module at this location";
                      self.session.buffer_lint(lint, item.id, item.span, msg);
index 559cc522810de579a358af4e779d41b5e713f032,c0f3c358e98f5101d976cfcdd74469441248e8e2..2d6c8c540758322cd83924e180f78f59e99cc408
@@@ -46,7 -46,7 +46,7 @@@ use crate::ptr::P
  use crate::parse::PResult;
  use crate::ThinVec;
  use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
- use crate::symbol::{keywords, Symbol};
+ use crate::symbol::{keywords, sym, Symbol};
  
  use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
  use rustc_target::spec::abi::{self, Abi};
@@@ -1833,7 -1833,7 +1833,7 @@@ impl<'a> Parser<'a> 
          Ok(MutTy { ty: t, mutbl: mutbl })
      }
  
 -    fn is_named_argument(&mut self) -> bool {
 +    fn is_named_argument(&self) -> bool {
          let offset = match self.token {
              token::Interpolated(ref nt) => match **nt {
                  token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
      /// This version of parse arg doesn't necessarily require identifier names.
      fn parse_arg_general(&mut self, require_name: bool, is_trait_item: bool,
                           allow_c_variadic: bool) -> PResult<'a, Arg> {
 -        maybe_whole!(self, NtArg, |x| x);
 -
          if let Ok(Some(_)) = self.parse_self_arg() {
              let mut err = self.struct_span_err(self.prev_span,
                  "unexpected `self` argument in function");
          })
      }
  
 -    fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
 +    fn mk_expr(&self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> {
          P(Expr { node, span, attrs, id: ast::DUMMY_NODE_ID })
      }
  
 -    fn mk_unary(&mut self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind {
 +    fn mk_unary(&self, unop: ast::UnOp, expr: P<Expr>) -> ast::ExprKind {
          ExprKind::Unary(unop, expr)
      }
  
 -    fn mk_binary(&mut self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
 +    fn mk_binary(&self, binop: ast::BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
          ExprKind::Binary(binop, lhs, rhs)
      }
  
 -    fn mk_call(&mut self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind {
 +    fn mk_call(&self, f: P<Expr>, args: Vec<P<Expr>>) -> ast::ExprKind {
          ExprKind::Call(f, args)
      }
  
 -    fn mk_index(&mut self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
 +    fn mk_index(&self, expr: P<Expr>, idx: P<Expr>) -> ast::ExprKind {
          ExprKind::Index(expr, idx)
      }
  
 -    fn mk_range(&mut self,
 +    fn mk_range(&self,
                      start: Option<P<Expr>>,
                      end: Option<P<Expr>>,
                      limits: RangeLimits)
          }
      }
  
 -    fn mk_assign_op(&mut self, binop: ast::BinOp,
 +    fn mk_assign_op(&self, binop: ast::BinOp,
                          lhs: P<Expr>, rhs: P<Expr>) -> ast::ExprKind {
          ExprKind::AssignOp(binop, lhs, rhs)
      }
                      hi = path.span;
                      return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs));
                  }
 -                if self.span.rust_2018() && self.check_keyword(keywords::Async)
 -                {
 -                    if self.is_async_block() { // check for `async {` and `async move {`
 -                        return self.parse_async_block(attrs);
 +                if self.span.rust_2018() && self.check_keyword(keywords::Async) {
 +                    return if self.is_async_block() { // check for `async {` and `async move {`
 +                        self.parse_async_block(attrs)
                      } else {
 -                        return self.parse_lambda_expr(attrs);
 -                    }
 +                        self.parse_lambda_expr(attrs)
 +                    };
                  }
                  if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) {
                      return self.parse_lambda_expr(attrs);
              } else {
                  self.restrictions
              };
 -            if op.precedence() < min_prec {
 +            let prec = op.precedence();
 +            if prec < min_prec {
                  break;
              }
              // Check for deprecated `...` syntax
                  // We have 2 alternatives here: `x..y`/`x..=y` and `x..`/`x..=` The other
                  // two variants are handled with `parse_prefix_range_expr` call above.
                  let rhs = if self.is_at_start_of_range_notation_rhs() {
 -                    Some(self.parse_assoc_expr_with(op.precedence() + 1,
 -                                                    LhsExpr::NotYetParsed)?)
 +                    Some(self.parse_assoc_expr_with(prec + 1, LhsExpr::NotYetParsed)?)
                  } else {
                      None
                  };
                  break
              }
  
 -            let rhs = match op.fixity() {
 -                Fixity::Right => self.with_res(
 -                    restrictions - Restrictions::STMT_EXPR,
 -                    |this| {
 -                        this.parse_assoc_expr_with(op.precedence(),
 -                            LhsExpr::NotYetParsed)
 -                }),
 -                Fixity::Left => self.with_res(
 -                    restrictions - Restrictions::STMT_EXPR,
 -                    |this| {
 -                        this.parse_assoc_expr_with(op.precedence() + 1,
 -                            LhsExpr::NotYetParsed)
 -                }),
 +            let fixity = op.fixity();
 +            let prec_adjustment = match fixity {
 +                Fixity::Right => 0,
 +                Fixity::Left => 1,
                  // We currently have no non-associative operators that are not handled above by
                  // the special cases. The code is here only for future convenience.
 -                Fixity::None => self.with_res(
 -                    restrictions - Restrictions::STMT_EXPR,
 -                    |this| {
 -                        this.parse_assoc_expr_with(op.precedence() + 1,
 -                            LhsExpr::NotYetParsed)
 -                }),
 -            }?;
 +                Fixity::None => 1,
 +            };
 +            let rhs = self.with_res(
 +                restrictions - Restrictions::STMT_EXPR,
 +                |this| this.parse_assoc_expr_with(prec + prec_adjustment, LhsExpr::NotYetParsed)
 +            )?;
  
              // Make sure that the span of the parent node is larger than the span of lhs and rhs,
              // including the attributes.
                  }
              };
  
 -            if op.fixity() == Fixity::None { break }
 +            if let Fixity::None = fixity { break }
          }
          Ok(lhs)
      }
      /// Produce an error if comparison operators are chained (RFC #558).
      /// We only need to check lhs, not rhs, because all comparison ops
      /// have same precedence and are left-associative
 -    fn check_no_chained_comparison(&mut self, lhs: &Expr, outer_op: &AssocOp) {
 +    fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) {
          debug_assert!(outer_op.is_comparison(),
                        "check_no_chained_comparison: {:?} is not comparison",
                        outer_op);
      }
  
      crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
 -        maybe_whole!(self, NtArm, |x| x);
 -
          let attrs = self.parse_outer_attributes()?;
          let pats = self.parse_pats()?;
          let guard = if self.eat_keyword(keywords::If) {
          })
      }
  
 -    fn is_async_block(&mut self) -> bool {
 +    fn is_async_block(&self) -> bool {
          self.token.is_keyword(keywords::Async) &&
          (
              ( // `async move {`
          )
      }
  
 -    fn is_async_fn(&mut self) -> bool {
 +    fn is_async_fn(&self) -> bool {
          self.token.is_keyword(keywords::Async) &&
              self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
      }
  
 -    fn is_do_catch_block(&mut self) -> bool {
 +    fn is_do_catch_block(&self) -> bool {
          self.token.is_keyword(keywords::Do) &&
          self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
          self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
          !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
      }
  
 -    fn is_try_block(&mut self) -> bool {
 +    fn is_try_block(&self) -> bool {
          self.token.is_keyword(keywords::Try) &&
          self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) &&
          self.span.rust_2018() &&
          self.look_ahead(1, |t| t.is_keyword(keywords::Type))
      }
  
 -    fn is_auto_trait_item(&mut self) -> bool {
 +    fn is_auto_trait_item(&self) -> bool {
          // auto trait
          (self.token.is_keyword(keywords::Auto)
              && self.look_ahead(1, |t| t.is_keyword(keywords::Trait)))
  
                  (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
              }
-             token::Ident(ident, _) if ident.name == "macro_rules" &&
+             token::Ident(ident, _) if ident.name == sym::macro_rules &&
                                     self.look_ahead(1, |t| *t == token::Not) => {
                  let prev_span = self.prev_span;
                  self.complain_if_pub_macro(&vis.node, prev_span);
      }
  
      /// Checks if this expression is a successfully parsed statement.
 -    fn expr_is_complete(&mut self, e: &Expr) -> bool {
 +    fn expr_is_complete(&self, e: &Expr) -> bool {
          self.restrictions.contains(Restrictions::STMT_EXPR) &&
              !classify::expr_requires_semi_to_be_stmt(e)
      }
      ///                  | ( < lifetimes , typaramseq ( , )? > )
      /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
      fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
 -        maybe_whole!(self, NtGenerics, |x| x);
 -
          let span_lo = self.span;
          if self.eat_lt() {
              let params = self.parse_generic_params()?;
      /// where T : Trait<U, V> + 'b, 'a : 'b
      /// ```
      fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
 -        maybe_whole!(self, NtWhereClause, |x| x);
 -
          let mut where_clause = WhereClause {
              id: ast::DUMMY_NODE_ID,
              predicates: Vec::new(),
          Ok((id, generics))
      }
  
 -    fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
 +    fn mk_item(&self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
                 attrs: Vec<Attribute>) -> P<Item> {
          P(Item {
              ident,
  
      /// Returns `true` if we are looking at `const ID`
      /// (returns `false` for things like `const fn`, etc.).
 -    fn is_const_item(&mut self) -> bool {
 +    fn is_const_item(&self) -> bool {
          self.token.is_keyword(keywords::Const) &&
              !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) &&
              !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe))
          })
      }
  
 -    fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, sp: Span) {
 +    fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) {
          match *vis {
              VisibilityKind::Inherited => {}
              _ => {
          }
      }
  
 -    fn missing_assoc_item_kind_err(&mut self, item_type: &str, prev_span: Span)
 +    fn missing_assoc_item_kind_err(&self, item_type: &str, prev_span: Span)
                                     -> DiagnosticBuilder<'a>
      {
          let expected_kinds = if item_type == "extern" {
      }
  
      fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
-         if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
+         if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) {
              self.directory.path.to_mut().push(&path.as_str());
              self.directory.ownership = DirectoryOwnership::Owned { relative: None };
          } else {
      }
  
      pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
-         if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") {
+         if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) {
              let s = s.as_str();
  
              // On windows, the base path might have the form