Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2018 edition ? Kleene operator #51587

Merged
merged 7 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# `macro_at_most_once_rep`

The tracking issue for this feature is: TODO(mark-i-m)
NOTE: This feature is only available in the 2018 Edition.

The tracking issue for this feature is: #48075

With this feature gate enabled, one can use `?` as a Kleene operator meaning "0
or 1 repetitions" in a macro definition. Previously only `+` and `*` were allowed.

For example:

```rust
```rust,ignore
#![feature(macro_at_most_once_rep)]

macro_rules! foo {
Expand Down
10 changes: 10 additions & 0 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,15 @@ declare_lint! {
via the module system"
}

/// Some lints that are buffered from `libsyntax`. See `syntax::early_buffered_lints`.
pub mod parser {
declare_lint! {
pub QUESTION_MARK_MACRO_SEP,
Allow,
"detects the use of `?` as a macro separator"
}
}

/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
Expand Down Expand Up @@ -389,6 +398,7 @@ impl LintPass for HardwiredLints {
WHERE_CLAUSES_OBJECT_SAFETY,
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
MACRO_USE_EXTERN_CRATE,
parser::QUESTION_MARK_MACRO_SEP,
)
}
}
Expand Down
14 changes: 12 additions & 2 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ use hir::def_id::{CrateNum, LOCAL_CRATE};
use hir::intravisit;
use hir;
use lint::builtin::BuiltinLintDiagnostics;
use lint::builtin::parser::QUESTION_MARK_MACRO_SEP;
use session::{Session, DiagnosticMessageId};
use std::{hash, ptr};
use syntax::ast;
use syntax::codemap::{MultiSpan, ExpnFormat};
use syntax::early_buffered_lints::BufferedEarlyLintId;
use syntax::edition::Edition;
use syntax::symbol::Symbol;
use syntax::visit as ast_visit;
Expand Down Expand Up @@ -86,6 +88,13 @@ pub struct Lint {
}

impl Lint {
/// Returns the `rust::lint::Lint` for a `syntax::early_buffered_lints::BufferedEarlyLintId`.
pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self {
match lint_id {
BufferedEarlyLintId::QuestionMarkMacroSep => QUESTION_MARK_MACRO_SEP,
}
}

/// Get the lint's name, with ASCII letters converted to lowercase.
pub fn name_lower(&self) -> String {
self.name.to_ascii_lowercase()
Expand Down Expand Up @@ -118,7 +127,7 @@ macro_rules! declare_lint {
};
);
($vis: vis $NAME: ident, $Level: ident, $desc: expr,
$lint_edition: expr => $edition_level: ident $(,)?
$lint_edition: expr => $edition_level: ident
) => (
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: stringify!($NAME),
Expand All @@ -133,7 +142,8 @@ macro_rules! declare_lint {
/// Declare a static `LintArray` and return it as an expression.
#[macro_export]
macro_rules! lint_array {
($( $lint:expr ),* $(,)?) => {{
($( $lint:expr ),* ,) => { lint_array!( $($lint),* ) };
($( $lint:expr ),*) => {{
vec![$($lint),*]
}}
}
Expand Down
16 changes: 10 additions & 6 deletions src/librustc/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ macro_rules! __impl_stable_hash_field {

#[macro_export]
macro_rules! impl_stable_hash_for {
(enum $enum_name:path { $( $variant:ident $( ( $($field:ident $(-> $delegate:tt)?),* ) )* ),* $(,)? }) => {
// FIXME(mark-i-m): Some of these should be `?` rather than `*`. See the git blame and change
// them back when `?` is supported again.
(enum $enum_name:path { $( $variant:ident $( ( $($field:ident $(-> $delegate:tt)*),* ) )* ),* $(,)* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $enum_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
Expand All @@ -83,14 +85,15 @@ macro_rules! impl_stable_hash_for {
match *self {
$(
$variant $( ( $(ref $field),* ) )* => {
$($( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)?) );*)*
$($( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*)*
}
)*
}
}
}
};
(struct $struct_name:path { $($field:ident $(-> $delegate:tt)?),* $(,)? }) => {
// FIXME(mark-i-m): same here.
(struct $struct_name:path { $($field:ident $(-> $delegate:tt)*),* $(,)* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
Expand All @@ -100,11 +103,12 @@ macro_rules! impl_stable_hash_for {
$(ref $field),*
} = *self;

$( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)?) );*
$( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*
}
}
};
(tuple_struct $struct_name:path { $($field:ident $(-> $delegate:tt)?),* $(,)? }) => {
// FIXME(mark-i-m): same here.
(tuple_struct $struct_name:path { $($field:ident $(-> $delegate:tt)*),* $(,)* }) => {
impl<'a, 'tcx> ::rustc_data_structures::stable_hasher::HashStable<$crate::ich::StableHashingContext<'a>> for $struct_name {
#[inline]
fn hash_stable<W: ::rustc_data_structures::stable_hasher::StableHasherResult>(&self,
Expand All @@ -114,7 +118,7 @@ macro_rules! impl_stable_hash_for {
$(ref $field),*
) = *self;

$( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)?) );*
$( __impl_stable_hash_field!($field, __ctx, __hasher $(, $delegate)*) );*
}
}
};
Expand Down
10 changes: 10 additions & 0 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ use std::path::{Path, PathBuf};
use rustc_data_structures::sync::{self, Lrc, Lock};
use std::sync::mpsc;
use syntax::{self, ast, attr, diagnostics, visit};
use syntax::early_buffered_lints::BufferedEarlyLint;
use syntax::ext::base::ExtCtxt;
use syntax::fold::Folder;
use syntax::parse::{self, PResult};
Expand Down Expand Up @@ -1066,6 +1067,15 @@ where
)
});

// Add all buffered lints from the `ParseSess` to the `Session`.
sess.parse_sess.buffered_lints.with_lock(|buffered_lints| {
info!("{} parse sess buffered_lints", buffered_lints.len());
for BufferedEarlyLint{id, span, msg, lint_id} in buffered_lints.drain(..) {
let lint = lint::Lint::from_parser_lint_id(lint_id);
sess.buffer_lint(lint, id, span, &msg);
}
});

// Done with macro expansion!

after_expand(&krate)?;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ declare_lint! {
pub ANONYMOUS_PARAMETERS,
Allow,
"detects anonymous parameters",
Edition::Edition2018 => Warn,
Edition::Edition2018 => Warn
}

/// Checks for use of anonymous parameters (RFC 1685)
Expand Down Expand Up @@ -1706,7 +1706,7 @@ impl LintPass for SoftLints {
UNIONS_WITH_DROP_FIELDS,
UNREACHABLE_PUB,
TYPE_ALIAS_BOUNDS,
TRIVIAL_BOUNDS,
TRIVIAL_BOUNDS
)
}
}
Expand Down
15 changes: 12 additions & 3 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ extern crate syntax_pos;

use rustc::lint;
use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray};
use rustc::lint::builtin::{BARE_TRAIT_OBJECTS, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
ELIDED_LIFETIMES_IN_PATHS};
use rustc::lint::builtin::MACRO_USE_EXTERN_CRATE;
use rustc::lint::builtin::{
BARE_TRAIT_OBJECTS,
ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
MACRO_USE_EXTERN_CRATE,
ELIDED_LIFETIMES_IN_PATHS,
parser::QUESTION_MARK_MACRO_SEP
};
use rustc::session;
use rustc::util;
use rustc::hir;
Expand Down Expand Up @@ -321,6 +325,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
edition: None,
},
FutureIncompatibleInfo {
id: LintId::of(QUESTION_MARK_MACRO_SEP),
reference: "issue #48075 <https://github.com/rust-lang/rust/issues/48075>",
edition: Some(Edition::Edition2018),
}
]);

// Register renamed and removed lints
Expand Down
39 changes: 39 additions & 0 deletions src/libsyntax/early_buffered_lints.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Allows the buffering of lints for later.
//!
//! Since we cannot have a dependency on `librustc`, we implement some types here that are somewhat
//! redundant. Later, these types can be converted to types for use by the rest of the compiler.

use syntax::ast::NodeId;
use syntax_pos::MultiSpan;

/// Since we cannot import `LintId`s from `rustc::lint`, we define some Ids here which can later be
/// passed to `rustc::lint::Lint::from_parser_lint_id` to get a `rustc::lint::Lint`.
pub enum BufferedEarlyLintId {
/// Usage of `?` as a macro separator is deprecated.
QuestionMarkMacroSep,
}

/// Stores buffered lint info which can later be passed to `librustc`.
pub struct BufferedEarlyLint {
/// The span of code that we are linting on.
pub span: MultiSpan,

/// The lint message.
pub msg: String,

/// The `NodeId` of the AST node that generated the lint.
pub id: NodeId,

/// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
pub lint_id: BufferedEarlyLintId,
}
18 changes: 10 additions & 8 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ macro_rules! ast_fragments {
(
$($Kind:ident($AstTy:ty) {
$kind_name:expr;
$(one fn $fold_ast:ident; fn $visit_ast:ident;)?
$(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)?
// FIXME: HACK: this should be `$(one ...)?` and `$(many ...)?` but `?` macro
// repetition was removed from 2015 edition in #51587 because of ambiguities.
$(one fn $fold_ast:ident; fn $visit_ast:ident;)*
$(many fn $fold_ast_elt:ident; fn $visit_ast_elt:ident;)*
fn $make_ast:ident;
})*
) => {
Expand Down Expand Up @@ -100,22 +102,22 @@ macro_rules! ast_fragments {
AstFragment::OptExpr(expr) =>
AstFragment::OptExpr(expr.and_then(|expr| folder.fold_opt_expr(expr))),
$($(AstFragment::$Kind(ast) =>
AstFragment::$Kind(folder.$fold_ast(ast)),)?)*
AstFragment::$Kind(folder.$fold_ast(ast)),)*)*
$($(AstFragment::$Kind(ast) =>
AstFragment::$Kind(ast.into_iter()
.flat_map(|ast| folder.$fold_ast_elt(ast))
.collect()),)?)*
.collect()),)*)*
}
}

pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
match *self {
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
AstFragment::OptExpr(None) => {}
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)*)*
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
visitor.$visit_ast_elt(ast_elt);
})?)*
})*)*
}
}
}
Expand All @@ -126,10 +128,10 @@ macro_rules! ast_fragments {
}
$($(fn $fold_ast(&mut self, ast: $AstTy) -> $AstTy {
self.expand_fragment(AstFragment::$Kind(ast)).$make_ast()
})?)*
})*)*
$($(fn $fold_ast_elt(&mut self, ast_elt: <$AstTy as IntoIterator>::Item) -> $AstTy {
self.expand_fragment(AstFragment::$Kind(SmallVector::one(ast_elt))).$make_ast()
})?)*
})*)*
}

impl<'a> MacResult for ::ext::tt::macro_rules::ParserAnyMacro<'a> {
Expand Down
25 changes: 21 additions & 4 deletions src/libsyntax/ext/tt/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,17 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
s.iter().map(|m| {
if let MatchedNonterminal(ref nt) = *m {
if let NtTT(ref tt) = **nt {
let tt = quoted::parse(tt.clone().into(), true, sess, features, &def.attrs)
.pop().unwrap();
let tt = quoted::parse(
tt.clone().into(),
true,
sess,
features,
&def.attrs,
edition,
def.id,
)
.pop()
.unwrap();
valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt);
return tt;
}
Expand All @@ -257,8 +266,16 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
s.iter().map(|m| {
if let MatchedNonterminal(ref nt) = *m {
if let NtTT(ref tt) = **nt {
return quoted::parse(tt.clone().into(), false, sess, features, &def.attrs)
.pop().unwrap();
return quoted::parse(
tt.clone().into(),
false,
sess,
features,
&def.attrs,
edition,
def.id,
).pop()
.unwrap();
}
}
sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
Expand Down
Loading