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:
commit
961a9d6e97
48 changed files with 387 additions and 750 deletions
|
@ -74,8 +74,9 @@ steps:
|
||||||
# images, etc.
|
# images, etc.
|
||||||
- bash: |
|
- bash: |
|
||||||
set -e
|
set -e
|
||||||
|
source src/ci/shared.sh
|
||||||
sudo apt-get install -y python3-setuptools
|
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"
|
echo "##vso[task.prependpath]$HOME/.local/bin"
|
||||||
displayName: Install awscli (Linux)
|
displayName: Install awscli (Linux)
|
||||||
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
|
condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux'))
|
||||||
|
|
|
@ -130,9 +130,9 @@ build.
|
||||||
|
|
||||||
MSVC builds of Rust additionally require an installation of Visual Studio 2017
|
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
|
(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
|
(If you're installing cmake yourself, be careful that “C++ CMake tools for
|
||||||
Windows” doesn't get included under “Individual components”.)
|
Windows” doesn't get included under “Individual components”.)
|
||||||
|
|
|
@ -1495,13 +1495,13 @@ pub trait Iterator {
|
||||||
let mut left: B = Default::default();
|
let mut left: B = Default::default();
|
||||||
let mut right: B = Default::default();
|
let mut right: B = Default::default();
|
||||||
|
|
||||||
for x in self {
|
self.for_each(|x| {
|
||||||
if f(&x) {
|
if f(&x) {
|
||||||
left.extend(Some(x))
|
left.extend(Some(x))
|
||||||
} else {
|
} else {
|
||||||
right.extend(Some(x))
|
right.extend(Some(x))
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
(left, right)
|
(left, right)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5420,7 +5420,7 @@ macro_rules! impl_marker_for {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_marker_for!(BytewiseEquality,
|
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)]
|
#[doc(hidden)]
|
||||||
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
|
unsafe impl<'a, T> TrustedRandomAccess for Iter<'a, T> {
|
||||||
|
|
|
@ -4000,11 +4000,11 @@ impl str {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut s = String::from("Grüße, Jürgen ❤");
|
/// let mut s = String::from("GRÜßE, JÜRGEN ❤");
|
||||||
///
|
///
|
||||||
/// s.make_ascii_lowercase();
|
/// 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")]
|
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||||
pub fn make_ascii_lowercase(&mut self) {
|
pub fn make_ascii_lowercase(&mut self) {
|
||||||
|
|
|
@ -227,13 +227,17 @@ impl OutputType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The type of diagnostics output to generate.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum ErrorOutputType {
|
pub enum ErrorOutputType {
|
||||||
|
/// Output meant for the consumption of humans.
|
||||||
HumanReadable(HumanReadableErrorType),
|
HumanReadable(HumanReadableErrorType),
|
||||||
|
/// Output that's consumed by other tools such as `rustfix` or the `RLS`.
|
||||||
Json {
|
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,
|
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,
|
json_rendered: HumanReadableErrorType,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,7 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||||
|
|
||||||
/// Convenience function for internal use, clients should use one of the
|
/// Convenience function for internal use, clients should use one of the
|
||||||
/// struct_* methods on Handler.
|
/// struct_* methods on Handler.
|
||||||
pub fn new_with_code(handler: &'a Handler,
|
crate fn new_with_code(handler: &'a Handler,
|
||||||
level: Level,
|
level: Level,
|
||||||
code: Option<DiagnosticId>,
|
code: Option<DiagnosticId>,
|
||||||
message: &str)
|
message: &str)
|
||||||
|
|
|
@ -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 Destination::*;
|
||||||
|
|
||||||
use syntax_pos::{SourceFile, Span, MultiSpan};
|
use syntax_pos::{SourceFile, Span, MultiSpan};
|
||||||
|
|
|
@ -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/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||||
|
|
||||||
|
#![feature(crate_visibility_modifier)]
|
||||||
#![allow(unused_attributes)]
|
#![allow(unused_attributes)]
|
||||||
#![cfg_attr(unix, feature(libc))]
|
#![cfg_attr(unix, feature(libc))]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
|
|
@ -614,7 +614,7 @@ impl<'a> CrateLoader<'a> {
|
||||||
match decl {
|
match decl {
|
||||||
ProcMacro::CustomDerive { trait_name, attributes, client } => {
|
ProcMacro::CustomDerive { trait_name, attributes, client } => {
|
||||||
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
||||||
(trait_name, SyntaxExtension::ProcMacroDerive(
|
(trait_name, SyntaxExtension::Derive(
|
||||||
Box::new(ProcMacroDerive {
|
Box::new(ProcMacroDerive {
|
||||||
client,
|
client,
|
||||||
attrs: attrs.clone(),
|
attrs: attrs.clone(),
|
||||||
|
@ -624,13 +624,13 @@ impl<'a> CrateLoader<'a> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ProcMacro::Attr { name, client } => {
|
ProcMacro::Attr { name, client } => {
|
||||||
(name, SyntaxExtension::AttrProcMacro(
|
(name, SyntaxExtension::Attr(
|
||||||
Box::new(AttrProcMacro { client }),
|
Box::new(AttrProcMacro { client }),
|
||||||
root.edition,
|
root.edition,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ProcMacro::Bang { name, client } => {
|
ProcMacro::Bang { name, client } => {
|
||||||
(name, SyntaxExtension::ProcMacro {
|
(name, SyntaxExtension::Bang {
|
||||||
expander: Box::new(BangProcMacro { client }),
|
expander: Box::new(BangProcMacro { client }),
|
||||||
allow_internal_unstable: None,
|
allow_internal_unstable: None,
|
||||||
edition: root.edition,
|
edition: root.edition,
|
||||||
|
|
|
@ -430,7 +430,7 @@ impl cstore::CStore {
|
||||||
use syntax_ext::proc_macro_impl::BangProcMacro;
|
use syntax_ext::proc_macro_impl::BangProcMacro;
|
||||||
|
|
||||||
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
||||||
let ext = SyntaxExtension::ProcMacro {
|
let ext = SyntaxExtension::Bang {
|
||||||
expander: Box::new(BangProcMacro { client }),
|
expander: Box::new(BangProcMacro { client }),
|
||||||
allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
|
allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
|
||||||
edition: data.root.edition,
|
edition: data.root.edition,
|
||||||
|
|
|
@ -299,7 +299,7 @@ fn check_terminator(
|
||||||
|
|
||||||
TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err((
|
TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err((
|
||||||
span,
|
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 => {
|
| TerminatorKind::Abort | TerminatorKind::Unreachable => {
|
||||||
Err((span, "const fn with unreachable code is not stable".into()))
|
Err((span, "const fn with unreachable code is not stable".into()))
|
||||||
|
|
|
@ -4,8 +4,9 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
|
||||||
use rustc::session::Session;
|
use rustc::session::Session;
|
||||||
use rustc::util::nodemap::FxHashMap;
|
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::base::MacroExpanderFn;
|
||||||
|
use syntax::ext::hygiene::Transparency;
|
||||||
use syntax::symbol::{Symbol, sym};
|
use syntax::symbol::{Symbol, sym};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::feature_gate::AttributeType;
|
use syntax::feature_gate::AttributeType;
|
||||||
|
@ -84,47 +85,26 @@ impl<'a> Registry<'a> {
|
||||||
/// Register a syntax extension of any kind.
|
/// Register a syntax extension of any kind.
|
||||||
///
|
///
|
||||||
/// This is the most general hook into `libsyntax`'s expansion behavior.
|
/// 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 {
|
if name == sym::macro_rules {
|
||||||
panic!("user-defined macros may not be named `macro_rules`");
|
panic!("user-defined macros may not be named `macro_rules`");
|
||||||
}
|
}
|
||||||
self.syntax_exts.push((name, match extension {
|
if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension {
|
||||||
NormalTT {
|
*def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
|
||||||
expander,
|
}
|
||||||
def_info: _,
|
self.syntax_exts.push((name, extension));
|
||||||
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,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a macro of the usual kind.
|
/// Register a macro of the usual kind.
|
||||||
///
|
///
|
||||||
/// This is a convenience wrapper for `register_syntax_extension`.
|
/// 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.
|
/// and also takes care of interning the macro's name.
|
||||||
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
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),
|
expander: Box::new(expander),
|
||||||
def_info: None,
|
def_info: None,
|
||||||
|
transparency: Transparency::SemiTransparent,
|
||||||
allow_internal_unstable: None,
|
allow_internal_unstable: None,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
local_inner_macros: false,
|
local_inner_macros: false,
|
||||||
|
|
|
@ -242,8 +242,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||||
fn check_unused_macros(&self) {
|
fn check_unused_macros(&self) {
|
||||||
for did in self.unused_macros.iter() {
|
for did in self.unused_macros.iter() {
|
||||||
let id_span = match *self.macro_map[did] {
|
let id_span = match *self.macro_map[did] {
|
||||||
SyntaxExtension::NormalTT { def_info, .. } |
|
SyntaxExtension::LegacyBang { def_info, .. } => def_info,
|
||||||
SyntaxExtension::DeclMacro { def_info, .. } => def_info,
|
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some((id, span)) = id_span {
|
if let Some((id, span)) = id_span {
|
||||||
|
@ -587,7 +586,7 @@ impl<'a> Resolver<'a> {
|
||||||
match self.resolve_macro_to_res(derive, MacroKind::Derive,
|
match self.resolve_macro_to_res(derive, MacroKind::Derive,
|
||||||
&parent_scope, true, force) {
|
&parent_scope, true, force) {
|
||||||
Ok((_, ext)) => {
|
Ok((_, ext)) => {
|
||||||
if let SyntaxExtension::ProcMacroDerive(_, helpers, _) = &*ext {
|
if let SyntaxExtension::Derive(_, helpers, _) = &*ext {
|
||||||
if helpers.contains(&ident.name) {
|
if helpers.contains(&ident.name) {
|
||||||
let binding =
|
let binding =
|
||||||
(Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
(Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
|
||||||
|
|
|
@ -2155,6 +2155,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
|
||||||
result_ty
|
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(
|
pub fn ast_const_to_const(
|
||||||
&self,
|
&self,
|
||||||
ast_const: &hir::AnonConst,
|
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 Some(def_id) = self.const_param_def_id(expr) {
|
||||||
if let hir::QPath::Resolved(_, ref path) = qpath {
|
// Find the name and index of the const parameter by indexing the generics of the
|
||||||
if let Res::Def(DefKind::ConstParam, def_id) = path.res {
|
// parent item and construct a `ParamConst`.
|
||||||
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
|
let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
|
||||||
let item_id = tcx.hir().get_parent_node(node_id);
|
let item_id = tcx.hir().get_parent_node(node_id);
|
||||||
let item_def_id = tcx.hir().local_def_id(item_id);
|
let item_def_id = tcx.hir().local_def_id(item_id);
|
||||||
let generics = tcx.generics_of(item_def_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 index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
|
||||||
let name = tcx.hir().name(node_id).as_interned_str();
|
let name = tcx.hir().name(node_id).as_interned_str();
|
||||||
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
|
const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
tcx.mk_const(const_)
|
tcx.mk_const(const_)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2504,6 +2504,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
ty
|
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> {
|
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)
|
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) => {
|
ExprKind::Repeat(ref element, ref count) => {
|
||||||
let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
|
let count_def_id = tcx.hir().local_def_id_from_hir_id(count.hir_id);
|
||||||
let param_env = ty::ParamEnv::empty();
|
let count = if self.const_param_def_id(count).is_some() {
|
||||||
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
|
Ok(self.to_const(count, self.tcx.type_of(count_def_id)))
|
||||||
let instance = ty::Instance::resolve(
|
} else {
|
||||||
tcx.global_tcx(),
|
let param_env = ty::ParamEnv::empty();
|
||||||
param_env,
|
let substs = InternalSubsts::identity_for_item(tcx.global_tcx(), count_def_id);
|
||||||
count_def_id,
|
let instance = ty::Instance::resolve(
|
||||||
substs,
|
tcx.global_tcx(),
|
||||||
).unwrap();
|
param_env,
|
||||||
let global_id = GlobalId {
|
count_def_id,
|
||||||
instance,
|
substs,
|
||||||
promoted: None
|
).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 {
|
let uty = match expected {
|
||||||
ExpectHasType(uty) => {
|
ExpectHasType(uty) => {
|
||||||
|
|
|
@ -471,7 +471,7 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE
|
||||||
}
|
}
|
||||||
LoadedMacro::ProcMacro(ext) => {
|
LoadedMacro::ProcMacro(ext) => {
|
||||||
let helpers = match &*ext {
|
let helpers = match &*ext {
|
||||||
&SyntaxExtension::ProcMacroDerive(_, ref syms, ..) => { syms.clean(cx) }
|
&SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) }
|
||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||||
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
|
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
|
||||||
// skip proc-macro stubs, they'll cause `get_macro` to crash
|
// skip proc-macro stubs, they'll cause `get_macro` to crash
|
||||||
} else {
|
} 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")));
|
return Some(res.map_id(|_| panic!("unexpected id")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,8 +482,8 @@ mod prim_pointer { }
|
||||||
/// an array. Indeed, this provides most of the API for working with arrays.
|
/// an array. Indeed, this provides most of the API for working with arrays.
|
||||||
/// Slices have a dynamic size and do not coerce to 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]
|
/// You can move elements out of an array with a slice pattern. If you want
|
||||||
/// for an alternative.
|
/// one element, see [`mem::replace`][replace].
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -525,6 +525,16 @@ mod prim_pointer { }
|
||||||
/// for x in &array { }
|
/// 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
|
/// [slice]: primitive.slice.html
|
||||||
/// [copy]: marker/trait.Copy.html
|
/// [copy]: marker/trait.Copy.html
|
||||||
/// [clone]: clone/trait.Clone.html
|
/// [clone]: clone/trait.Clone.html
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
pub use SyntaxExtension::*;
|
use crate::ast::{self, Attribute, Name, PatKind};
|
||||||
|
|
||||||
use crate::ast::{self, Attribute, Name, PatKind, MetaItem};
|
|
||||||
use crate::attr::HasAttrs;
|
use crate::attr::HasAttrs;
|
||||||
use crate::source_map::{SourceMap, Spanned, respan};
|
use crate::source_map::{SourceMap, Spanned, respan};
|
||||||
use crate::edition::Edition;
|
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.
|
// `meta_item` is the annotation, and `item` is the item being modified.
|
||||||
// FIXME Decorators should follow the same pattern too.
|
// FIXME Decorators should follow the same pattern too.
|
||||||
pub trait MultiItemModifier {
|
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
|
// Use a macro because forwarding to a simple function has type system issues
|
||||||
macro_rules! make_stmts_default {
|
macro_rules! make_stmts_default {
|
||||||
($me:expr) => {
|
($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.
|
/// Represents different kinds of macro invocations that can be resolved.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||||
pub enum MacroKind {
|
pub enum MacroKind {
|
||||||
|
@ -606,129 +550,116 @@ impl MacroKind {
|
||||||
|
|
||||||
/// An enum representing the different kinds of syntax extensions.
|
/// An enum representing the different kinds of syntax extensions.
|
||||||
pub enum SyntaxExtension {
|
pub enum SyntaxExtension {
|
||||||
/// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
|
/// A token-based function-like macro.
|
||||||
NonMacroAttr { mark_used: bool },
|
Bang {
|
||||||
|
/// An expander with signature TokenStream -> TokenStream.
|
||||||
/// 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 {
|
|
||||||
expander: Box<dyn ProcMacro + sync::Sync + sync::Send>,
|
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]>>,
|
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||||
|
/// Edition of the crate in which this macro is defined.
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
|
/// An AST-based function-like macro.
|
||||||
/// The first TokenSteam is the attribute, the second is the annotated item.
|
LegacyBang {
|
||||||
/// Allows modification of the input items and adding new items, similar to
|
/// An expander with signature TokenStream -> AST.
|
||||||
/// 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 {
|
|
||||||
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||||
|
/// Some info about the macro's definition point.
|
||||||
def_info: Option<(ast::NodeId, Span)>,
|
def_info: Option<(ast::NodeId, Span)>,
|
||||||
/// Whether the contents of the macro can
|
/// Hygienic properties of identifiers produced by this macro.
|
||||||
/// directly use `#[unstable]` things.
|
transparency: Transparency,
|
||||||
///
|
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||||
/// Only allows things that require a feature gate in the given whitelist
|
|
||||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||||
/// Whether the contents of the macro can use `unsafe`
|
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||||
/// without triggering the `unsafe_code` lint.
|
|
||||||
allow_internal_unsafe: bool,
|
allow_internal_unsafe: bool,
|
||||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
|
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||||
/// for a given macro.
|
|
||||||
local_inner_macros: bool,
|
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)>,
|
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,
|
edition: Edition,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A function-like syntax extension that has an extra ident before
|
/// A token-based attribute macro.
|
||||||
/// the block.
|
Attr(
|
||||||
IdentTT {
|
/// An expander with signature (TokenStream, TokenStream) -> TokenStream.
|
||||||
expander: Box<dyn IdentMacroExpander + sync::Sync + sync::Send>,
|
/// The first TokenSteam is the attribute itself, the second is the annotated item.
|
||||||
span: Option<Span>,
|
/// The produced TokenSteam replaces the input TokenSteam.
|
||||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
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.
|
/// A token-based derive macro.
|
||||||
/// The input is the annotated item.
|
Derive(
|
||||||
/// Allows generating code to implement a Trait for a given struct
|
/// An expander with signature TokenStream -> TokenStream (not yet).
|
||||||
/// or enum item.
|
/// The produced TokenSteam is appended to the input TokenSteam.
|
||||||
ProcMacroDerive(Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||||
Vec<Symbol> /* inert attribute names */, Edition),
|
/// 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.
|
/// An AST-based derive macro.
|
||||||
BuiltinDerive(BuiltinDeriveFn),
|
LegacyDerive(
|
||||||
|
/// An expander with signature AST -> AST.
|
||||||
/// A declarative macro, e.g., `macro m() {}`.
|
/// The produced AST fragment is appended to the input AST fragment.
|
||||||
DeclMacro {
|
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||||
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
),
|
||||||
def_info: Option<(ast::NodeId, Span)>,
|
|
||||||
is_transparent: bool,
|
|
||||||
edition: Edition,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyntaxExtension {
|
impl SyntaxExtension {
|
||||||
/// Returns which kind of macro calls this syntax extension.
|
/// Returns which kind of macro calls this syntax extension.
|
||||||
pub fn kind(&self) -> MacroKind {
|
pub fn kind(&self) -> MacroKind {
|
||||||
match *self {
|
match *self {
|
||||||
SyntaxExtension::DeclMacro { .. } |
|
SyntaxExtension::Bang { .. } |
|
||||||
SyntaxExtension::NormalTT { .. } |
|
SyntaxExtension::LegacyBang { .. } => MacroKind::Bang,
|
||||||
SyntaxExtension::IdentTT { .. } |
|
SyntaxExtension::Attr(..) |
|
||||||
SyntaxExtension::ProcMacro { .. } =>
|
SyntaxExtension::LegacyAttr(..) |
|
||||||
MacroKind::Bang,
|
SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr,
|
||||||
SyntaxExtension::NonMacroAttr { .. } |
|
SyntaxExtension::Derive(..) |
|
||||||
SyntaxExtension::MultiDecorator(..) |
|
SyntaxExtension::LegacyDerive(..) => MacroKind::Derive,
|
||||||
SyntaxExtension::MultiModifier(..) |
|
|
||||||
SyntaxExtension::AttrProcMacro(..) =>
|
|
||||||
MacroKind::Attr,
|
|
||||||
SyntaxExtension::ProcMacroDerive(..) |
|
|
||||||
SyntaxExtension::BuiltinDerive(..) =>
|
|
||||||
MacroKind::Derive,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_transparency(&self) -> Transparency {
|
pub fn default_transparency(&self) -> Transparency {
|
||||||
match *self {
|
match *self {
|
||||||
SyntaxExtension::ProcMacro { .. } |
|
SyntaxExtension::LegacyBang { transparency, .. } => transparency,
|
||||||
SyntaxExtension::AttrProcMacro(..) |
|
SyntaxExtension::Bang { .. } |
|
||||||
SyntaxExtension::ProcMacroDerive(..) |
|
SyntaxExtension::Attr(..) |
|
||||||
SyntaxExtension::DeclMacro { is_transparent: false, .. } => Transparency::Opaque,
|
SyntaxExtension::Derive(..) |
|
||||||
SyntaxExtension::DeclMacro { is_transparent: true, .. } => Transparency::Transparent,
|
SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque,
|
||||||
_ => Transparency::SemiTransparent,
|
SyntaxExtension::LegacyAttr(..) |
|
||||||
|
SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn edition(&self, default_edition: Edition) -> Edition {
|
pub fn edition(&self, default_edition: Edition) -> Edition {
|
||||||
match *self {
|
match *self {
|
||||||
SyntaxExtension::NormalTT { edition, .. } |
|
SyntaxExtension::Bang { edition, .. } |
|
||||||
SyntaxExtension::DeclMacro { edition, .. } |
|
SyntaxExtension::LegacyBang { edition, .. } |
|
||||||
SyntaxExtension::ProcMacro { edition, .. } |
|
SyntaxExtension::Attr(.., edition) |
|
||||||
SyntaxExtension::AttrProcMacro(.., edition) |
|
SyntaxExtension::Derive(.., edition) => edition,
|
||||||
SyntaxExtension::ProcMacroDerive(.., edition) => edition,
|
|
||||||
// Unstable legacy stuff
|
// Unstable legacy stuff
|
||||||
SyntaxExtension::NonMacroAttr { .. } |
|
SyntaxExtension::NonMacroAttr { .. } |
|
||||||
SyntaxExtension::IdentTT { .. } |
|
SyntaxExtension::LegacyAttr(..) |
|
||||||
SyntaxExtension::MultiDecorator(..) |
|
SyntaxExtension::LegacyDerive(..) => default_edition,
|
||||||
SyntaxExtension::MultiModifier(..) |
|
|
||||||
SyntaxExtension::BuiltinDerive(..) => default_edition,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,7 +389,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
let item = match self.cx.resolver.resolve_macro_path(
|
let item = match self.cx.resolver.resolve_macro_path(
|
||||||
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
|
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
|
||||||
Ok(ext) => match *ext {
|
Ok(ext) => match *ext {
|
||||||
BuiltinDerive(..) => item_with_markers.clone(),
|
SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(),
|
||||||
_ => item.clone(),
|
_ => item.clone(),
|
||||||
},
|
},
|
||||||
_ => item.clone(),
|
_ => item.clone(),
|
||||||
|
@ -548,7 +548,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
_ => unreachable!(),
|
_ => 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,
|
// Macro attrs are always used when expanded,
|
||||||
// non-macro attrs are considered used when the field says so.
|
// non-macro attrs are considered used when the field says so.
|
||||||
attr::mark_used(&attr);
|
attr::mark_used(&attr);
|
||||||
|
@ -564,26 +564,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
});
|
});
|
||||||
|
|
||||||
match *ext {
|
match *ext {
|
||||||
NonMacroAttr { .. } => {
|
SyntaxExtension::NonMacroAttr { .. } => {
|
||||||
attr::mark_known(&attr);
|
attr::mark_known(&attr);
|
||||||
item.visit_attrs(|attrs| attrs.push(attr));
|
item.visit_attrs(|attrs| attrs.push(attr));
|
||||||
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
|
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)
|
let meta = attr.parse_meta(self.cx.parse_sess)
|
||||||
.map_err(|mut e| { e.emit(); }).ok()?;
|
.map_err(|mut e| { e.emit(); }).ok()?;
|
||||||
let item = mac.expand(self.cx, attr.span, &meta, item);
|
let item = mac.expand(self.cx, attr.span, &meta, item);
|
||||||
Some(invoc.fragment_kind.expect_from_annotatables(item))
|
Some(invoc.fragment_kind.expect_from_annotatables(item))
|
||||||
}
|
}
|
||||||
MultiDecorator(ref mac) => {
|
SyntaxExtension::Attr(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, ..) => {
|
|
||||||
self.gate_proc_macro_attr_item(attr.span, &item);
|
self.gate_proc_macro_attr_item(attr.span, &item);
|
||||||
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
|
||||||
Annotatable::Item(item) => token::NtItem(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);
|
self.gate_proc_macro_expansion(attr.span, &res);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
ProcMacroDerive(..) | BuiltinDerive(..) => {
|
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||||
self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
|
self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
invoc.fragment_kind.dummy(attr.span)
|
invoc.fragment_kind.dummy(attr.span)
|
||||||
|
@ -755,17 +747,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let opt_expanded = match *ext {
|
let opt_expanded = match *ext {
|
||||||
DeclMacro { ref expander, def_info, edition, .. } => {
|
SyntaxExtension::LegacyBang {
|
||||||
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 {
|
|
||||||
ref expander,
|
ref expander,
|
||||||
def_info,
|
def_info,
|
||||||
ref allow_internal_unstable,
|
ref allow_internal_unstable,
|
||||||
|
@ -773,6 +755,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
local_inner_macros,
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition,
|
edition,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
||||||
allow_internal_unstable.clone(),
|
allow_internal_unstable.clone(),
|
||||||
|
@ -791,43 +774,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => {
|
SyntaxExtension::Attr(..) |
|
||||||
if ident.name == kw::Invalid {
|
SyntaxExtension::LegacyAttr(..) |
|
||||||
self.cx.span_err(path.span,
|
SyntaxExtension::NonMacroAttr { .. } => {
|
||||||
&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 { .. } => {
|
|
||||||
self.cx.span_err(path.span,
|
self.cx.span_err(path.span,
|
||||||
&format!("`{}` can only be used in attributes", path));
|
&format!("`{}` can only be used in attributes", path));
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
kind.dummy(span)
|
kind.dummy(span)
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcMacroDerive(..) | BuiltinDerive(..) => {
|
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||||
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
|
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
kind.dummy(span)
|
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 {
|
if ident.name != kw::Invalid {
|
||||||
let msg =
|
let msg =
|
||||||
format!("macro {}! expects no ident argument, given '{}'", path, ident);
|
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),
|
edition: ext.edition(self.cx.parse_sess.edition),
|
||||||
};
|
};
|
||||||
|
|
||||||
match *ext {
|
match ext {
|
||||||
ProcMacroDerive(ref ext, ..) => {
|
SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => {
|
||||||
invoc.expansion_data.mark.set_expn_info(expn_info);
|
let meta = match ext {
|
||||||
let span = span.with_ctxt(self.cx.backtrace());
|
SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this
|
||||||
let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
|
path: Path::from_ident(Ident::invalid()),
|
||||||
path: Path::from_ident(Ident::invalid()),
|
span: DUMMY_SP,
|
||||||
span: DUMMY_SP,
|
node: ast::MetaItemKind::Word,
|
||||||
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);
|
invoc.expansion_data.mark.set_expn_info(expn_info);
|
||||||
let span = span.with_ctxt(self.cx.backtrace());
|
let span = span.with_ctxt(self.cx.backtrace());
|
||||||
let mut items = Vec::new();
|
let items = expander.expand(self.cx, span, &meta, item);
|
||||||
func(self.cx, span, &attr.meta()?, &item, &mut |a| items.push(a));
|
|
||||||
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
Some(invoc.fragment_kind.expect_from_annotatables(items))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{ast, attr};
|
use crate::{ast, attr};
|
||||||
use crate::edition::Edition;
|
use crate::edition::Edition;
|
||||||
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
|
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander};
|
||||||
use crate::ext::base::{NormalTT, TTMacroExpander};
|
|
||||||
use crate::ext::expand::{AstFragment, AstFragmentKind};
|
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::{Success, Error, Failure};
|
||||||
use crate::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
use crate::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||||
use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
|
use crate::ext::tt::macro_parser::{parse, parse_failure_msg};
|
||||||
|
@ -374,66 +374,66 @@ pub fn compile(
|
||||||
valid,
|
valid,
|
||||||
});
|
});
|
||||||
|
|
||||||
if body.legacy {
|
let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
|
||||||
let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable)
|
Transparency::Transparent
|
||||||
.map(|attr| attr
|
} else if body.legacy {
|
||||||
.meta_item_list()
|
Transparency::SemiTransparent
|
||||||
.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,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
let is_transparent = attr::contains_name(&def.attrs, sym::rustc_transparent_macro);
|
Transparency::Opaque
|
||||||
|
};
|
||||||
|
|
||||||
SyntaxExtension::DeclMacro {
|
let allow_internal_unstable = attr::find_by_name(&def.attrs, sym::allow_internal_unstable)
|
||||||
expander,
|
.map(|attr| attr
|
||||||
def_info: Some((def.id, def.span)),
|
.meta_item_list()
|
||||||
is_transparent,
|
.map(|list| list.iter()
|
||||||
edition,
|
.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,
|
fn check_lhs_nt_follows(sess: &ParseSess,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! The compiler code necessary to implement the `#[derive]` extensions.
|
//! The compiler code necessary to implement the `#[derive]` extensions.
|
||||||
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use syntax::ast;
|
use syntax::ast::{self, MetaItem};
|
||||||
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver};
|
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier};
|
||||||
use syntax::ext::build::AstBuilder;
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
|
@ -39,9 +39,25 @@ pub mod partial_ord;
|
||||||
#[path="cmp/ord.rs"]
|
#[path="cmp/ord.rs"]
|
||||||
pub mod ord;
|
pub mod ord;
|
||||||
|
|
||||||
|
|
||||||
pub mod generic;
|
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 {
|
macro_rules! derive_traits {
|
||||||
($( $name:expr => $func:path, )+) => {
|
($( $name:expr => $func:path, )+) => {
|
||||||
pub fn is_builtin_trait(name: ast::Name) -> bool {
|
pub fn is_builtin_trait(name: ast::Name) -> bool {
|
||||||
|
@ -55,7 +71,7 @@ macro_rules! derive_traits {
|
||||||
$(
|
$(
|
||||||
resolver.add_builtin(
|
resolver.add_builtin(
|
||||||
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
|
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
|
||||||
Lrc::new(SyntaxExtension::BuiltinDerive($func))
|
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func))))
|
||||||
);
|
);
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,9 @@ pub mod proc_macro_impl;
|
||||||
|
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use syntax::ast;
|
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::edition::Edition;
|
||||||
use syntax::symbol::{sym, Symbol};
|
use syntax::symbol::{sym, Symbol};
|
||||||
|
|
||||||
|
@ -57,9 +59,10 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||||
macro_rules! register {
|
macro_rules! register {
|
||||||
($( $name:ident: $f:expr, )*) => { $(
|
($( $name:ident: $f:expr, )*) => { $(
|
||||||
register(Symbol::intern(stringify!($name)),
|
register(Symbol::intern(stringify!($name)),
|
||||||
NormalTT {
|
SyntaxExtension::LegacyBang {
|
||||||
expander: Box::new($f as MacroExpanderFn),
|
expander: Box::new($f as MacroExpanderFn),
|
||||||
def_info: None,
|
def_info: None,
|
||||||
|
transparency: Transparency::SemiTransparent,
|
||||||
allow_internal_unstable: None,
|
allow_internal_unstable: None,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
local_inner_macros: false,
|
local_inner_macros: false,
|
||||||
|
@ -94,15 +97,16 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||||
assert: assert::expand_assert,
|
assert: assert::expand_assert,
|
||||||
}
|
}
|
||||||
|
|
||||||
register(sym::test_case, MultiModifier(Box::new(test_case::expand)));
|
register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand)));
|
||||||
register(sym::test, MultiModifier(Box::new(test::expand_test)));
|
register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test)));
|
||||||
register(sym::bench, MultiModifier(Box::new(test::expand_bench)));
|
register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench)));
|
||||||
|
|
||||||
// format_args uses `unstable` things internally.
|
// format_args uses `unstable` things internally.
|
||||||
register(Symbol::intern("format_args"),
|
register(Symbol::intern("format_args"),
|
||||||
NormalTT {
|
SyntaxExtension::LegacyBang {
|
||||||
expander: Box::new(format::expand_format_args),
|
expander: Box::new(format::expand_format_args),
|
||||||
def_info: None,
|
def_info: None,
|
||||||
|
transparency: Transparency::SemiTransparent,
|
||||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
local_inner_macros: false,
|
local_inner_macros: false,
|
||||||
|
@ -110,9 +114,10 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||||
edition,
|
edition,
|
||||||
});
|
});
|
||||||
register(sym::format_args_nl,
|
register(sym::format_args_nl,
|
||||||
NormalTT {
|
SyntaxExtension::LegacyBang {
|
||||||
expander: Box::new(format::expand_format_args_nl),
|
expander: Box::new(format::expand_format_args_nl),
|
||||||
def_info: None,
|
def_info: None,
|
||||||
|
transparency: Transparency::SemiTransparent,
|
||||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
local_inner_macros: false,
|
local_inner_macros: false,
|
||||||
|
|
|
@ -8,13 +8,13 @@ use std::intrinsics::exact_div;
|
||||||
// CHECK-LABEL: @exact_sdiv
|
// CHECK-LABEL: @exact_sdiv
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 {
|
pub unsafe fn exact_sdiv(x: i32, y: i32) -> i32 {
|
||||||
// CHECK: sdiv exact
|
// CHECK: sdiv exact
|
||||||
exact_div(x, y)
|
exact_div(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @exact_udiv
|
// CHECK-LABEL: @exact_udiv
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 {
|
pub unsafe fn exact_udiv(x: u32, y: u32) -> u32 {
|
||||||
// CHECK: udiv exact
|
// CHECK: udiv exact
|
||||||
exact_div(x, y)
|
exact_div(x, y)
|
||||||
}
|
}
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -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()))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -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)
|
|
||||||
}
|
|
|
@ -10,11 +10,10 @@ extern crate rustc_plugin;
|
||||||
|
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::ext::hygiene;
|
|
||||||
use syntax::ext::build::AstBuilder;
|
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::print::pprust;
|
||||||
use syntax::ptr::P;
|
|
||||||
use syntax::symbol::Symbol;
|
use syntax::symbol::Symbol;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
use syntax::tokenstream::TokenStream;
|
use syntax::tokenstream::TokenStream;
|
||||||
|
@ -29,7 +28,7 @@ impl TTMacroExpander for Expander {
|
||||||
ecx: &'cx mut ExtCtxt,
|
ecx: &'cx mut ExtCtxt,
|
||||||
sp: Span,
|
sp: Span,
|
||||||
_: TokenStream,
|
_: 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))
|
let args = self.args.iter().map(|i| pprust::meta_list_item_to_string(i))
|
||||||
.collect::<Vec<_>>().join(", ");
|
.collect::<Vec<_>>().join(", ");
|
||||||
MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args)))
|
MacEager::expr(ecx.expr_str(sp, Symbol::intern(&args)))
|
||||||
|
@ -40,9 +39,10 @@ impl TTMacroExpander for Expander {
|
||||||
pub fn plugin_registrar(reg: &mut Registry) {
|
pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
let args = reg.args().to_owned();
|
let args = reg.args().to_owned();
|
||||||
reg.register_syntax_extension(Symbol::intern("plugin_args"),
|
reg.register_syntax_extension(Symbol::intern("plugin_args"),
|
||||||
NormalTT {
|
SyntaxExtension::LegacyBang {
|
||||||
expander: Box::new(Expander { args: args, }),
|
expander: Box::new(Expander { args: args, }),
|
||||||
def_info: None,
|
def_info: None,
|
||||||
|
transparency: Transparency::SemiTransparent,
|
||||||
allow_internal_unstable: None,
|
allow_internal_unstable: None,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
local_inner_macros: false,
|
local_inner_macros: false,
|
||||||
|
|
|
@ -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() {}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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() {}
|
|
12
src/test/ui/const-generics/issue-61336-1.rs
Normal file
12
src/test/ui/const-generics/issue-61336-1.rs
Normal 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]);
|
||||||
|
}
|
14
src/test/ui/const-generics/issue-61336-1.stderr
Normal file
14
src/test/ui/const-generics/issue-61336-1.stderr
Normal 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
|
||||||
|
|
16
src/test/ui/const-generics/issue-61336.rs
Normal file
16
src/test/ui/const-generics/issue-61336.rs
Normal 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]);
|
||||||
|
}
|
18
src/test/ui/const-generics/issue-61336.stderr
Normal file
18
src/test/ui/const-generics/issue-61336.stderr
Normal 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`.
|
|
@ -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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:100:38
|
||||||
|
|
|
|
||||||
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:102:29
|
||||||
|
|
|
|
||||||
LL | const fn foo30_5(b: bool) { while b { } }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:104:44
|
||||||
|
|
|
|
||||||
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:106:44
|
||||||
|
|
|
|
||||||
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
|
||||||
|
|
|
@ -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 } }
|
const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
|
||||||
//~^ ERROR casting pointers to ints is unstable
|
//~^ ERROR casting pointers to ints is unstable
|
||||||
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
|
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_5(b: bool) { while b { } } //~ ERROR not stable in const fn
|
||||||
const fn foo30_6() -> bool { let x = true; x }
|
const fn foo30_6() -> bool { let x = true; x }
|
||||||
const fn foo36(a: bool, b: bool) -> bool { a && b }
|
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 }
|
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 }
|
const fn inc(x: &mut i32) { *x += 1 }
|
||||||
//~^ ERROR mutable references in const fn are unstable
|
//~^ ERROR mutable references in const fn are unstable
|
||||||
|
|
||||||
|
|
|
@ -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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:100:38
|
||||||
|
|
|
|
||||||
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:102:29
|
||||||
|
|
|
|
||||||
LL | const fn foo30_5(b: bool) { while b { } }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:104:44
|
||||||
|
|
|
|
||||||
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
|
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
|
= 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
|
= 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
|
--> $DIR/min_const_fn.rs:106:44
|
||||||
|
|
|
|
||||||
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
|
||||||
|
|
|
@ -15,7 +15,7 @@ impl Foo {
|
||||||
use self::Foo::*;
|
use self::Foo::*;
|
||||||
|
|
||||||
match *self {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ error[E0019]: constant contains unimplemented expression type
|
||||||
LL | x => 42,
|
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
|
--> $DIR/single_variant_match_ice.rs:18:13
|
||||||
|
|
|
|
||||||
LL | Prob => 0x1,
|
LL | Prob => 0x1,
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error: no rules expected the token `enum E { }`
|
error: no rules expected the token `enum E { }`
|
||||||
--> $DIR/nonterminal-matching.rs:19:10
|
--> $DIR/nonterminal-matching.rs:19:10
|
||||||
|
|
|
|
||||||
|
LL | macro n(a $nt_item b) {
|
||||||
|
| --------------------- when calling this macro
|
||||||
|
...
|
||||||
LL | n!(a $nt_item b);
|
LL | n!(a $nt_item b);
|
||||||
| ^^^^^^^^ no rules expected this token in macro call
|
| ^^^^^^^^ no rules expected this token in macro call
|
||||||
...
|
...
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue