Auto merge of #61741 - Centril:rollup-fgro5kz, r=Centril

Rollup of 11 pull requests

Successful merges:

 - #61518 (Add loops to doc list of things not stable in const fn)
 - #61526 (move some tests into subfolders)
 - #61550 (Windows 10 SDK is also required now.)
 - #61606 (Remove some legacy proc macro flavors)
 - #61652 (Mention slice patterns in array)
 - #61686 (librustc_errors: Add some more documentation)
 - #61698 (typeck: Fix const generic in repeat param ICE.)
 - #61707 (Azure: retry failed awscli installs)
 - #61715 (make sure make_ascii_lowercase actually leaves upper-case non-ASCII characters alone)
 - #61724 (core: use memcmp optimization for 128 bit integer slices)
 - #61726 (Use `for_each` in `Iterator::partition`)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-06-11 23:29:20 +00:00
commit 961a9d6e97
48 changed files with 387 additions and 750 deletions

View file

@ -74,8 +74,9 @@ steps:
# images, etc.
- bash: |
set -e
source src/ci/shared.sh
sudo apt-get install -y python3-setuptools
pip3 install awscli --upgrade --user
retry pip3 install awscli --upgrade --user
echo "##vso[task.prependpath]$HOME/.local/bin"
displayName: Install awscli (Linux)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))

View file

@ -130,9 +130,9 @@ build.
MSVC builds of Rust additionally require an installation of Visual Studio 2017
(or later) so `rustc` can use its linker. The simplest way is to get the
[Visual Studio Build Tools] and check the “C++ build tools” workload.
[Visual Studio], check the “C++ build tools” and “Windows 10 SDK” workload.
[Visual Studio Build Tools]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
[Visual Studio]: https://visualstudio.microsoft.com/downloads/
(If you're installing cmake yourself, be careful that “C++ CMake tools for
Windows” doesn't get included under “Individual components”.)

View file

@ -1495,13 +1495,13 @@ pub trait Iterator {
let mut left: B = Default::default();
let mut right: B = Default::default();
for x in self {
self.for_each(|x| {
if f(&x) {
left.extend(Some(x))
} else {
right.extend(Some(x))
}
}
});
(left, right)
}

View file

@ -5420,7 +5420,7 @@ macro_rules! impl_marker_for {
}
impl_marker_for!(BytewiseEquality,
u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool);
u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool);
#[doc(hidden)]
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {

View file

@ -4000,11 +4000,11 @@ impl str {
/// # Examples
///
/// ```
/// let mut s = String::from("Grüße, Jürgen ❤");
/// let mut s = String::from("GRÜßE, JÜRGEN ❤");
///
/// s.make_ascii_lowercase();
///
/// assert_eq!("grüße, jürgen ❤", s);
/// assert_eq!("grÜße, jÜrgen ❤", s);
/// ```
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
pub fn make_ascii_lowercase(&mut self) {

View file

@ -227,13 +227,17 @@ impl OutputType {
}
}
/// The type of diagnostics output to generate.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
/// Output meant for the consumption of humans.
HumanReadable(HumanReadableErrorType),
/// Output that's consumed by other tools such as `rustfix` or the `RLS`.
Json {
/// Render the json in a human readable way (with indents and newlines)
/// Render the JSON in a human readable way (with indents and newlines).
pretty: bool,
/// The way the `rendered` field is created
/// The JSON output includes a `rendered` field that includes the rendered
/// human output.
json_rendered: HumanReadableErrorType,
},
}

View file

@ -348,7 +348,7 @@ impl<'a> DiagnosticBuilder<'a> {
/// Convenience function for internal use, clients should use one of the
/// struct_* methods on Handler.
pub fn new_with_code(handler: &'a Handler,
crate fn new_with_code(handler: &'a Handler,
level: Level,
code: Option<DiagnosticId>,
message: &str)

View file

@ -1,3 +1,12 @@
//! The current rustc diagnostics emitter.
//!
//! An `Emitter` takes care of generating the output from a `DiagnosticBuilder` struct.
//!
//! There are various `Emitter` implementations that generate different output formats such as
//! JSON and human readable output.
//!
//! The output types are defined in `librustc::session::config::ErrorOutputType`.
use Destination::*;
use syntax_pos::{SourceFile, Span, MultiSpan};

View file

@ -1,5 +1,10 @@
//! Diagnostics creation and emission for `rustc`.
//!
//! This module contains the code for creating and emitting diagnostics.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(crate_visibility_modifier)]
#![allow(unused_attributes)]
#![cfg_attr(unix, feature(libc))]
#![feature(nll)]

View file

@ -614,7 +614,7 @@ impl<'a> CrateLoader<'a> {
match decl {
ProcMacro::CustomDerive { trait_name, attributes, client } => {
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
(trait_name, SyntaxExtension::ProcMacroDerive(
(trait_name, SyntaxExtension::Derive(
Box::new(ProcMacroDerive {
client,
attrs: attrs.clone(),
@ -624,13 +624,13 @@ impl<'a> CrateLoader<'a> {
))
}
ProcMacro::Attr { name, client } => {
(name, SyntaxExtension::AttrProcMacro(
(name, SyntaxExtension::Attr(
Box::new(AttrProcMacro { client }),
root.edition,
))
}
ProcMacro::Bang { name, client } => {
(name, SyntaxExtension::ProcMacro {
(name, SyntaxExtension::Bang {
expander: Box::new(BangProcMacro { client }),
allow_internal_unstable: None,
edition: root.edition,

View file

@ -430,7 +430,7 @@ impl cstore::CStore {
use syntax_ext::proc_macro_impl::BangProcMacro;
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
let ext = SyntaxExtension::ProcMacro {
let ext = SyntaxExtension::Bang {
expander: Box::new(BangProcMacro { client }),
allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
edition: data.root.edition,

View file

@ -299,7 +299,7 @@ fn check_terminator(
TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err((
span,
"`if`, `match`, `&&` and `||` are not stable in const fn".into(),
"loops and conditional expressions are not stable in const fn".into(),
)),
| TerminatorKind::Abort | TerminatorKind::Unreachable => {
Err((span, "const fn with unreachable code is not stable".into()))

View file

@ -4,8 +4,9 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension};
use syntax::ext::base::MacroExpanderFn;
use syntax::ext::hygiene::Transparency;
use syntax::symbol::{Symbol, sym};
use syntax::ast;
use syntax::feature_gate::AttributeType;
@ -84,47 +85,26 @@ impl<'a> Registry<'a> {
/// Register a syntax extension of any kind.
///
/// This is the most general hook into `libsyntax`'s expansion behavior.
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: SyntaxExtension) {
if name == sym::macro_rules {
panic!("user-defined macros may not be named `macro_rules`");
}
self.syntax_exts.push((name, match extension {
NormalTT {
expander,
def_info: _,
allow_internal_unstable,
allow_internal_unsafe,
local_inner_macros,
unstable_feature,
edition,
} => {
let nid = ast::CRATE_NODE_ID;
NormalTT {
expander,
def_info: Some((nid, self.krate_span)),
allow_internal_unstable,
allow_internal_unsafe,
local_inner_macros,
unstable_feature,
edition,
}
}
IdentTT { expander, span: _, allow_internal_unstable } => {
IdentTT { expander, span: Some(self.krate_span), allow_internal_unstable }
}
_ => extension,
}));
if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension {
*def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
}
self.syntax_exts.push((name, extension));
}
/// Register a macro of the usual kind.
///
/// This is a convenience wrapper for `register_syntax_extension`.
/// It builds for you a `NormalTT` that calls `expander`,
/// It builds for you a `SyntaxExtension::LegacyBang` that calls `expander`,
/// and also takes care of interning the macro's name.
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
self.register_syntax_extension(Symbol::intern(name), NormalTT {
self.register_syntax_extension(Symbol::intern(name), SyntaxExtension::LegacyBang {
expander: Box::new(expander),
def_info: None,
transparency: Transparency::SemiTransparent,
allow_internal_unstable: None,
allow_internal_unsafe: false,
local_inner_macros: false,

View file

@ -242,8 +242,7 @@ impl<'a> base::Resolver for Resolver<'a> {
fn check_unused_macros(&self) {
for did in self.unused_macros.iter() {
let id_span = match *self.macro_map[did] {
SyntaxExtension::NormalTT { def_info, .. } |
SyntaxExtension::DeclMacro { def_info, .. } => def_info,
SyntaxExtension::LegacyBang { def_info, .. } => def_info,
_ => None,
};
if let Some((id, span)) = id_span {
@ -587,7 +586,7 @@ impl<'a> Resolver<'a> {
match self.resolve_macro_to_res(derive, MacroKind::Derive,
&parent_scope, true, force) {
Ok((_, ext)) => {
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
if let SyntaxExtension::Derive(_, helpers, _) = &*ext {
if helpers.contains(&ident.name) {
let binding =
(Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),

View file

@ -2155,6 +2155,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
result_ty
}
/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
pub fn const_param_def_id(&self, expr: &hir::Expr) -> Option<DefId> {
match &expr.node {
ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
Res::Def(DefKind::ConstParam, did) => Some(did),
_ => None,
},
_ => None,
}
}
pub fn ast_const_to_const(
&self,
ast_const: &hir::AnonConst,
@ -2185,19 +2196,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
}
}
if let ExprKind::Path(ref qpath) = expr.node {
if let hir::QPath::Resolved(_, ref path) = qpath {
if let Res::Def(DefKind::ConstParam, def_id) = path.res {
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(node_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
let name = tcx.hir().name(node_id).as_interned_str();
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
}
}
};
if let Some(def_id) = self.const_param_def_id(expr) {
// Find the name and index of the const parameter by indexing the generics of the
// parent item and construct a `ParamConst`.
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
let item_id = tcx.hir().get_parent_node(node_id);
let item_def_id = tcx.hir().local_def_id(item_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
let name = tcx.hir().name(node_id).as_interned_str();
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
}
tcx.mk_const(const_)
}

View file

@ -2504,6 +2504,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty
}
/// Returns the `DefId` of the constant parameter that the provided expression is a path to.
pub fn const_param_def_id(&self, hir_c: &hir::AnonConst) -> Option<DefId> {
AstConv::const_param_def_id(self, &self.tcx.hir().body(hir_c.body).value)
}
pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
AstConv::ast_const_to_const(self, ast_c, ty)
}
@ -4479,19 +4484,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
ExprKind::Repeat(ref element, ref count) => {
let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
let param_env = ty::ParamEnv::empty();
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
count_def_id,
substs,
).unwrap();
let global_id = GlobalId {
instance,
promoted: None
let count = if self.const_param_def_id(count).is_some() {
Ok(self.to_const(count, self.tcx.type_of(count_def_id)))
} else {
let param_env = ty::ParamEnv::empty();
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
let instance = ty::Instance::resolve(
tcx.global_tcx(),
param_env,
count_def_id,
substs,
).unwrap();
let global_id = GlobalId {
instance,
promoted: None
};
tcx.const_eval(param_env.and(global_id))
};
let count = tcx.const_eval(param_env.and(global_id));
let uty = match expected {
ExpectHasType(uty) => {

View file

@ -471,7 +471,7 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE
}
LoadedMacro::ProcMacro(ext) => {
let helpers = match &*ext {
&SyntaxExtension::ProcMacroDerive(_, ref syms, ..) => { syms.clean(cx) }
&SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) }
_ => Vec::new(),
};

View file

@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
// skip proc-macro stubs, they'll cause `get_macro` to crash
} else {
if let SyntaxExtension::DeclMacro { .. } = *resolver.get_macro(res) {
if let SyntaxExtension::LegacyBang { .. } = *resolver.get_macro(res) {
return Some(res.map_id(|_| panic!("unexpected id")));
}
}

View file

@ -482,8 +482,8 @@ mod prim_pointer { }
/// an array. Indeed, this provides most of the API for working with arrays.
/// Slices have a dynamic size and do not coerce to arrays.
///
/// There is no way to move elements out of an array. See [`mem::replace`][replace]
/// for an alternative.
/// You can move elements out of an array with a slice pattern. If you want
/// one element, see [`mem::replace`][replace].
///
/// # Examples
///
@ -525,6 +525,16 @@ mod prim_pointer { }
/// for x in &array { }
/// ```
///
/// You can use a slice pattern to move elements out of an array:
///
/// ```
/// fn move_away(_: String) { /* Do interesting things. */ }
///
/// let [john, roa] = ["John".to_string(), "Roa".to_string()];
/// move_away(john);
/// move_away(roa);
/// ```
///
/// [slice]: primitive.slice.html
/// [copy]: marker/trait.Copy.html
/// [clone]: clone/trait.Clone.html

View file

@ -1,6 +1,4 @@
pub use SyntaxExtension::*;
use crate::ast::{self, Attribute, Name, PatKind, MetaItem};
use crate::ast::{self, Attribute, Name, PatKind};
use crate::attr::HasAttrs;
use crate::source_map::{SourceMap, Spanned, respan};
use crate::edition::Edition;
@ -137,29 +135,6 @@ impl Annotatable {
}
}
// A more flexible ItemDecorator.
pub trait MultiItemDecorator {
fn expand(&self,
ecx: &mut ExtCtxt<'_>,
sp: Span,
meta_item: &ast::MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable));
}
impl<F> MultiItemDecorator for F
where F : Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
{
fn expand(&self,
ecx: &mut ExtCtxt<'_>,
sp: Span,
meta_item: &ast::MetaItem,
item: &Annotatable,
push: &mut dyn FnMut(Annotatable)) {
(*self)(ecx, sp, meta_item, item, push)
}
}
// `meta_item` is the annotation, and `item` is the item being modified.
// FIXME Decorators should follow the same pattern too.
pub trait MultiItemModifier {
@ -288,34 +263,6 @@ impl<F> TTMacroExpander for F
}
}
pub trait IdentMacroExpander {
fn expand<'cx>(&self,
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
ident: ast::Ident,
token_tree: Vec<tokenstream::TokenTree>)
-> Box<dyn MacResult+'cx>;
}
pub type IdentMacroExpanderFn =
for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, ast::Ident, Vec<tokenstream::TokenTree>)
-> Box<dyn MacResult+'cx>;
impl<F> IdentMacroExpander for F
where F : for<'cx> Fn(&'cx mut ExtCtxt<'_>, Span, ast::Ident,
Vec<tokenstream::TokenTree>) -> Box<dyn MacResult+'cx>
{
fn expand<'cx>(&self,
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
ident: ast::Ident,
token_tree: Vec<tokenstream::TokenTree>)
-> Box<dyn MacResult+'cx>
{
(*self)(cx, sp, ident, token_tree)
}
}
// Use a macro because forwarding to a simple function has type system issues
macro_rules! make_stmts_default {
($me:expr) => {
@ -570,9 +517,6 @@ impl MacResult for DummyResult {
}
}
pub type BuiltinDeriveFn =
for<'cx> fn(&'cx mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable));
/// Represents different kinds of macro invocations that can be resolved.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum MacroKind {
@ -606,129 +550,116 @@ impl MacroKind {
/// An enum representing the different kinds of syntax extensions.
pub enum SyntaxExtension {
/// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
NonMacroAttr { mark_used: bool },
/// A syntax extension that is attached to an item and creates new items
/// based upon it.
///
/// `#[derive(...)]` is a `MultiItemDecorator`.
///
/// Prefer ProcMacro or MultiModifier since they are more flexible.
MultiDecorator(Box<dyn MultiItemDecorator + sync::Sync + sync::Send>),
/// A syntax extension that is attached to an item and modifies it
/// in-place. Also allows decoration, i.e., creating new items.
MultiModifier(Box<dyn MultiItemModifier + sync::Sync + sync::Send>),
/// A function-like procedural macro. TokenStream -> TokenStream.
ProcMacro {
/// A token-based function-like macro.
Bang {
/// An expander with signature TokenStream -> TokenStream.
expander: Box<dyn ProcMacro + sync::Sync + sync::Send>,
/// Whitelist of unstable features that are treated as stable inside this macro
/// Whitelist of unstable features that are treated as stable inside this macro.
allow_internal_unstable: Option<Lrc<[Symbol]>>,
/// Edition of the crate in which this macro is defined.
edition: Edition,
},
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
/// The first TokenSteam is the attribute, the second is the annotated item.
/// Allows modification of the input items and adding new items, similar to
/// MultiModifier, but uses TokenStreams, rather than AST nodes.
AttrProcMacro(Box<dyn AttrProcMacro + sync::Sync + sync::Send>, Edition),
/// A normal, function-like syntax extension.
///
/// `bytes!` is a `NormalTT`.
NormalTT {
/// An AST-based function-like macro.
LegacyBang {
/// An expander with signature TokenStream -> AST.
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
/// Some info about the macro's definition point.
def_info: Option<(ast::NodeId, Span)>,
/// Whether the contents of the macro can
/// directly use `#[unstable]` things.
///
/// Only allows things that require a feature gate in the given whitelist
/// Hygienic properties of identifiers produced by this macro.
transparency: Transparency,
/// Whitelist of unstable features that are treated as stable inside this macro.
allow_internal_unstable: Option<Lrc<[Symbol]>>,
/// Whether the contents of the macro can use `unsafe`
/// without triggering the `unsafe_code` lint.
/// Suppresses the `unsafe_code` lint for code produced by this macro.
allow_internal_unsafe: bool,
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
/// for a given macro.
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
local_inner_macros: bool,
/// The macro's feature name if it is unstable, and the stability feature
/// The macro's feature name and tracking issue number if it is unstable.
unstable_feature: Option<(Symbol, u32)>,
/// Edition of the crate in which the macro is defined
/// Edition of the crate in which this macro is defined.
edition: Edition,
},
/// A function-like syntax extension that has an extra ident before
/// the block.
IdentTT {
expander: Box<dyn IdentMacroExpander + sync::Sync + sync::Send>,
span: Option<Span>,
allow_internal_unstable: Option<Lrc<[Symbol]>>,
/// A token-based attribute macro.
Attr(
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
/// The first TokenSteam is the attribute itself, the second is the annotated item.
/// The produced TokenSteam replaces the input TokenSteam.
Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
/// Edition of the crate in which this macro is defined.
Edition,
),
/// An AST-based attribute macro.
LegacyAttr(
/// An expander with signature (AST, AST) -> AST.
/// The first AST fragment is the attribute itself, the second is the annotated item.
/// The produced AST fragment replaces the input AST fragment.
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
),
/// A trivial attribute "macro" that does nothing,
/// only keeps the attribute and marks it as known.
NonMacroAttr {
/// Suppresses the `unused_attributes` lint for this attribute.
mark_used: bool,
},
/// An attribute-like procedural macro. TokenStream -> TokenStream.
/// The input is the annotated item.
/// Allows generating code to implement a Trait for a given struct
/// or enum item.
ProcMacroDerive(Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
Vec<Symbol> /* inert attribute names */, Edition),
/// A token-based derive macro.
Derive(
/// An expander with signature TokenStream -> TokenStream (not yet).
/// The produced TokenSteam is appended to the input TokenSteam.
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
/// Names of helper attributes registered by this macro.
Vec<Symbol>,
/// Edition of the crate in which this macro is defined.
Edition,
),
/// An attribute-like procedural macro that derives a builtin trait.
BuiltinDerive(BuiltinDeriveFn),
/// A declarative macro, e.g., `macro m() {}`.
DeclMacro {
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
def_info: Option<(ast::NodeId, Span)>,
is_transparent: bool,
edition: Edition,
}
/// An AST-based derive macro.
LegacyDerive(
/// An expander with signature AST -> AST.
/// The produced AST fragment is appended to the input AST fragment.
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
),
}
impl SyntaxExtension {
/// Returns which kind of macro calls this syntax extension.
pub fn kind(&self) -> MacroKind {
match *self {
SyntaxExtension::DeclMacro { .. } |
SyntaxExtension::NormalTT { .. } |
SyntaxExtension::IdentTT { .. } |
SyntaxExtension::ProcMacro { .. } =>
MacroKind::Bang,
SyntaxExtension::NonMacroAttr { .. } |
SyntaxExtension::MultiDecorator(..) |
SyntaxExtension::MultiModifier(..) |
SyntaxExtension::AttrProcMacro(..) =>
MacroKind::Attr,
SyntaxExtension::ProcMacroDerive(..) |
SyntaxExtension::BuiltinDerive(..) =>
MacroKind::Derive,
SyntaxExtension::Bang { .. } |
SyntaxExtension::LegacyBang { .. } => MacroKind::Bang,
SyntaxExtension::Attr(..) |
SyntaxExtension::LegacyAttr(..) |
SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr,
SyntaxExtension::Derive(..) |
SyntaxExtension::LegacyDerive(..) => MacroKind::Derive,
}
}
pub fn default_transparency(&self) -> Transparency {
match *self {
SyntaxExtension::ProcMacro { .. } |
SyntaxExtension::AttrProcMacro(..) |
SyntaxExtension::ProcMacroDerive(..) |
SyntaxExtension::DeclMacro { is_transparent: false, .. } => Transparency::Opaque,
SyntaxExtension::DeclMacro { is_transparent: true, .. } => Transparency::Transparent,
_ => Transparency::SemiTransparent,
SyntaxExtension::LegacyBang { transparency, .. } => transparency,
SyntaxExtension::Bang { .. } |
SyntaxExtension::Attr(..) |
SyntaxExtension::Derive(..) |
SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque,
SyntaxExtension::LegacyAttr(..) |
SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent,
}
}
pub fn edition(&self, default_edition: Edition) -> Edition {
match *self {
SyntaxExtension::NormalTT { edition, .. } |
SyntaxExtension::DeclMacro { edition, .. } |
SyntaxExtension::ProcMacro { edition, .. } |
SyntaxExtension::AttrProcMacro(.., edition) |
SyntaxExtension::ProcMacroDerive(.., edition) => edition,
SyntaxExtension::Bang { edition, .. } |
SyntaxExtension::LegacyBang { edition, .. } |
SyntaxExtension::Attr(.., edition) |
SyntaxExtension::Derive(.., edition) => edition,
// Unstable legacy stuff
SyntaxExtension::NonMacroAttr { .. } |
SyntaxExtension::IdentTT { .. } |
SyntaxExtension::MultiDecorator(..) |
SyntaxExtension::MultiModifier(..) |
SyntaxExtension::BuiltinDerive(..) => default_edition,
SyntaxExtension::LegacyAttr(..) |
SyntaxExtension::LegacyDerive(..) => default_edition,
}
}
}

View file

@ -389,7 +389,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let item = match self.cx.resolver.resolve_macro_path(
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
Ok(ext) => match *ext {
BuiltinDerive(..) => item_with_markers.clone(),
SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(),
_ => item.clone(),
},
_ => item.clone(),
@ -548,7 +548,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
_ => unreachable!(),
};
if let NonMacroAttr { mark_used: false } = *ext {} else {
if let SyntaxExtension::NonMacroAttr { mark_used: false } = *ext {} else {
// Macro attrs are always used when expanded,
// non-macro attrs are considered used when the field says so.
attr::mark_used(&attr);
@ -564,26 +564,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
});
match *ext {
NonMacroAttr { .. } => {
SyntaxExtension::NonMacroAttr { .. } => {
attr::mark_known(&attr);
item.visit_attrs(|attrs| attrs.push(attr));
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
}
MultiModifier(ref mac) => {
SyntaxExtension::LegacyAttr(ref mac) => {
let meta = attr.parse_meta(self.cx.parse_sess)
.map_err(|mut e| { e.emit(); }).ok()?;
let item = mac.expand(self.cx, attr.span, &meta, item);
Some(invoc.fragment_kind.expect_from_annotatables(item))
}
MultiDecorator(ref mac) => {
let mut items = Vec::new();
let meta = attr.parse_meta(self.cx.parse_sess)
.expect("derive meta should already have been parsed");
mac.expand(self.cx, attr.span, &meta, &item, &mut |item| items.push(item));
items.push(item);
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
AttrProcMacro(ref mac, ..) => {
SyntaxExtension::Attr(ref mac, ..) => {
self.gate_proc_macro_attr_item(attr.span, &item);
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
Annotatable::Item(item) => token::NtItem(item),
@ -600,7 +592,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.gate_proc_macro_expansion(attr.span, &res);
res
}
ProcMacroDerive(..) | BuiltinDerive(..) => {
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(attr.span)
@ -755,17 +747,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
};
let opt_expanded = match *ext {
DeclMacro { ref expander, def_info, edition, .. } => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
None, false, false, None,
edition) {
dummy_span
} else {
kind.make_from(expander.expand(self.cx, span, mac.node.stream(), None))
}
}
NormalTT {
SyntaxExtension::LegacyBang {
ref expander,
def_info,
ref allow_internal_unstable,
@ -773,6 +755,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
local_inner_macros,
unstable_feature,
edition,
..
} => {
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
allow_internal_unstable.clone(),
@ -791,43 +774,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
}
}
IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => {
if ident.name == kw::Invalid {
self.cx.span_err(path.span,
&format!("macro {}! expects an ident argument", path));
self.cx.trace_macros_diag();
kind.dummy(span)
} else {
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
call_site: span,
def_site: tt_span,
format: macro_bang_format(path),
allow_internal_unstable: allow_internal_unstable.clone(),
allow_internal_unsafe: false,
local_inner_macros: false,
edition: self.cx.parse_sess.edition,
});
let input: Vec<_> = mac.node.stream().into_trees().collect();
kind.make_from(expander.expand(self.cx, span, ident, input))
}
}
MultiDecorator(..) | MultiModifier(..) |
AttrProcMacro(..) | SyntaxExtension::NonMacroAttr { .. } => {
SyntaxExtension::Attr(..) |
SyntaxExtension::LegacyAttr(..) |
SyntaxExtension::NonMacroAttr { .. } => {
self.cx.span_err(path.span,
&format!("`{}` can only be used in attributes", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}
ProcMacroDerive(..) | BuiltinDerive(..) => {
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}
SyntaxExtension::ProcMacro { ref expander, ref allow_internal_unstable, edition } => {
SyntaxExtension::Bang { ref expander, ref allow_internal_unstable, edition } => {
if ident.name != kw::Invalid {
let msg =
format!("macro {}! expects no ident argument, given '{}'", path, ident);
@ -924,29 +886,29 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
edition: ext.edition(self.cx.parse_sess.edition),
};
match *ext {
ProcMacroDerive(ref ext, ..) => {
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
path: Path::from_ident(Ident::invalid()),
span: DUMMY_SP,
node: ast::MetaItemKind::Word,
match ext {
SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => {
let meta = match ext {
SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this
path: Path::from_ident(Ident::invalid()),
span: DUMMY_SP,
node: ast::MetaItemKind::Word,
},
_ => {
expn_info.allow_internal_unstable = Some(vec![
sym::rustc_attrs,
Symbol::intern("derive_clone_copy"),
Symbol::intern("derive_eq"),
// RustcDeserialize and RustcSerialize
Symbol::intern("libstd_sys_internals"),
].into());
attr.meta()?
}
};
let items = ext.expand(self.cx, span, &dummy, item);
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
BuiltinDerive(func) => {
expn_info.allow_internal_unstable = Some(vec![
sym::rustc_attrs,
Symbol::intern("derive_clone_copy"),
Symbol::intern("derive_eq"),
Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize
].into());
invoc.expansion_data.mark.set_expn_info(expn_info);
let span = span.with_ctxt(self.cx.backtrace());
let mut items = Vec::new();
func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
let items = expander.expand(self.cx, span, &meta, item);
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
_ => {

View file

@ -1,8 +1,8 @@
use crate::{ast, attr};
use crate::edition::Edition;
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
use crate::ext::base::{NormalTT, TTMacroExpander};
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander};
use crate::ext::expand::{AstFragment, AstFragmentKind};
use crate::ext::hygiene::Transparency;
use crate::ext::tt::macro_parser::{Success, Error, Failure};
use crate::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
@ -374,66 +374,66 @@ pub fn compile(
valid,
});
if body.legacy {
let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable)
.map(|attr| attr
.meta_item_list()
.map(|list| list.iter()
.filter_map(|it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
sess.span_diagnostic.span_err(it.span(),
"allow internal unstable expects feature names")
}
name
})
.collect::<Vec<Symbol>>().into()
)
.unwrap_or_else(|| {
sess.span_diagnostic.span_warn(
attr.span, "allow_internal_unstable expects list of feature names. In the \
future this will become a hard error. Please use `allow_internal_unstable(\
foo, bar)` to only allow the `foo` and `bar` features",
);
vec![sym::allow_internal_unstable_backcompat_hack].into()
})
);
let allow_internal_unsafe = attr::contains_name(&def.attrs, sym::allow_internal_unsafe);
let mut local_inner_macros = false;
if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) {
if let Some(l) = macro_export.meta_item_list() {
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
}
}
let unstable_feature = attr::find_stability(&sess,
&def.attrs, def.span).and_then(|stability| {
if let attr::StabilityLevel::Unstable { issue, .. } = stability.level {
Some((stability.feature, issue))
} else {
None
}
});
NormalTT {
expander,
def_info: Some((def.id, def.span)),
allow_internal_unstable,
allow_internal_unsafe,
local_inner_macros,
unstable_feature,
edition,
}
let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
Transparency::Transparent
} else if body.legacy {
Transparency::SemiTransparent
} else {
let is_transparent = attr::contains_name(&def.attrs, sym::rustc_transparent_macro);
Transparency::Opaque
};
SyntaxExtension::DeclMacro {
expander,
def_info: Some((def.id, def.span)),
is_transparent,
edition,
let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable)
.map(|attr| attr
.meta_item_list()
.map(|list| list.iter()
.filter_map(|it| {
let name = it.ident().map(|ident| ident.name);
if name.is_none() {
sess.span_diagnostic.span_err(it.span(),
"allow internal unstable expects feature names")
}
name
})
.collect::<Vec<Symbol>>().into()
)
.unwrap_or_else(|| {
sess.span_diagnostic.span_warn(
attr.span, "allow_internal_unstable expects list of feature names. In the \
future this will become a hard error. Please use `allow_internal_unstable(\
foo, bar)` to only allow the `foo` and `bar` features",
);
vec![sym::allow_internal_unstable_backcompat_hack].into()
})
);
let allow_internal_unsafe = attr::contains_name(&def.attrs, sym::allow_internal_unsafe);
let mut local_inner_macros = false;
if let Some(macro_export) = attr::find_by_name(&def.attrs, sym::macro_export) {
if let Some(l) = macro_export.meta_item_list() {
local_inner_macros = attr::list_contains_name(&l, sym::local_inner_macros);
}
}
let unstable_feature = attr::find_stability(&sess,
&def.attrs, def.span).and_then(|stability| {
if let attr::StabilityLevel::Unstable { issue, .. } = stability.level {
Some((stability.feature, issue))
} else {
None
}
});
SyntaxExtension::LegacyBang {
expander,
def_info: Some((def.id, def.span)),
transparency,
allow_internal_unstable,
allow_internal_unsafe,
local_inner_macros,
unstable_feature,
edition,
}
}
fn check_lhs_nt_follows(sess: &ParseSess,

View file

@ -1,8 +1,8 @@
//! The compiler code necessary to implement the `#[derive]` extensions.
use rustc_data_structures::sync::Lrc;
use syntax::ast;
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
use syntax::ast::{self, MetaItem};
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier};
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ptr::P;
@ -39,9 +39,25 @@ pub mod partial_ord;
#[path="cmp/ord.rs"]
pub mod ord;
pub mod generic;
struct BuiltinDerive(
fn(&mut ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable))
);
impl MultiItemModifier for BuiltinDerive {
fn expand(&self,
ecx: &mut ExtCtxt<'_>,
span: Span,
meta_item: &MetaItem,
item: Annotatable)
-> Vec<Annotatable> {
let mut items = Vec::new();
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
items
}
}
macro_rules! derive_traits {
($( $name:expr => $func:path, )+) => {
pub fn is_builtin_trait(name: ast::Name) -> bool {
@ -55,7 +71,7 @@ macro_rules! derive_traits {
$(
resolver.add_builtin(
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
Lrc::new(SyntaxExtension::BuiltinDerive($func))
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func))))
);
)*
}

View file

@ -42,7 +42,9 @@ pub mod proc_macro_impl;
use rustc_data_structures::sync::Lrc;
use syntax::ast;
use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension, MultiModifier};
use syntax::ext::base::{MacroExpanderFn, NamedSyntaxExtension, SyntaxExtension};
use syntax::ext::hygiene::Transparency;
use syntax::edition::Edition;
use syntax::symbol::{sym, Symbol};
@ -57,9 +59,10 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
macro_rules! register {
($( $name:ident: $f:expr, )*) => { $(
register(Symbol::intern(stringify!($name)),
NormalTT {
SyntaxExtension::LegacyBang {
expander: Box::new($f as MacroExpanderFn),
def_info: None,
transparency: Transparency::SemiTransparent,
allow_internal_unstable: None,
allow_internal_unsafe: false,
local_inner_macros: false,
@ -94,15 +97,16 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
assert: assert::expand_assert,
}
register(sym::test_case, MultiModifier(Box::new(test_case::expand)));
register(sym::test, MultiModifier(Box::new(test::expand_test)));
register(sym::bench, MultiModifier(Box::new(test::expand_bench)));
register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand)));
register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test)));
register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench)));
// format_args uses `unstable` things internally.
register(Symbol::intern("format_args"),
NormalTT {
SyntaxExtension::LegacyBang {
expander: Box::new(format::expand_format_args),
def_info: None,
transparency: Transparency::SemiTransparent,
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
allow_internal_unsafe: false,
local_inner_macros: false,
@ -110,9 +114,10 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
edition,
});
register(sym::format_args_nl,
NormalTT {
SyntaxExtension::LegacyBang {
expander: Box::new(format::expand_format_args_nl),
def_info: None,
transparency: Transparency::SemiTransparent,
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
allow_internal_unsafe: false,
local_inner_macros: false,

View file

@ -8,13 +8,13 @@ use std::intrinsics::exact_div;
// CHECK-LABEL: @exact_sdiv
#[no_mangle]
pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 {
// CHECK: sdiv exact
// CHECK: sdiv exact
exact_div(x, y)
}
// CHECK-LABEL: @exact_udiv
#[no_mangle]
pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 {
// CHECK: udiv exact
// CHECK: udiv exact
exact_div(x, y)
}

View file

@ -1,71 +0,0 @@
// force-host
#![feature(plugin_registrar, rustc_private)]
extern crate syntax;
extern crate syntax_ext;
extern crate rustc_plugin;
use syntax_ext::deriving;
use deriving::generic::*;
use deriving::generic::ty::*;
use rustc_plugin::Registry;
use syntax::ast::*;
use syntax::source_map::Span;
use syntax::ext::base::*;
use syntax::ext::build::AstBuilder;
use syntax::symbol::Symbol;
use syntax::ptr::P;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(Symbol::intern("derive_CustomPartialEq"),
MultiDecorator(Box::new(expand_deriving_partial_eq)));
}
fn expand_deriving_partial_eq(cx: &mut ExtCtxt, span: Span, mitem: &MetaItem, item: &Annotatable,
push: &mut FnMut(Annotatable)) {
// structures are equal if all fields are equal, and non equal, if
// any fields are not equal or if the enum variants are different
fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
cs_fold(true,
|cx, span, subexpr, self_f, other_fs| {
let other_f = (other_fs.len(), other_fs.get(0)).1.unwrap();
let eq = cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone());
cx.expr_binary(span, BinOpKind::And, subexpr, eq)
},
cx.expr_bool(span, true),
Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
cx,
span,
substr)
}
let inline = cx.meta_word(span, Symbol::intern("inline"));
let attrs = vec![cx.attribute(span, inline)];
let methods = vec![MethodDef {
name: "eq",
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![(borrowed_self(), "other")],
ret_ty: Literal(deriving::generic::ty::Path::new_local("bool")),
attributes: attrs,
is_unsafe: false,
unify_fieldless_variants: true,
combine_substructure: combine_substructure(Box::new(cs_eq)),
}];
let trait_def = TraitDef {
span: span,
attributes: Vec::new(),
path: deriving::generic::ty::Path::new(vec!["cmp", "PartialEq"]),
additional_bounds: Vec::new(),
generics: LifetimeBounds::empty(),
is_unsafe: false,
supports_unions: false,
methods: methods,
associated_types: Vec::new(),
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -1,84 +0,0 @@
// force-host
#![feature(plugin_registrar)]
#![feature(box_syntax)]
#![feature(rustc_private)]
extern crate syntax;
extern crate syntax_ext;
extern crate syntax_pos;
extern crate rustc;
extern crate rustc_plugin;
use syntax::ast;
use syntax::attr;
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::symbol::{Symbol, sym};
use syntax::ptr::P;
use syntax_ext::deriving::generic::{TraitDef, MethodDef, combine_substructure};
use syntax_ext::deriving::generic::{Substructure, Struct, EnumMatching};
use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
use syntax_pos::Span;
use rustc_plugin::Registry;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
Symbol::intern("rustc_derive_TotalSum"),
MultiDecorator(box expand));
}
fn expand(cx: &mut ExtCtxt,
span: Span,
mitem: &ast::MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
let trait_def = TraitDef {
span: span,
attributes: vec![],
path: Path::new_local("TotalSum"),
additional_bounds: vec![],
generics: LifetimeBounds::empty(),
associated_types: vec![],
is_unsafe: false,
supports_unions: false,
methods: vec![
MethodDef {
name: "total_sum",
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![],
ret_ty: Literal(Path::new_local("isize")),
attributes: vec![],
is_unsafe: false,
unify_fieldless_variants: true,
combine_substructure: combine_substructure(Box::new(totalsum_substructure)),
},
],
};
trait_def.expand(cx, mitem, item, push)
}
// Mostly copied from syntax::ext::deriving::hash
/// Defines how the implementation for `trace()` is to be generated
fn totalsum_substructure(cx: &mut ExtCtxt, trait_span: Span,
substr: &Substructure) -> P<ast::Expr> {
let fields = match *substr.fields {
Struct(_, ref fs) | EnumMatching(.., ref fs) => fs,
_ => cx.span_bug(trait_span, "impossible substructure")
};
fields.iter().fold(cx.expr_isize(trait_span, 0), |acc, ref item| {
if attr::contains_name(&item.attrs, sym::ignore) {
acc
} else {
cx.expr_binary(item.span, ast::BinOpKind::Add, acc,
cx.expr_method_call(item.span,
item.self_.clone(),
substr.method_ident,
Vec::new()))
}
})
}

View file

@ -1,76 +0,0 @@
// force-host
#![feature(plugin_registrar)]
#![feature(box_syntax)]
#![feature(rustc_private)]
extern crate syntax;
extern crate syntax_ext;
extern crate syntax_pos;
extern crate rustc;
extern crate rustc_plugin;
use syntax::ast;
use syntax::ext::base::{MultiDecorator, ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::symbol::Symbol;
use syntax_ext::deriving::generic::{cs_fold, TraitDef, MethodDef, combine_substructure};
use syntax_ext::deriving::generic::ty::{Literal, LifetimeBounds, Path, borrowed_explicit_self};
use syntax_pos::Span;
use rustc_plugin::Registry;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
Symbol::intern("derive_TotalSum"),
MultiDecorator(box expand));
reg.register_syntax_extension(
Symbol::intern("derive_Nothing"),
MultiDecorator(box noop));
}
fn noop(_: &mut ExtCtxt, _: Span, _: &ast::MetaItem, _: &Annotatable, _: &mut FnMut(Annotatable)) {}
fn expand(cx: &mut ExtCtxt,
span: Span,
mitem: &ast::MetaItem,
item: &Annotatable,
push: &mut FnMut(Annotatable)) {
let trait_def = TraitDef {
span: span,
attributes: vec![],
path: Path::new_local("TotalSum"),
additional_bounds: vec![],
generics: LifetimeBounds::empty(),
associated_types: vec![],
is_unsafe: false,
supports_unions: false,
methods: vec![
MethodDef {
name: "total_sum",
generics: LifetimeBounds::empty(),
explicit_self: borrowed_explicit_self(),
args: vec![],
ret_ty: Literal(Path::new_local("isize")),
attributes: vec![],
is_unsafe: false,
unify_fieldless_variants: true,
combine_substructure: combine_substructure(box |cx, span, substr| {
let zero = cx.expr_isize(span, 0);
cs_fold(false,
|cx, span, subexpr, field, _| {
cx.expr_binary(span, ast::BinOpKind::Add, subexpr,
cx.expr_method_call(span, field,
ast::Ident::from_str("total_sum"), vec![]))
},
zero,
box |cx, span, _, _| { cx.span_bug(span, "wtf??"); },
cx, span, substr)
}),
},
],
};
trait_def.expand(cx, mitem, item, push)
}

View file

@ -10,11 +10,10 @@ extern crate rustc_plugin;
use std::borrow::ToOwned;
use syntax::ast;
use syntax::ext::hygiene;
use syntax::ext::build::AstBuilder;
use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager, NormalTT};
use syntax::ext::base::{SyntaxExtension, TTMacroExpander, ExtCtxt, MacResult, MacEager};
use syntax::ext::hygiene::Transparency;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use syntax::tokenstream::TokenStream;
@ -29,7 +28,7 @@ impl TTMacroExpander for Expander {
ecx: &'cx mut ExtCtxt,
sp: Span,
_: TokenStream,
_: Option<Span>) -> Box<MacResult+'cx> {
_: Option<Span>) -> Box<dyn MacResult+'cx> {
let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
.collect::<Vec<_>>().join(", ");
MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args)))
@ -40,9 +39,10 @@ impl TTMacroExpander for Expander {
pub fn plugin_registrar(reg: &mut Registry) {
let args = reg.args().to_owned();
reg.register_syntax_extension(Symbol::intern("plugin_args"),
NormalTT {
SyntaxExtension::LegacyBang {
expander: Box::new(Expander { args: args, }),
def_info: None,
transparency: Transparency::SemiTransparent,
allow_internal_unstable: None,
allow_internal_unsafe: false,
local_inner_macros: false,

View file

@ -1,10 +0,0 @@
// aux-build:custom-derive-partial-eq.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(custom_derive_partial_eq)]
#![allow(unused)]
#[derive_CustomPartialEq] // Check that this is not a stability error.
enum E { V1, V2 }
fn main() {}

View file

@ -1,64 +0,0 @@
// aux-build:custom-derive-plugin-attr.rs
// ignore-stage1
#![feature(plugin, rustc_attrs)]
#![plugin(custom_derive_plugin_attr)]
trait TotalSum {
fn total_sum(&self) -> isize;
}
impl TotalSum for isize {
fn total_sum(&self) -> isize {
*self
}
}
struct Seven;
impl TotalSum for Seven {
fn total_sum(&self) -> isize {
7
}
}
#[rustc_derive_TotalSum]
struct Foo {
seven: Seven,
bar: Bar,
baz: isize,
#[ignore]
nan: NaN,
}
#[rustc_derive_TotalSum]
struct Bar {
quux: isize,
bleh: isize,
#[ignore]
nan: NaN2
}
struct NaN;
impl TotalSum for NaN {
fn total_sum(&self) -> isize {
panic!();
}
}
struct NaN2;
pub fn main() {
let v = Foo {
seven: Seven,
bar: Bar {
quux: 9,
bleh: 3,
nan: NaN2
},
baz: 80,
nan: NaN
};
assert_eq!(v.total_sum(), 99);
}

View file

@ -1,49 +0,0 @@
// aux-build:custom-derive-plugin.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(custom_derive_plugin)]
trait TotalSum {
fn total_sum(&self) -> isize;
}
impl TotalSum for isize {
fn total_sum(&self) -> isize {
*self
}
}
struct Seven;
impl TotalSum for Seven {
fn total_sum(&self) -> isize {
7
}
}
#[derive_TotalSum]
struct Foo {
seven: Seven,
bar: Bar,
baz: isize,
}
#[derive_TotalSum]
struct Bar {
quux: isize,
bleh: isize,
}
pub fn main() {
let v = Foo {
seven: Seven,
bar: Bar {
quux: 9,
bleh: 3,
},
baz: 80,
};
assert_eq!(v.total_sum(), 99);
}

View file

@ -1,13 +0,0 @@
#![allow(dead_code)]
// aux-build:custom-derive-plugin.rs
// ignore-stage1
#![feature(plugin)]
#![plugin(custom_derive_plugin)]
#[derive_Nothing]
#[derive_Nothing]
#[derive_Nothing]
struct S;
fn main() {}

View file

@ -0,0 +1,12 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; N]
//~^ ERROR array lengths can't depend on generic parameters
}
fn main() {
let x: [u32; 5] = f::<u32, 5>(3);
assert_eq!(x, [3u32; 5]);
}

View file

@ -0,0 +1,14 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/issue-61336-1.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error: array lengths can't depend on generic parameters
--> $DIR/issue-61336-1.rs:5:9
|
LL | [x; N]
| ^
error: aborting due to previous error

View file

@ -0,0 +1,16 @@
#![feature(const_generics)]
//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
[x; N]
}
fn g<T, const N: usize>(x: T) -> [T; N] {
[x; N]
//~^ ERROR the trait bound `T: std::marker::Copy` is not satisfied [E0277]
}
fn main() {
let x: [u32; 5] = f::<u32, 5>(3);
assert_eq!(x, [3u32; 5]);
}

View file

@ -0,0 +1,18 @@
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
--> $DIR/issue-61336.rs:1:12
|
LL | #![feature(const_generics)]
| ^^^^^^^^^^^^^^
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> $DIR/issue-61336.rs:9:5
|
LL | [x; N]
| ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
= note: the `Copy` trait is required because the repeated element will be copied
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -160,7 +160,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:100:38
|
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
@ -169,7 +169,7 @@ LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:102:29
|
LL | const fn foo30_5(b: bool) { while b { } }
@ -178,7 +178,7 @@ LL | const fn foo30_5(b: bool) { while b { } }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:104:44
|
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
@ -187,7 +187,7 @@ LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:106:44
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }

View file

@ -98,13 +98,13 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
//~^ ERROR casting pointers to ints is unstable
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
//~^ ERROR loops and conditional expressions are not stable in const fn
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
const fn foo30_6() -> bool { let x = true; x }
const fn foo36(a: bool, b: bool) -> bool { a && b }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
//~^ ERROR loops and conditional expressions are not stable in const fn
const fn foo37(a: bool, b: bool) -> bool { a || b }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
//~^ ERROR loops and conditional expressions are not stable in const fn
const fn inc(x: &mut i32) { *x += 1 }
//~^ ERROR mutable references in const fn are unstable

View file

@ -160,7 +160,7 @@ LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:100:38
|
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
@ -169,7 +169,7 @@ LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:102:29
|
LL | const fn foo30_5(b: bool) { while b { } }
@ -178,7 +178,7 @@ LL | const fn foo30_5(b: bool) { while b { } }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:104:44
|
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
@ -187,7 +187,7 @@ LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
= note: for more information, see issue https://github.com/rust-lang/rust/issues/57563
= help: add #![feature(const_fn)] to the crate attributes to enable
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/min_const_fn.rs:106:44
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }

View file

@ -15,7 +15,7 @@ impl Foo {
use self::Foo::*;
match *self {
Prob => 0x1, //~ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
Prob => 0x1, //~ ERROR loops and conditional expressions are not stable in const fn
}
}
}

View file

@ -10,7 +10,7 @@ error[E0019]: constant contains unimplemented expression type
LL | x => 42,
| ^
error[E0723]: `if`, `match`, `&&` and `||` are not stable in const fn
error[E0723]: loops and conditional expressions are not stable in const fn
--> $DIR/single_variant_match_ice.rs:18:13
|
LL | Prob => 0x1,

View file

@ -1,6 +1,9 @@
error: no rules expected the token `enum E { }`
--> $DIR/nonterminal-matching.rs:19:10
|
LL | macro n(a $nt_item b) {
| --------------------- when calling this macro
...
LL | n!(a $nt_item b);
| ^^^^^^^^ no rules expected this token in macro call
...