Auto merge of #62580 - Centril:rollup-remihe0, r=Centril

Rollup of 7 pull requests

Successful merges:

 - #61665 (core: check for pointer equality when comparing Eq slices)
 - #61923 (Prerequisites from dep graph refactoring #2)
 - #62270 (Move async-await tests from run-pass to ui)
 - #62425 (filedesc: don't use ioctl(FIOCLEX) on Linux)
 - #62476 (Continue refactoring macro expansion and resolution)
 - #62519 (Regression test for HRTB bug (issue 30786).)
 - #62557 (Fix typo in libcore/intrinsics.rs)

Failed merges:

r? @ghost
This commit is contained in:
bors
2019-07-11 04:45:15 +00:00
94 changed files with 1342 additions and 1146 deletions
@@ -98,7 +98,8 @@ application of these fields based on a variety of attributes when using
`crate_local`) or matching against a particular method. Currently used
for `try`.
- `from_desugaring`: usable both as boolean (whether the flag is present)
or matching against a particular desugaring.
or matching against a particular desugaring. The desugaring is identified
with its variant name in the `DesugaringKind` enum.
For example, the `Iterator` trait can be annotated in the following way:
+2 -1
View File
@@ -705,7 +705,8 @@
they should be used through stabilized interfaces \
in the rest of the standard library",
issue = "0")]
#[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUnint instead",
#[rustc_deprecated(reason = "no longer used by rustc, will be removed - use MaybeUninit \
instead",
since = "1.38.0")]
pub fn init<T>() -> T;
+3
View File
@@ -1244,12 +1244,14 @@ mod builtin {
/// Attribute macro applied to a function to turn it into a unit test.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
pub macro test($item:item) { /* compiler built-in */ }
/// Attribute macro applied to a function to turn it into a benchmark test.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
pub macro bench($item:item) { /* compiler built-in */ }
@@ -1257,6 +1259,7 @@ mod builtin {
/// An implementation detail of the `#[test]` and `#[bench]` macros.
#[unstable(feature = "custom_test_frameworks", issue = "50297",
reason = "custom test frameworks are an unstable feature")]
#[allow_internal_unstable(test, rustc_attrs)]
#[rustc_builtin_macro]
#[rustc_macro_transparency = "semitransparent"]
pub macro test_case($item:item) { /* compiler built-in */ }
+2 -2
View File
@@ -8,12 +8,12 @@
#[rustc_on_unimplemented(
on(all(
any(from_method="from_error", from_method="from_ok"),
from_desugaring="?"),
from_desugaring="QuestionMark"),
message="the `?` operator can only be used in a \
function that returns `Result` or `Option` \
(or another type that implements `{Try}`)",
label="cannot use the `?` operator in a function that returns `{Self}`"),
on(all(from_method="into_result", from_desugaring="?"),
on(all(from_method="into_result", from_desugaring="QuestionMark"),
message="the `?` operator can only be applied to values \
that implement `{Try}`",
label="the `?` operator cannot be applied to type `{Self}`")
+17 -6
View File
@@ -5342,13 +5342,24 @@ impl<A, B> SlicePartialEq<B> for [A]
return false;
}
for i in 0..self.len() {
if !self[i].eq(&other[i]) {
return false;
}
self.iter().zip(other.iter()).all(|(x, y)| x == y)
}
}
// Use an equal-pointer optimization when types are `Eq`
impl<A> SlicePartialEq<A> for [A]
where A: PartialEq<A> + Eq
{
default fn equal(&self, other: &[A]) -> bool {
if self.len() != other.len() {
return false;
}
true
if self.as_ptr() == other.as_ptr() {
return true;
}
self.iter().zip(other.iter()).all(|(x, y)| x == y)
}
}
@@ -5457,7 +5468,7 @@ fn compare(&self, other: &[u8]) -> Ordering {
#[doc(hidden)]
/// Trait implemented for types that can be compared for equality using
/// their bytewise representation
trait BytewiseEquality { }
trait BytewiseEquality: Eq + Copy { }
macro_rules! impl_marker_for {
($traitname:ident, $($ty:ty)*) => {
+52 -36
View File
@@ -7,6 +7,7 @@
use std::env;
use std::hash::Hash;
use std::collections::hash_map::Entry;
use std::mem;
use crate::ty::{self, TyCtxt};
use crate::util::common::{ProfileQueriesMsg, profq_msg};
use parking_lot::{Mutex, Condvar};
@@ -61,11 +62,11 @@ struct DepGraphData {
colors: DepNodeColorMap,
/// A set of loaded diagnostics that have been emitted.
emitted_diagnostics: Mutex<FxHashSet<DepNodeIndex>>,
/// A set of loaded diagnostics that is in the progress of being emitted.
emitting_diagnostics: Mutex<FxHashSet<DepNodeIndex>>,
/// Used to wait for diagnostics to be emitted.
emitted_diagnostics_cond_var: Condvar,
emitting_diagnostics_cond_var: Condvar,
/// When we load, there may be `.o` files, cached MIR, or other such
/// things available to us. If we find that they are not dirty, we
@@ -99,8 +100,8 @@ pub fn new(prev_graph: PreviousDepGraph,
previous_work_products: prev_work_products,
dep_node_debug: Default::default(),
current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
emitted_diagnostics: Default::default(),
emitted_diagnostics_cond_var: Condvar::new(),
emitting_diagnostics: Default::default(),
emitting_diagnostics_cond_var: Condvar::new(),
previous: prev_graph,
colors: DepNodeColorMap::new(prev_graph_node_count),
loaded_from_cache: Default::default(),
@@ -744,7 +745,7 @@ fn try_mark_previous_green<'tcx>(
// There may be multiple threads trying to mark the same dep node green concurrently
let (dep_node_index, did_allocation) = {
let dep_node_index = {
let mut current = data.current.borrow_mut();
// Copy the fingerprint from the previous graph,
@@ -758,34 +759,36 @@ fn try_mark_previous_green<'tcx>(
// ... emitting any stored diagnostic ...
// FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere
// Maybe store a list on disk and encode this fact in the DepNodeState
let diagnostics = tcx.queries.on_disk_cache
.load_diagnostics(tcx, prev_dep_node_index);
.load_diagnostics(tcx, prev_dep_node_index);
#[cfg(not(parallel_compiler))]
debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
"DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
insertion for {:?}", dep_node);
if unlikely!(diagnostics.len() > 0) {
self.emit_diagnostics(
tcx,
data,
dep_node_index,
did_allocation,
prev_dep_node_index,
diagnostics
);
}
// ... and finally storing a "Green" entry in the color map.
// Multiple threads can all write the same color here
#[cfg(not(parallel_compiler))]
debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
"DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
insertion for {:?}", dep_node);
data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
Some(dep_node_index)
}
/// Atomically emits some loaded diagnotics, assuming that this only gets called with
/// `did_allocation` set to `true` on a single thread.
/// Atomically emits some loaded diagnostics.
/// This may be called concurrently on multiple threads for the same dep node.
#[cold]
#[inline(never)]
fn emit_diagnostics<'tcx>(
@@ -793,36 +796,49 @@ fn emit_diagnostics<'tcx>(
tcx: TyCtxt<'tcx>,
data: &DepGraphData,
dep_node_index: DepNodeIndex,
did_allocation: bool,
prev_dep_node_index: SerializedDepNodeIndex,
diagnostics: Vec<Diagnostic>,
) {
if did_allocation || !cfg!(parallel_compiler) {
// Only the thread which did the allocation emits the error messages
let handle = tcx.sess.diagnostic();
let mut emitting = data.emitting_diagnostics.lock();
if data.colors.get(prev_dep_node_index) == Some(DepNodeColor::Green(dep_node_index)) {
// The node is already green so diagnostics must have been emitted already
return;
}
if emitting.insert(dep_node_index) {
// We were the first to insert the node in the set so this thread
// must emit the diagnostics and signal other potentially waiting
// threads after.
mem::drop(emitting);
// Promote the previous diagnostics to the current session.
tcx.queries.on_disk_cache
.store_diagnostics(dep_node_index, diagnostics.clone().into());
.store_diagnostics(dep_node_index, diagnostics.clone().into());
let handle = tcx.sess.diagnostic();
for diagnostic in diagnostics {
DiagnosticBuilder::new_diagnostic(handle, diagnostic).emit();
}
#[cfg(parallel_compiler)]
{
// Mark the diagnostics and emitted and wake up waiters
data.emitted_diagnostics.lock().insert(dep_node_index);
data.emitted_diagnostics_cond_var.notify_all();
}
} else {
// The other threads will wait for the diagnostics to be emitted
// Mark the node as green now that diagnostics are emitted
data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
// Remove the node from the set
data.emitting_diagnostics.lock().remove(&dep_node_index);
// Wake up waiters
data.emitting_diagnostics_cond_var.notify_all();
} else {
// We must wait for the other thread to finish emitting the diagnostic
let mut emitted_diagnostics = data.emitted_diagnostics.lock();
loop {
if emitted_diagnostics.contains(&dep_node_index) {
data.emitting_diagnostics_cond_var.wait(&mut emitting);
if data.colors
.get(prev_dep_node_index) == Some(DepNodeColor::Green(dep_node_index)) {
break;
}
data.emitted_diagnostics_cond_var.wait(&mut emitted_diagnostics);
}
}
}
@@ -1027,7 +1043,7 @@ fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeI
hash: self.anon_id_seed.combine(hasher.finish()),
};
self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO).0
self.intern_node(target_dep_node, task_deps.reads, Fingerprint::ZERO)
}
fn alloc_node(
@@ -1037,7 +1053,7 @@ fn alloc_node(
fingerprint: Fingerprint
) -> DepNodeIndex {
debug_assert!(!self.node_to_node_index.contains_key(&dep_node));
self.intern_node(dep_node, edges, fingerprint).0
self.intern_node(dep_node, edges, fingerprint)
}
fn intern_node(
@@ -1045,11 +1061,11 @@ fn intern_node(
dep_node: DepNode,
edges: SmallVec<[DepNodeIndex; 8]>,
fingerprint: Fingerprint
) -> (DepNodeIndex, bool) {
) -> DepNodeIndex {
debug_assert_eq!(self.node_to_node_index.len(), self.data.len());
match self.node_to_node_index.entry(dep_node) {
Entry::Occupied(entry) => (*entry.get(), false),
Entry::Occupied(entry) => *entry.get(),
Entry::Vacant(entry) => {
let dep_node_index = DepNodeIndex::new(self.data.len());
self.data.push(DepNodeData {
@@ -1058,7 +1074,7 @@ fn intern_node(
fingerprint
});
entry.insert(dep_node_index);
(dep_node_index, true)
dep_node_index
}
}
}
+23 -22
View File
@@ -60,10 +60,9 @@
use syntax::ast;
use syntax::ast::*;
use syntax::errors;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ext::hygiene::Mark;
use syntax::print::pprust;
use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned};
use syntax::source_map::CompilerDesugaringKind::CondTemporary;
use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
use syntax::std_inject;
use syntax::symbol::{kw, sym, Symbol};
use syntax::tokenstream::{TokenStream, TokenTree};
@@ -872,17 +871,15 @@ fn diagnostic(&self) -> &errors::Handler {
/// allowed inside this span.
fn mark_span_with_reason(
&self,
reason: CompilerDesugaringKind,
reason: DesugaringKind,
span: Span,
allow_internal_unstable: Option<Lrc<[Symbol]>>,
) -> Span {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo {
def_site: Some(span),
span.fresh_expansion(Mark::root(), ExpnInfo {
def_site: span,
allow_internal_unstable,
..ExpnInfo::default(source_map::CompilerDesugaring(reason), span, self.sess.edition())
});
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
..ExpnInfo::default(ExpnKind::Desugaring(reason), span, self.sess.edition())
})
}
fn with_anonymous_lifetime_mode<R>(
@@ -1188,7 +1185,7 @@ fn make_async_expr(
};
let unstable_span = self.mark_span_with_reason(
CompilerDesugaringKind::Async,
DesugaringKind::Async,
span,
self.allow_gen_future.clone(),
);
@@ -1733,7 +1730,7 @@ fn lower_existential_impl_trait(
// Not tracking it makes lints in rustc and clippy very fragile, as
// frequently opened issues show.
let exist_ty_span = self.mark_span_with_reason(
CompilerDesugaringKind::ExistentialType,
DesugaringKind::ExistentialType,
span,
None,
);
@@ -2603,7 +2600,7 @@ fn lower_async_fn_ret_ty(
let span = output.span();
let exist_ty_span = self.mark_span_with_reason(
CompilerDesugaringKind::Async,
DesugaringKind::Async,
span,
None,
);
@@ -3275,7 +3272,7 @@ fn lower_maybe_async_body(
};
let desugared_span =
this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None);
this.mark_span_with_reason(DesugaringKind::Async, span, None);
// Construct an argument representing `__argN: <ty>` to replace the argument of the
// async function.
@@ -4410,7 +4407,9 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
_ => {
// Lower condition:
let cond = self.lower_expr(cond);
let span_block = self.mark_span_with_reason(CondTemporary, cond.span, None);
let span_block = self.mark_span_with_reason(
DesugaringKind::CondTemporary, cond.span, None
);
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
// to preserve drop semantics since `if cond { ... }` does not
// let temporaries live outside of `cond`.
@@ -4469,7 +4468,9 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// Lower condition:
let cond = this.with_loop_condition_scope(|this| this.lower_expr(cond));
let span_block = this.mark_span_with_reason(CondTemporary, cond.span, None);
let span_block = this.mark_span_with_reason(
DesugaringKind::CondTemporary, cond.span, None
);
// Wrap in a construct equivalent to `{ let _t = $cond; _t }`
// to preserve drop semantics since `while cond { ... }` does not
// let temporaries live outside of `cond`.
@@ -4508,7 +4509,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
ExprKind::TryBlock(ref body) => {
self.with_catch_scope(body.id, |this| {
let unstable_span = this.mark_span_with_reason(
CompilerDesugaringKind::TryBlock,
DesugaringKind::TryBlock,
body.span,
this.allow_try_trait.clone(),
);
@@ -4836,7 +4837,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let mut head = self.lower_expr(head);
let head_sp = head.span;
let desugared_span = self.mark_span_with_reason(
CompilerDesugaringKind::ForLoop,
DesugaringKind::ForLoop,
head_sp,
None,
);
@@ -4990,13 +4991,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
// }
let unstable_span = self.mark_span_with_reason(
CompilerDesugaringKind::QuestionMark,
DesugaringKind::QuestionMark,
e.span,
self.allow_try_trait.clone(),
);
let try_span = self.sess.source_map().end_point(e.span);
let try_span = self.mark_span_with_reason(
CompilerDesugaringKind::QuestionMark,
DesugaringKind::QuestionMark,
try_span,
self.allow_try_trait.clone(),
);
@@ -5811,12 +5812,12 @@ fn lower_await(
}
}
let span = self.mark_span_with_reason(
CompilerDesugaringKind::Await,
DesugaringKind::Await,
await_span,
None,
);
let gen_future_span = self.mark_span_with_reason(
CompilerDesugaringKind::Await,
DesugaringKind::Await,
await_span,
self.allow_gen_future.clone(),
);
+19 -58
View File
@@ -1,6 +1,5 @@
use crate::hir::map::definitions::*;
use crate::hir::def_id::{CRATE_DEF_INDEX, DefIndex};
use crate::session::CrateDisambiguator;
use crate::hir::def_id::DefIndex;
use syntax::ast::*;
use syntax::ext::hygiene::Mark;
@@ -12,33 +11,14 @@
/// Creates `DefId`s for nodes in the AST.
pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
parent_def: DefIndex,
expansion: Mark,
pub visit_macro_invoc: Option<&'a mut dyn FnMut(MacroInvocationData)>,
}
pub struct MacroInvocationData {
pub mark: Mark,
pub def_index: DefIndex,
}
impl<'a> DefCollector<'a> {
pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
DefCollector {
definitions,
expansion,
parent_def: None,
visit_macro_invoc: None,
}
}
pub fn collect_root(&mut self,
crate_name: &str,
crate_disambiguator: CrateDisambiguator) {
let root = self.definitions.create_root_def(crate_name,
crate_disambiguator);
assert_eq!(root, CRATE_DEF_INDEX);
self.parent_def = Some(root);
let parent_def = definitions.invocation_parent(expansion);
DefCollector { definitions, parent_def, expansion }
}
fn create_def(&mut self,
@@ -46,17 +26,15 @@ fn create_def(&mut self,
data: DefPathData,
span: Span)
-> DefIndex {
let parent_def = self.parent_def.unwrap();
let parent_def = self.parent_def;
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
self.definitions
.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span)
}
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
let parent = self.parent_def;
self.parent_def = Some(parent_def);
let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def);
f(self);
self.parent_def = parent;
self.parent_def = orig_parent_def;
}
fn visit_async_fn(
@@ -97,12 +75,7 @@ fn visit_async_fn(
}
fn visit_macro_invoc(&mut self, id: NodeId) {
if let Some(ref mut visit) = self.visit_macro_invoc {
visit(MacroInvocationData {
mark: id.placeholder_to_mark(),
def_index: self.parent_def.unwrap(),
})
}
self.definitions.set_invocation_parent(id.placeholder_to_mark(), self.parent_def);
}
}
@@ -275,36 +248,24 @@ fn visit_anon_const(&mut self, constant: &'a AnonConst) {
}
fn visit_expr(&mut self, expr: &'a Expr) {
let parent_def = self.parent_def;
match expr.node {
let parent_def = match expr.node {
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
ExprKind::Closure(_, asyncness, ..) => {
let closure_def = self.create_def(expr.id,
DefPathData::ClosureExpr,
expr.span);
self.parent_def = Some(closure_def);
// Async closures desugar to closures inside of closures, so
// we must create two defs.
if let IsAsync::Async { closure_id, .. } = asyncness {
let async_def = self.create_def(closure_id,
DefPathData::ClosureExpr,
expr.span);
self.parent_def = Some(async_def);
let closure_def = self.create_def(expr.id, DefPathData::ClosureExpr, expr.span);
match asyncness {
IsAsync::Async { closure_id, .. } =>
self.create_def(closure_id, DefPathData::ClosureExpr, expr.span),
IsAsync::NotAsync => closure_def,
}
}
ExprKind::Async(_, async_id, _) => {
let async_def = self.create_def(async_id,
DefPathData::ClosureExpr,
expr.span);
self.parent_def = Some(async_def);
}
_ => {}
ExprKind::Async(_, async_id, _) =>
self.create_def(async_id, DefPathData::ClosureExpr, expr.span),
_ => self.parent_def,
};
visit::walk_expr(self, expr);
self.parent_def = parent_def;
self.with_parent(parent_def, |this| visit::walk_expr(this, expr));
}
fn visit_ty(&mut self, ty: &'a Ty) {
+13
View File
@@ -100,6 +100,9 @@ pub struct Definitions {
expansions_that_defined: FxHashMap<DefIndex, Mark>,
next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>,
def_index_to_span: FxHashMap<DefIndex, Span>,
/// When collecting definitions from an AST fragment produced by a macro invocation `Mark`
/// we know what parent node that fragment should be attached to thanks to this table.
invocation_parents: FxHashMap<Mark, DefIndex>,
}
/// A unique identifier that we can use to lookup a definition
@@ -434,6 +437,7 @@ pub fn create_root_def(&mut self,
assert!(self.def_index_to_node.is_empty());
self.def_index_to_node.push(ast::CRATE_NODE_ID);
self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index);
self.set_invocation_parent(Mark::root(), root_index);
// Allocate some other DefIndices that always must exist.
GlobalMetaDataKind::allocate_def_indices(self);
@@ -526,6 +530,15 @@ pub fn parent_module_of_macro_def(&self, mark: Mark) -> DefId {
pub fn add_parent_module_of_macro_def(&mut self, mark: Mark, module: DefId) {
self.parent_modules_of_macro_defs.insert(mark, module);
}
pub fn invocation_parent(&self, invoc_id: Mark) -> DefIndex {
self.invocation_parents[&invoc_id]
}
pub fn set_invocation_parent(&mut self, invoc_id: Mark, parent: DefIndex) {
let old_parent = self.invocation_parents.insert(invoc_id, parent);
assert!(old_parent.is_none(), "parent def-index is reset for an invocation");
}
}
impl DefPathData {
+1 -1
View File
@@ -1,5 +1,5 @@
use self::collector::NodeCollector;
pub use self::def_collector::{DefCollector, MacroInvocationData};
pub use self::def_collector::DefCollector;
pub use self::definitions::{
Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash
};
+6 -7
View File
@@ -89,7 +89,6 @@ fn to_stable_hash_key(&self,
Bang,
Attr,
Derive,
ProcMacroStub,
});
@@ -399,7 +398,7 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
call_site,
format,
kind,
def_site,
default_transparency,
allow_internal_unstable,
@@ -408,13 +407,13 @@ fn hash_stable<W: StableHasherResult>(&self,
edition
});
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnFormat {
MacroAttribute(sym),
MacroBang(sym),
CompilerDesugaring(kind)
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
Root,
Macro(kind, descr),
Desugaring(kind)
});
impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
impl_stable_hash_for!(enum ::syntax_pos::hygiene::DesugaringKind {
CondTemporary,
Async,
Await,
@@ -5,7 +5,7 @@
use crate::infer::type_variable::TypeVariableOriginKind;
use crate::ty::{self, Ty, Infer, TyVar};
use crate::ty::print::Print;
use syntax::source_map::CompilerDesugaringKind;
use syntax::source_map::DesugaringKind;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
@@ -194,12 +194,12 @@ pub fn need_type_info_err(
));
} else if let Some(pattern) = local_visitor.found_local_pattern {
if let Some(simple_ident) = pattern.simple_ident() {
match pattern.span.compiler_desugaring_kind() {
match pattern.span.desugaring_kind() {
None => labels.push((
pattern.span,
format!("consider giving `{}` {}", simple_ident, suffix),
)),
Some(CompilerDesugaringKind::ForLoop) => labels.push((
Some(DesugaringKind::ForLoop) => labels.push((
pattern.span,
"the element type for this iterator is not specified".to_owned(),
)),
+2 -2
View File
@@ -247,10 +247,10 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
}
fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
if expn_info.format.name() == sym::impl_lint_pass {
if expn_info.kind.descr() == sym::impl_lint_pass {
true
} else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
info.format.name() == sym::declare_lint_pass
info.kind.descr() == sym::declare_lint_pass
} else {
false
}
+17 -22
View File
@@ -35,9 +35,10 @@
use errors::{DiagnosticBuilder, DiagnosticId};
use std::{hash, ptr};
use syntax::ast;
use syntax::source_map::{MultiSpan, ExpnFormat, CompilerDesugaringKind};
use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind};
use syntax::early_buffered_lints::BufferedEarlyLintId;
use syntax::edition::Edition;
use syntax::ext::base::MacroKind;
use syntax::symbol::{Symbol, sym};
use syntax_pos::Span;
@@ -883,36 +884,30 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
None => return false,
};
match info.format {
ExpnFormat::MacroAttribute(..) => true, // definitely a plugin
ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::ForLoop) => false,
ExpnFormat::CompilerDesugaring(_) => true, // well, it's "external"
ExpnFormat::MacroBang(..) => {
let def_site = match info.def_site {
Some(span) => span,
// no span for the def_site means it's an external macro
None => return true,
};
match sess.source_map().span_to_snippet(def_site) {
match info.kind {
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
if info.def_site.is_dummy() {
// dummy span for the def_site means it's an external macro
return true;
}
match sess.source_map().span_to_snippet(info.def_site) {
Ok(code) => !code.starts_with("macro_rules"),
// no snippet = external macro or compiler-builtin expansion
Err(_) => true,
}
}
ExpnKind::Macro(..) => true, // definitely a plugin
}
}
/// Returns whether `span` originates in a derive macro's expansion
pub fn in_derive_expansion(span: Span) -> bool {
let info = match span.ctxt().outer_expn_info() {
Some(info) => info,
// no ExpnInfo means this span doesn't come from a macro
None => return false,
};
match info.format {
ExpnFormat::MacroAttribute(symbol) => symbol.as_str().starts_with("derive("),
_ => false,
if let Some(info) = span.ctxt().outer_expn_info() {
if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind {
return true;
}
}
false
}
+1 -1
View File
@@ -928,7 +928,7 @@ pub fn is_ref_for_guard(&self) -> bool {
/// `__next` from a `for` loop.
#[inline]
pub fn from_compiler_desugaring(&self) -> bool {
self.source_info.span.compiler_desugaring_kind().is_some()
self.source_info.span.desugaring_kind().is_some()
}
/// Creates a new `LocalDecl` for a temporary.
+6 -9
View File
@@ -36,7 +36,7 @@
use std::fmt;
use syntax::ast;
use syntax::symbol::sym;
use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat};
use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind};
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_fulfillment_errors(&self,
@@ -61,12 +61,9 @@ struct ErrorDescriptor<'tcx> {
// We want to ignore desugarings here: spans are equivalent even
// if one is the result of a desugaring and the other is not.
let mut span = error.obligation.cause.span;
if let Some(ExpnInfo {
format: ExpnFormat::CompilerDesugaring(_),
def_site: Some(def_span),
..
}) = span.ctxt().outer_expn_info() {
span = def_span;
if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. })
= span.ctxt().outer_expn_info() {
span = def_site;
}
error_map.entry(span).or_default().push(
@@ -373,9 +370,9 @@ fn on_unimplemented_note(
flags.push((sym::parent_trait, Some(t)));
}
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
if let Some(k) = obligation.cause.span.desugaring_kind() {
flags.push((sym::from_desugaring, None));
flags.push((sym::from_desugaring, Some(k.name().to_string())));
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
+22 -22
View File
@@ -588,41 +588,41 @@ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
let expn_info_tag = u8::decode(self)?;
let ctxt = match expn_info_tag {
// FIXME(mw): This method does not restore `MarkData::parent` or
// `SyntaxContextData::prev_ctxt` or `SyntaxContextData::opaque`. These things
// don't seem to be used after HIR lowering, so everything should be fine
// as long as incremental compilation does not kick in before that.
let location = || Span::new(lo, hi, SyntaxContext::empty());
let recover_from_expn_info = |this: &Self, expn_info, pos| {
let span = location().fresh_expansion(Mark::root(), expn_info);
this.synthetic_expansion_infos.borrow_mut().insert(pos, span.ctxt());
span
};
Ok(match expn_info_tag {
TAG_NO_EXPANSION_INFO => {
SyntaxContext::empty()
location()
}
TAG_EXPANSION_INFO_INLINE => {
let pos = AbsoluteBytePos::new(self.opaque.position());
let expn_info: ExpnInfo = Decodable::decode(self)?;
let ctxt = SyntaxContext::allocate_directly(expn_info);
self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
ctxt
let expn_info = Decodable::decode(self)?;
recover_from_expn_info(
self, expn_info, AbsoluteBytePos::new(self.opaque.position())
)
}
TAG_EXPANSION_INFO_SHORTHAND => {
let pos = AbsoluteBytePos::decode(self)?;
let cached_ctxt = self.synthetic_expansion_infos
.borrow()
.get(&pos)
.cloned();
let cached_ctxt = self.synthetic_expansion_infos.borrow().get(&pos).cloned();
if let Some(ctxt) = cached_ctxt {
ctxt
Span::new(lo, hi, ctxt)
} else {
let expn_info = self.with_position(pos.to_usize(), |this| {
ExpnInfo::decode(this)
})?;
let ctxt = SyntaxContext::allocate_directly(expn_info);
self.synthetic_expansion_infos.borrow_mut().insert(pos, ctxt);
ctxt
let expn_info =
self.with_position(pos.to_usize(), |this| ExpnInfo::decode(this))?;
recover_from_expn_info(self, expn_info, pos)
}
}
_ => {
unreachable!()
}
};
Ok(Span::new(lo, hi, ctxt))
})
}
}
+7 -10
View File
@@ -8,13 +8,13 @@
},
attr,
source_map::{
respan, ExpnInfo, MacroAttribute,
respan, ExpnInfo, ExpnKind,
},
ext::{
base::{ExtCtxt, Resolver},
base::{ExtCtxt, MacroKind, Resolver},
build::AstBuilder,
expand::ExpansionConfig,
hygiene::{Mark, SyntaxContext},
hygiene::Mark,
},
mut_visit::{self, MutVisitor},
parse::ParseSess,
@@ -84,15 +84,12 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
}
self.found = true;
// Create a fresh Mark for the new macro expansion we are about to do
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(sym::global_allocator), item.span, self.sess.edition, &[sym::rustc_attrs]
// Create a new expansion for the generated allocator code.
let span = item.span.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::global_allocator), item.span, self.sess.edition,
[sym::rustc_attrs][..].into(),
));
// Tie the span to the macro expansion info we just created
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
// Create an expansion config
let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap());
+3 -3
View File
@@ -33,7 +33,7 @@
use std::fmt;
use std::rc::Rc;
use std::hash::{Hash, Hasher};
use syntax::source_map::CompilerDesugaringKind;
use syntax::source_map::DesugaringKind;
use syntax_pos::{MultiSpan, Span};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
@@ -734,8 +734,8 @@ pub fn report_use_of_moved_value(&self,
},
moved_lp.ty));
}
if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = (
move_span.compiler_desugaring_kind(),
if let (Some(DesugaringKind::ForLoop), Ok(snippet)) = (
move_span.desugaring_kind(),
self.tcx.sess.source_map().span_to_snippet(move_span),
) {
if !snippet.starts_with("&") {
+31 -33
View File
@@ -723,39 +723,37 @@ fn fix_multispan_in_std_macros(&mut self,
for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() {
// Only show macro locations that are local
// and display them like a span_note
if let Some(def_site) = trace.def_site_span {
if def_site.is_dummy() {
continue;
}
if always_backtrace {
new_labels.push((def_site,
format!("in this expansion of `{}`{}",
trace.macro_decl_name,
if backtrace_len > 2 {
// if backtrace_len == 1 it'll be pointed
// at by "in this macro invocation"
format!(" (#{})", i + 1)
} else {
String::new()
})));
}
// Check to make sure we're not in any <*macros>
if !sm.span_to_filename(def_site).is_macros() &&
!trace.macro_decl_name.starts_with("desugaring of ") &&
!trace.macro_decl_name.starts_with("#[") ||
always_backtrace {
new_labels.push((trace.call_site,
format!("in this macro invocation{}",
if backtrace_len > 2 && always_backtrace {
// only specify order when the macro
// backtrace is multiple levels deep
format!(" (#{})", i + 1)
} else {
String::new()
})));
if !always_backtrace {
break;
}
if trace.def_site_span.is_dummy() {
continue;
}
if always_backtrace {
new_labels.push((trace.def_site_span,
format!("in this expansion of `{}`{}",
trace.macro_decl_name,
if backtrace_len > 2 {
// if backtrace_len == 1 it'll be pointed
// at by "in this macro invocation"
format!(" (#{})", i + 1)
} else {
String::new()
})));
}
// Check to make sure we're not in any <*macros>
if !sm.span_to_filename(trace.def_site_span).is_macros() &&
!trace.macro_decl_name.starts_with("desugaring of ") &&
!trace.macro_decl_name.starts_with("#[") ||
always_backtrace {
new_labels.push((trace.call_site,
format!("in this macro invocation{}",
if backtrace_len > 2 && always_backtrace {
// only specify order when the macro
// backtrace is multiple levels deep
format!(" (#{})", i + 1)
} else {
String::new()
})));
if !always_backtrace {
break;
}
}
}
@@ -10,7 +10,7 @@
use rustc_data_structures::indexed_vec::Idx;
use rustc_errors::{Applicability, DiagnosticBuilder};
use syntax_pos::Span;
use syntax::source_map::CompilerDesugaringKind;
use syntax::source_map::DesugaringKind;
use super::nll::explain_borrow::BorrowExplanation;
use super::nll::region_infer::{RegionName, RegionNameSource};
@@ -174,7 +174,7 @@ pub(super) fn report_use_of_moved_or_uninitialized(
format!("variable moved due to use{}", move_spans.describe()),
);
}
if Some(CompilerDesugaringKind::ForLoop) == move_span.compiler_desugaring_kind() {
if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() {
if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
move_span,
+1 -1
View File
@@ -335,7 +335,7 @@ fn do_mir_borrowck<'a, 'tcx>(
}
let span = local_decl.source_info.span;
if span.compiler_desugaring_kind().is_some() {
if span.desugaring_kind().is_some() {
// If the `mut` arises as part of a desugaring, we should ignore it.
continue;
}
+20 -36
View File
@@ -9,7 +9,7 @@
use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
use crate::{ModuleOrUniformRoot, PerNS, Resolver, ResolverArenas, ExternPreludeEntry};
use crate::Namespace::{self, TypeNS, ValueNS, MacroNS};
use crate::{resolve_error, resolve_struct_error, ResolutionError};
use crate::{resolve_error, resolve_struct_error, ResolutionError, Determinacy};
use rustc::bug;
use rustc::hir::def::{self, *};
@@ -29,8 +29,7 @@
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind, Variant};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::base::SyntaxExtension;
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::is_builtin_attr;
@@ -231,9 +230,9 @@ fn build_reduced_graph_for_use_tree(
source: source.ident,
target: ident,
source_bindings: PerNS {
type_ns: Cell::new(Err(Undetermined)),
value_ns: Cell::new(Err(Undetermined)),
macro_ns: Cell::new(Err(Undetermined)),
type_ns: Cell::new(Err(Determinacy::Undetermined)),
value_ns: Cell::new(Err(Determinacy::Undetermined)),
macro_ns: Cell::new(Err(Determinacy::Undetermined)),
},
target_bindings: PerNS {
type_ns: Cell::new(None),
@@ -456,23 +455,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent_scope: ParentScop
// Functions introducing procedural macros reserve a slot
// in the macro namespace as well (see #52225).
if attr::contains_name(&item.attrs, sym::proc_macro) ||
attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
let res = Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), res.def_id());
self.define(parent, ident, MacroNS, (res, vis, sp, expansion));
}
if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
if let Some(trait_attr) =
attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
if let Some(ident) = trait_attr.ident() {
let res = Res::Def(
DefKind::Macro(MacroKind::ProcMacroStub),
res.def_id(),
);
self.define(parent, ident, MacroNS, (res, vis, ident.span, expansion));
}
}
}
self.define_macro(item, expansion, &mut LegacyScope::Empty);
}
// These items live in the type namespace.
@@ -772,14 +755,8 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
}
}
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
self.opt_get_macro(res).expect("expected `DefKind::Macro` or `Res::NonMacroAttr`")
}
crate fn opt_get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
pub fn get_macro(&mut self, res: Res) -> Option<Lrc<SyntaxExtension>> {
let def_id = match res {
Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) =>
return Some(self.non_macro_attr(true)), // some dummy extension
Res::Def(DefKind::Macro(..), def_id) => def_id,
Res::NonMacroAttr(attr_kind) =>
return Some(self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool)),
@@ -946,12 +923,19 @@ pub struct BuildReducedGraphVisitor<'a, 'b> {
impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
let mark = id.placeholder_to_mark();
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
let invocation = self.resolver.invocations[&mark];
invocation.module.set(self.resolver.current_module);
invocation.parent_legacy_scope.set(self.current_legacy_scope);
invocation
let invoc_id = id.placeholder_to_mark();
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(invoc_id);
let invocation_data = self.resolver.arenas.alloc_invocation_data(InvocationData {
module: self.resolver.current_module,
parent_legacy_scope: self.current_legacy_scope,
output_legacy_scope: Cell::new(None),
});
let old_invocation_data = self.resolver.invocations.insert(invoc_id, invocation_data);
assert!(old_invocation_data.is_none(), "invocation data is reset for an invocation");
invocation_data
}
}
+33 -8
View File
@@ -15,11 +15,12 @@
pub use rustc::hir::def::{Namespace, PerNS};
use Determinacy::*;
use GenericParameters::*;
use RibKind::*;
use smallvec::smallvec;
use rustc::hir::map::{Definitions, DefCollector};
use rustc::hir::map::Definitions;
use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
use rustc::middle::cstore::CrateStore;
use rustc::session::Session;
@@ -40,8 +41,7 @@
use syntax::source_map::SourceMap;
use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::MacroKind;
use syntax::symbol::{Symbol, kw, sym};
use syntax::util::lev_distance::find_best_match_for_name;
@@ -93,6 +93,18 @@ enum Weak {
No,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Determinacy {
Determined,
Undetermined,
}
impl Determinacy {
fn determined(determined: bool) -> Determinacy {
if determined { Determinacy::Determined } else { Determinacy::Undetermined }
}
}
enum ScopeSet {
Import(Namespace),
AbsolutePath(Namespace),
@@ -1663,10 +1675,13 @@ pub struct Resolver<'a> {
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Res>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
dummy_ext_bang: Lrc<SyntaxExtension>,
dummy_ext_derive: Lrc<SyntaxExtension>,
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
unused_macros: NodeMap<Span>,
proc_macro_stubs: NodeSet,
/// Maps the `Mark` of an expansion to its containing module or block.
invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
@@ -1901,8 +1916,7 @@ pub fn new(session: &'a Session,
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
let mut definitions = Definitions::default();
DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, session.local_crate_disambiguator());
definitions.create_root_def(crate_name, session.local_crate_disambiguator());
let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> =
session.opts.externs.iter().map(|kv| (Ident::from_str(kv.0), Default::default()))
@@ -1926,9 +1940,8 @@ pub fn new(session: &'a Session,
macro_defs.insert(Mark::root(), root_def_id);
let features = session.features_untracked();
let non_macro_attr = |mark_used| Lrc::new(SyntaxExtension::default(
SyntaxExtensionKind::NonMacroAttr { mark_used }, session.edition()
));
let non_macro_attr =
|mark_used| Lrc::new(SyntaxExtension::non_macro_attr(mark_used, session.edition()));
Resolver {
session,
@@ -2003,6 +2016,8 @@ pub fn new(session: &'a Session,
macro_use_prelude: FxHashMap::default(),
all_macros: FxHashMap::default(),
macro_map: FxHashMap::default(),
dummy_ext_bang: Lrc::new(SyntaxExtension::dummy_bang(session.edition())),
dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())),
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
invocations,
macro_defs,
@@ -2011,6 +2026,7 @@ pub fn new(session: &'a Session,
potentially_unused_imports: Vec::new(),
struct_constructors: Default::default(),
unused_macros: Default::default(),
proc_macro_stubs: Default::default(),
current_type_ascription: Vec::new(),
injected_crate: None,
active_features:
@@ -2028,6 +2044,14 @@ fn non_macro_attr(&self, mark_used: bool) -> Lrc<SyntaxExtension> {
self.non_macro_attrs[mark_used as usize].clone()
}
fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
match macro_kind {
MacroKind::Bang => self.dummy_ext_bang.clone(),
MacroKind::Derive => self.dummy_ext_derive.clone(),
MacroKind::Attr => self.non_macro_attr(true),
}
}
/// Runs the function on each namespace.
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
f(self, TypeNS);
@@ -2223,6 +2247,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
}
if !module.no_implicit_prelude {
ident.span.adjust(Mark::root());
if ns == TypeNS {
if let Some(binding) = self.extern_prelude_get(ident, !record_used) {
return Some(LexicalScopeBinding::Item(binding));
+172 -176
View File
@@ -1,4 +1,4 @@
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
use crate::{CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
use crate::{Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
use crate::{is_known_tool, resolve_error};
@@ -8,16 +8,16 @@
use crate::resolve_imports::ImportResolver;
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
use rustc::hir::map::{self, DefCollector};
use rustc::hir::map::DefCollector;
use rustc::middle::stability;
use rustc::{ty, lint, span_bug};
use syntax::ast::{self, Ident};
use syntax::ast::{self, Ident, ItemKind};
use syntax::attr::{self, StabilityLevel};
use syntax::errors::DiagnosticBuilder;
use syntax::ext::base::{self, Determinacy};
use syntax::ext::base::{self, Indeterminate};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, Mark};
use syntax::ext::hygiene::{self, Mark, ExpnInfo, ExpnKind};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
@@ -32,14 +32,14 @@
type Res = def::Res<ast::NodeId>;
// FIXME: Merge this with `ParentScope`.
#[derive(Clone, Debug)]
pub struct InvocationData<'a> {
def_index: DefIndex,
/// The module in which the macro was invoked.
crate module: Cell<Module<'a>>,
crate module: Module<'a>,
/// The legacy scope in which the macro was invoked.
/// The invocation path is resolved in this scope.
crate parent_legacy_scope: Cell<LegacyScope<'a>>,
crate parent_legacy_scope: LegacyScope<'a>,
/// The legacy scope *produced* by expanding this macro invocation,
/// includes all the macro_rules items, other invocations, etc generated by it.
/// `None` if the macro is not expanded yet.
@@ -49,10 +49,9 @@ pub struct InvocationData<'a> {
impl<'a> InvocationData<'a> {
pub fn root(graph_root: Module<'a>) -> Self {
InvocationData {
module: Cell::new(graph_root),
def_index: CRATE_DEF_INDEX,
parent_legacy_scope: Cell::new(LegacyScope::Empty),
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
module: graph_root,
parent_legacy_scope: LegacyScope::Empty,
output_legacy_scope: Cell::new(None),
}
}
}
@@ -74,9 +73,6 @@ pub struct LegacyBinding<'a> {
/// can potentially expand into macro definitions.
#[derive(Copy, Clone, Debug)]
pub enum LegacyScope<'a> {
/// Created when invocation data is allocated in the arena;
/// must be replaced with a proper scope later.
Uninitialized,
/// Empty "root" scope at the crate start containing no names.
Empty,
/// The scope introduced by a `macro_rules!` macro definition.
@@ -102,12 +98,11 @@ fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKi
#[derive(PartialEq)]
enum SubNS { Bang, AttrLike }
let sub_ns = |kind| match kind {
MacroKind::Bang => Some(SubNS::Bang),
MacroKind::Attr | MacroKind::Derive => Some(SubNS::AttrLike),
MacroKind::ProcMacroStub => None,
MacroKind::Bang => SubNS::Bang,
MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike,
};
let requirement = requirement.and_then(|kind| sub_ns(kind));
let candidate = candidate.and_then(|kind| sub_ns(kind));
let candidate = candidate.map(sub_ns);
let requirement = requirement.map(sub_ns);
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
candidate.is_none() || requirement.is_none() || candidate == requirement
}
@@ -115,17 +110,36 @@ enum SubNS { Bang, AttrLike }
// We don't want to format a path using pretty-printing,
// `format!("{}", path)`, because that tries to insert
// line-breaks and is slow.
fn fast_print_path(path: &ast::Path) -> String {
let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() {
if i != 0 {
path_str.push_str("::");
fn fast_print_path(path: &ast::Path) -> Symbol {
if path.segments.len() == 1 {
return path.segments[0].ident.name
} else {
let mut path_str = String::with_capacity(64);
for (i, segment) in path.segments.iter().enumerate() {
if i != 0 {
path_str.push_str("::");
}
if segment.ident.name != kw::PathRoot {
path_str.push_str(&segment.ident.as_str())
}
}
if segment.ident.name != kw::PathRoot {
path_str.push_str(&segment.ident.as_str())
Symbol::intern(&path_str)
}
}
fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
if attr::contains_name(&item.attrs, sym::proc_macro) {
return Some((MacroKind::Bang, item.ident, item.span));
} else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
return Some((MacroKind::Attr, item.ident, item.span));
} else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
if let Some(ident) = nested_meta.ident() {
return Some((MacroKind::Derive, ident, ident.span));
}
}
}
path_str
None
}
impl<'a> base::Resolver for Resolver<'a> {
@@ -134,13 +148,16 @@ fn next_node_id(&mut self) -> ast::NodeId {
}
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark {
let mark = Mark::fresh(Mark::root());
let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::default(
ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, self.session.edition()
));
let mark = span.ctxt().outer();
let module = self.module_map[&self.definitions.local_def_id(id)];
self.definitions.set_invocation_parent(mark, module.def_id().unwrap().index);
self.invocations.insert(mark, self.arenas.alloc_invocation_data(InvocationData {
module: Cell::new(module),
def_index: module.def_id().unwrap().index,
parent_legacy_scope: Cell::new(LegacyScope::Empty),
output_legacy_scope: Cell::new(Some(LegacyScope::Empty)),
module,
parent_legacy_scope: LegacyScope::Empty,
output_legacy_scope: Cell::new(None),
}));
mark
}
@@ -157,16 +174,20 @@ fn resolve_dollar_crates(&mut self) {
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
derives: &[Mark]) {
let invocation = self.invocations[&mark];
self.collect_def_ids(mark, invocation, fragment);
fragment.visit_with(&mut DefCollector::new(&mut self.definitions, mark));
self.current_module = invocation.module.get();
let invocation = self.invocations[&mark];
self.current_module = invocation.module;
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
let parent_def = self.definitions.invocation_parent(mark);
for &derive_invoc_id in derives {
self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
}
self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
let mut visitor = BuildReducedGraphVisitor {
resolver: self,
current_legacy_scope: invocation.parent_legacy_scope.get(),
current_legacy_scope: invocation.parent_legacy_scope,
expansion: mark,
};
fragment.visit_with(&mut visitor);
@@ -198,36 +219,23 @@ fn resolve_imports(&mut self) {
}
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate> {
let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
InvocationKind::Attr { attr: None, .. } =>
return Ok(None),
InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
(&attr.path, MacroKind::Attr, traits.clone(), after_derive),
InvocationKind::Attr { ref attr, ref derives, after_derive, .. } =>
(&attr.path, MacroKind::Attr, derives.clone(), after_derive),
InvocationKind::Bang { ref mac, .. } =>
(&mac.node.path, MacroKind::Bang, Vec::new(), false),
InvocationKind::Derive { ref path, .. } =>
(path, MacroKind::Derive, Vec::new(), false),
InvocationKind::DeriveContainer { .. } =>
return Ok(None),
};
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
let (res, ext) = match self.resolve_macro_to_res(path, kind, &parent_scope, true, force) {
Ok((res, ext)) => (res, ext),
// Replace unresolved attributes with used inert attributes for better recovery.
Err(Determinacy::Determined) if kind == MacroKind::Attr =>
(Res::Err, self.non_macro_attr(true)),
Err(determinacy) => return Err(determinacy),
};
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, true, force)?;
let span = invoc.span();
let path = fast_print_path(path);
let format = match kind {
MacroKind::Derive => format!("derive({})", path),
_ => path.clone(),
};
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, &format));
self.check_stability_and_deprecation(&ext, &path, span);
invoc.expansion_data.mark.set_expn_info(ext.expn_info(span, fast_print_path(path)));
if let Res::Def(_, def_id) = res {
if after_derive {
@@ -243,13 +251,6 @@ fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force
Ok(Some(ext))
}
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
derives_in_scope: Vec<ast::Path>, force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy> {
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
Ok(self.resolve_macro_to_res(path, kind, &parent_scope, false, force)?.1)
}
fn check_unused_macros(&self) {
for (&node_id, &span) in self.unused_macros.iter() {
self.session.buffer_lint(
@@ -267,91 +268,95 @@ pub fn dummy_parent_scope(&self) -> ParentScope<'a> {
fn invoc_parent_scope(&self, invoc_id: Mark, derives: Vec<ast::Path>) -> ParentScope<'a> {
let invoc = self.invocations[&invoc_id];
ParentScope {
module: invoc.module.get().nearest_item_scope(),
module: invoc.module.nearest_item_scope(),
expansion: invoc_id.parent(),
legacy: invoc.parent_legacy_scope.get(),
legacy: invoc.parent_legacy_scope,
derives,
}
}
fn resolve_macro_to_res(
/// Resolve macro path with error reporting and recovery.
fn smart_resolve_macro_path(
&mut self,
path: &ast::Path,
kind: MacroKind,
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
) -> Result<(Res, Lrc<SyntaxExtension>), Determinacy> {
let res = self.resolve_macro_to_res_inner(path, kind, parent_scope, trace, force);
) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
let (ext, res) = match self.resolve_macro_path(path, kind, parent_scope, trace, force) {
Ok((Some(ext), res)) => (ext, res),
// Use dummy syntax extensions for unresolved macros for better recovery.
Ok((None, res)) => (self.dummy_ext(kind), res),
Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err),
Err(Determinacy::Undetermined) => return Err(Indeterminate),
};
// Report errors and enforce feature gates for the resolved macro.
let features = self.session.features_untracked();
if res != Err(Determinacy::Undetermined) {
// Do not report duplicated errors on every undetermined resolution.
for segment in &path.segments {
if let Some(args) = &segment.args {
self.session.span_err(args.span(), "generic arguments in macro path");
}
if kind == MacroKind::Attr && !features.rustc_attrs &&
segment.ident.as_str().starts_with("rustc") {
let msg = "attributes starting with `rustc` are \
reserved for use by the `rustc` compiler";
emit_feature_err(
&self.session.parse_sess,
sym::rustc_attrs,
segment.ident.span,
GateIssue::Language,
msg,
);
}
for segment in &path.segments {
if let Some(args) = &segment.args {
self.session.span_err(args.span(), "generic arguments in macro path");
}
if kind == MacroKind::Attr && !features.rustc_attrs &&
segment.ident.as_str().starts_with("rustc") {
let msg =
"attributes starting with `rustc` are reserved for use by the `rustc` compiler";
emit_feature_err(
&self.session.parse_sess,
sym::rustc_attrs,
segment.ident.span,
GateIssue::Language,
msg,
);
}
}
let res = res?;
match res {
Res::Def(DefKind::Macro(macro_kind), def_id) => {
Res::Def(DefKind::Macro(_), def_id) => {
if let Some(node_id) = self.definitions.as_local_node_id(def_id) {
self.unused_macros.remove(&node_id);
}
if macro_kind == MacroKind::ProcMacroStub {
let msg = "can't use a procedural macro from the same crate that defines it";
self.session.span_err(path.span, msg);
return Err(Determinacy::Determined);
if self.proc_macro_stubs.contains(&node_id) {
self.session.span_err(
path.span,
"can't use a procedural macro from the same crate that defines it",
);
}
}
}
Res::NonMacroAttr(attr_kind) => {
if kind == MacroKind::Attr {
if attr_kind == NonMacroAttrKind::Custom {
assert!(path.segments.len() == 1);
if !features.custom_attribute {
let msg = format!("The attribute `{}` is currently unknown to the \
compiler and may have meaning added to it in the \
future", path);
self.report_unknown_attribute(
path.span,
&path.segments[0].ident.as_str(),
&msg,
sym::custom_attribute,
);
}
if attr_kind == NonMacroAttrKind::Custom {
assert!(path.segments.len() == 1);
if !features.custom_attribute {
let msg = format!("The attribute `{}` is currently unknown to the \
compiler and may have meaning added to it in the \
future", path);
self.report_unknown_attribute(
path.span,
&path.segments[0].ident.as_str(),
&msg,
sym::custom_attribute,
);
}
} else {
// Not only attributes, but anything in macro namespace can result in
// `Res::NonMacroAttr` definition (e.g., `inline!()`), so we must report
// an error for those cases.
let msg = format!("expected a macro, found {}", res.descr());
self.session.span_err(path.span, &msg);
return Err(Determinacy::Determined);
}
}
Res::Err => {
return Err(Determinacy::Determined);
}
Res::Err => {}
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
}
};
Ok((res, self.get_macro(res)))
self.check_stability_and_deprecation(&ext, path);
Ok(if ext.macro_kind() != kind {
let expected = if kind == MacroKind::Attr { "attribute" } else { kind.descr() };
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
self.session.struct_span_err(path.span, &msg)
.span_label(path.span, format!("not {} {}", kind.article(), expected))
.emit();
// Use dummy syntax extensions for unexpected macro kinds for better recovery.
(self.dummy_ext(kind), Res::Err)
} else {
(ext, res)
})
}
fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: Symbol) {
@@ -408,14 +413,14 @@ fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: S
err.emit();
}
pub fn resolve_macro_to_res_inner(
pub fn resolve_macro_path(
&mut self,
path: &ast::Path,
kind: MacroKind,
parent_scope: &ParentScope<'a>,
trace: bool,
force: bool,
) -> Result<Res, Determinacy> {
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
let path_span = path.span;
let mut path = Segment::from_path(path);
@@ -427,7 +432,7 @@ pub fn resolve_macro_to_res_inner(
path.insert(0, Segment::from_ident(root));
}
if path.len() > 1 {
let res = if path.len() > 1 {
let res = match self.resolve_path(&path, Some(MacroNS), parent_scope,
false, path_span, CrateLint::No) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
@@ -463,7 +468,9 @@ pub fn resolve_macro_to_res_inner(
let res = binding.map(|binding| binding.res());
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
res
}
};
res.map(|res| (self.get_macro(res), res))
}
// Resolve an identifier in lexical scope.
@@ -592,16 +599,16 @@ struct Flags: u8 {
let mut result = Err(Determinacy::Determined);
for derive in &parent_scope.derives {
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
match self.resolve_macro_to_res(derive, MacroKind::Derive,
&parent_scope, true, force) {
Ok((_, ext)) => if ext.helper_attrs.contains(&ident.name) {
match self.resolve_macro_path(derive, MacroKind::Derive,
&parent_scope, true, force) {
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
ty::Visibility::Public, derive.span, Mark::root())
.to_name_binding(self.arenas);
result = Ok((binding, Flags::empty()));
break;
}
Err(Determinacy::Determined) => {}
Ok(_) | Err(Determinacy::Determined) => {}
Err(Determinacy::Undetermined) =>
result = Err(Determinacy::Undetermined),
}
@@ -837,10 +844,9 @@ struct Flags: u8 {
binding.parent_legacy_scope
),
LegacyScope::Invocation(invoc) => WhereToResolve::MacroRules(
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope.get())
invoc.output_legacy_scope.get().unwrap_or(invoc.parent_legacy_scope)
),
LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
LegacyScope::Uninitialized => unreachable!(),
}
WhereToResolve::CrateRoot => match ns {
TypeNS => {
@@ -853,6 +859,7 @@ struct Flags: u8 {
match self.hygienic_lexical_parent(module, &mut ident.span) {
Some(parent_module) => WhereToResolve::Module(parent_module),
None => {
ident.span.adjust(Mark::root());
use_prelude = !module.no_implicit_prelude;
match ns {
TypeNS => WhereToResolve::ExternPrelude,
@@ -862,7 +869,7 @@ struct Flags: u8 {
}
}
}
WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
WhereToResolve::MacroUsePrelude => WhereToResolve::StdLibPrelude,
WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
@@ -872,7 +879,7 @@ struct Flags: u8 {
WhereToResolve::StdLibPrelude => match ns {
TypeNS => WhereToResolve::BuiltinTypes,
ValueNS => break, // nowhere else to search
MacroNS => unreachable!(),
MacroNS => WhereToResolve::BuiltinMacros,
}
WhereToResolve::BuiltinTypes => break, // nowhere else to search
};
@@ -999,7 +1006,8 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
}
}
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &str, span: Span) {
fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Path) {
let span = path.span;
if let Some(stability) = &ext.stability {
if let StabilityLevel::Unstable { reason, issue } = stability.level {
let feature = stability.feature;
@@ -1008,14 +1016,14 @@ fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &str, spa
}
}
if let Some(depr) = &stability.rustc_depr {
let (message, lint) = stability::rustc_deprecation_message(depr, path);
let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string());
stability::early_report_deprecation(
self.session, &message, depr.suggestion, lint, span
);
}
}
if let Some(depr) = &ext.deprecation {
let (message, lint) = stability::deprecation_message(depr, path);
let (message, lint) = stability::deprecation_message(depr, &path.to_string());
stability::early_report_deprecation(self.session, &message, None, lint, span);
}
}
@@ -1092,36 +1100,11 @@ fn suggest_macro_name(&mut self, name: Symbol, kind: MacroKind,
}
}
fn collect_def_ids(&mut self,
mark: Mark,
invocation: &'a InvocationData<'a>,
fragment: &AstFragment) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, .. } = *invocation;
let visit_macro_invoc = &mut |invoc: map::MacroInvocationData| {
invocations.entry(invoc.mark).or_insert_with(|| {
arenas.alloc_invocation_data(InvocationData {
def_index: invoc.def_index,
module: Cell::new(graph_root),
parent_legacy_scope: Cell::new(LegacyScope::Uninitialized),
output_legacy_scope: Cell::new(None),
})
});
};
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
fragment.visit_with(def_collector)
});
}
crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) {
// Reserve some names that are not quite covered by the general check
// performed on `Resolver::builtin_attrs`.
if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive {
let macro_kind = self.opt_get_macro(res).map(|ext| ext.macro_kind());
let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind());
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
self.session.span_err(
ident.span, &format!("name `{}` is reserved in attribute namespace", ident)
@@ -1134,19 +1117,32 @@ pub fn define_macro(&mut self,
item: &ast::Item,
expansion: Mark,
current_legacy_scope: &mut LegacyScope<'a>) {
self.local_macro_def_scopes.insert(item.id, self.current_module);
let ident = item.ident;
let (ext, ident, span, is_legacy) = match &item.node {
ItemKind::MacroDef(def) => {
let ext = Lrc::new(macro_rules::compile(
&self.session.parse_sess,
&self.session.features_untracked(),
item,
self.session.edition(),
));
(ext, item.ident, item.span, def.legacy)
}
ItemKind::Fn(..) => match proc_macro_stub(item) {
Some((macro_kind, ident, span)) => {
self.proc_macro_stubs.insert(item.id);
(self.dummy_ext(macro_kind), ident, span, false)
}
None => return,
}
_ => unreachable!(),
};
let def_id = self.definitions.local_def_id(item.id);
let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
&self.session.features_untracked(),
item, self.session.edition()));
let macro_kind = ext.macro_kind();
let res = Res::Def(DefKind::Macro(macro_kind), def_id);
let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
self.macro_map.insert(def_id, ext);
self.local_macro_def_scopes.insert(item.id, self.current_module);
let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() };
if def.legacy {
if is_legacy {
let ident = ident.modern();
self.macro_names.insert(ident);
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
@@ -1155,7 +1151,7 @@ pub fn define_macro(&mut self,
} else {
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
};
let binding = (res, vis, item.span, expansion).to_name_binding(self.arenas);
let binding = (res, vis, span, expansion).to_name_binding(self.arenas);
self.set_binding_parent_module(binding, self.current_module);
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
parent_legacy_scope: *current_legacy_scope, binding, ident
@@ -1165,18 +1161,18 @@ pub fn define_macro(&mut self,
if is_macro_export {
let module = self.graph_root;
self.define(module, ident, MacroNS,
(res, vis, item.span, expansion, IsMacroExport));
(res, vis, span, expansion, IsMacroExport));
} else {
self.check_reserved_macro_name(ident, res);
self.unused_macros.insert(item.id, item.span);
self.unused_macros.insert(item.id, span);
}
} else {
let module = self.current_module;
let vis = self.resolve_visibility(&item.vis);
if vis != ty::Visibility::Public {
self.unused_macros.insert(item.id, item.span);
self.unused_macros.insert(item.id, span);
}
self.define(module, ident, MacroNS, (res, vis, item.span, expansion));
self.define(module, ident, MacroNS, (res, vis, span, expansion));
}
}
}
+1 -1
View File
@@ -2,6 +2,7 @@
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, Weak};
use crate::Determinacy::{self, *};
use crate::Namespace::{self, TypeNS, MacroNS};
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use crate::{Resolver, Segment};
@@ -27,7 +28,6 @@
use rustc::{bug, span_bug};
use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID};
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
use syntax::ext::hygiene::Mark;
use syntax::symbol::kw;
use syntax::util::lev_distance::find_best_match_for_name;
+5 -6
View File
@@ -37,7 +37,6 @@
use syntax::print::pprust;
use syntax::visit::{self, Visitor};
use syntax::print::pprust::{arg_to_string, ty_to_string};
use syntax::source_map::MacroAttribute;
use syntax_pos::*;
use json_dumper::JsonDumper;
@@ -842,10 +841,10 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
let callsite = span.source_callsite();
let callsite_span = self.span_from_span(callsite);
let callee = span.source_callee()?;
let callee_span = callee.def_site?;
// Ignore attribute macros, their spans are usually mangled
if let MacroAttribute(_) = callee.format {
if let ExpnKind::Macro(MacroKind::Attr, _) |
ExpnKind::Macro(MacroKind::Derive, _) = callee.kind {
return None;
}
@@ -856,7 +855,7 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
.sess
.imported_macro_spans
.borrow()
.get(&callee_span)
.get(&callee.def_site)
{
let &(ref mac_name, mac_span) = mac;
let mac_span = self.span_from_span(mac_span);
@@ -867,10 +866,10 @@ pub fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
});
}
let callee_span = self.span_from_span(callee_span);
let callee_span = self.span_from_span(callee.def_site);
Some(MacroRef {
span: callsite_span,
qualname: callee.format.name().to_string(), // FIXME: generate the real qualname
qualname: callee.kind.descr().to_string(), // FIXME: generate the real qualname
callee_span,
})
}
+2 -2
View File
@@ -15,7 +15,7 @@
use syntax::source_map::Spanned;
use syntax::util::lev_distance::find_best_match_for_name;
use syntax_pos::Span;
use syntax_pos::hygiene::CompilerDesugaringKind;
use syntax_pos::hygiene::DesugaringKind;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::cmp;
@@ -184,7 +184,7 @@ pub fn check_pat_walk(
// In the case of `if`- and `while`-expressions we've already checked
// that `scrutinee: bool`. We know that the pattern is `true`,
// so an error here would be a duplicate and from the wrong POV.
s.is_compiler_desugaring(CompilerDesugaringKind::CondTemporary)
s.is_desugaring(DesugaringKind::CondTemporary)
})
.is_some());
}
+2 -2
View File
@@ -119,7 +119,7 @@
use rustc::ty::util::{Representability, IntTypeExt, Discr};
use rustc::ty::layout::VariantIdx;
use syntax_pos::{self, BytePos, Span, MultiSpan};
use syntax_pos::hygiene::CompilerDesugaringKind;
use syntax_pos::hygiene::DesugaringKind;
use syntax::ast;
use syntax::attr;
use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -2165,7 +2165,7 @@ fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) {
// If span arose from a desugaring of `if` or `while`, then it is the condition itself,
// which diverges, that we are about to lint on. This gives suboptimal diagnostics.
// Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
!span.is_compiler_desugaring(CompilerDesugaringKind::CondTemporary) {
!span.is_desugaring(DesugaringKind::CondTemporary) {
self.diverges.set(Diverges::WarnedAlways);
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
-1
View File
@@ -4199,7 +4199,6 @@ pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId {
MacroKind::Bang => (i, TypeKind::Macro),
MacroKind::Attr => (i, TypeKind::Attr),
MacroKind::Derive => (i, TypeKind::Derive),
MacroKind::ProcMacroStub => unreachable!(),
},
Res::Def(DefKind::TraitAlias, i) => (i, TypeKind::TraitAlias),
Res::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait),
-1
View File
@@ -92,7 +92,6 @@ fn from(item: &'a clean::Item) -> ItemType {
MacroKind::Bang => ItemType::Macro,
MacroKind::Attr => ItemType::ProcAttribute,
MacroKind::Derive => ItemType::ProcDerive,
MacroKind::ProcMacroStub => unreachable!(),
}
clean::StrippedItem(..) => unreachable!(),
}
-2
View File
@@ -2471,7 +2471,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
MacroKind::Bang => write!(fmt, "Macro ")?,
MacroKind::Attr => write!(fmt, "Attribute Macro ")?,
MacroKind::Derive => write!(fmt, "Derive Macro ")?,
MacroKind::ProcMacroStub => unreachable!(),
}
clean::PrimitiveItem(..) => write!(fmt, "Primitive Type ")?,
clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
@@ -5092,7 +5091,6 @@ fn item_proc_macro(w: &mut fmt::Formatter<'_>, cx: &Context, it: &clean::Item, m
}
write!(w, "</pre>")?;
}
_ => {}
}
document(w, cx, it)
}
@@ -429,15 +429,11 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
let segment = ast::PathSegment::from_ident(Ident::from_str(path_str));
let path = ast::Path { segments: vec![segment], span: DUMMY_SP };
cx.enter_resolver(|resolver| {
let parent_scope = resolver.dummy_parent_scope();
if let Ok(res) = resolver.resolve_macro_to_res_inner(&path, MacroKind::Bang,
&parent_scope, false, false) {
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
// skip proc-macro stubs, they'll cause `get_macro` to crash
} else {
if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind {
return Some(res.map_id(|_| panic!("unexpected id")));
}
if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
&path, MacroKind::Bang, &resolver.dummy_parent_scope(), false, false
) {
if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
return Some(res.map_id(|_| panic!("unexpected id")));
}
}
if let Some(res) = resolver.all_macros.get(&Symbol::intern(path_str)) {
+2 -5
View File
@@ -406,11 +406,8 @@ pub fn visit_item(&mut self, item: &'tcx hir::Item,
// Struct and variant constructors and proc macro stubs always show up alongside
// their definitions, we've already processed them so just discard these.
match path.res {
Res::Def(DefKind::Ctor(..), _)
| Res::SelfCtor(..)
| Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) => return,
_ => {}
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
return;
}
// If there was a private module in the current path then don't bother inlining
+2
View File
@@ -175,6 +175,7 @@ pub fn get_cloexec(&self) -> io::Result<bool> {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "linux",
target_os = "haiku")))]
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
@@ -187,6 +188,7 @@ pub fn set_cloexec(&self) -> io::Result<()> {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "linux",
target_os = "haiku"))]
pub fn set_cloexec(&self) -> io::Result<()> {
unsafe {
+30 -60
View File
@@ -10,12 +10,12 @@
use crate::ptr::P;
use crate::symbol::{kw, sym, Ident, Symbol};
use crate::{ThinVec, MACRO_ARGUMENTS};
use crate::tokenstream::{self, TokenStream};
use crate::tokenstream::{self, TokenStream, TokenTree};
use errors::{DiagnosticBuilder, DiagnosticId};
use smallvec::{smallvec, SmallVec};
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use syntax_pos::hygiene::{ExpnInfo, ExpnFormat};
use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
@@ -24,6 +24,7 @@
use std::rc::Rc;
use std::default::Default;
pub use syntax_pos::hygiene::MacroKind;
#[derive(Debug,Clone)]
pub enum Annotatable {
@@ -218,7 +219,6 @@ fn expand<'cx>(
ecx: &'cx mut ExtCtxt<'_>,
span: Span,
input: TokenStream,
def_span: Option<Span>,
) -> Box<dyn MacResult+'cx>;
}
@@ -235,7 +235,6 @@ fn expand<'cx>(
ecx: &'cx mut ExtCtxt<'_>,
span: Span,
input: TokenStream,
_def_span: Option<Span>,
) -> Box<dyn MacResult+'cx> {
struct AvoidInterpolatedIdents;
@@ -518,37 +517,6 @@ fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
}
}
/// Represents different kinds of macro invocations that can be resolved.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum MacroKind {
/// A bang macro - foo!()
Bang,
/// An attribute macro - #[foo]
Attr,
/// A derive attribute macro - #[derive(Foo)]
Derive,
/// A view of a procedural macro from the same crate that defines it.
ProcMacroStub,
}
impl MacroKind {
pub fn descr(self) -> &'static str {
match self {
MacroKind::Bang => "macro",
MacroKind::Attr => "attribute macro",
MacroKind::Derive => "derive macro",
MacroKind::ProcMacroStub => "crate-local procedural macro",
}
}
pub fn article(self) -> &'static str {
match self {
MacroKind::Attr => "an",
_ => "a",
}
}
}
/// A syntax extension kind.
pub enum SyntaxExtensionKind {
/// A token-based function-like macro.
@@ -672,19 +640,31 @@ pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
}
}
fn expn_format(&self, symbol: Symbol) -> ExpnFormat {
match self.kind {
SyntaxExtensionKind::Bang(..) |
SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol),
_ => ExpnFormat::MacroAttribute(symbol),
pub fn dummy_bang(edition: Edition) -> SyntaxExtension {
fn expander<'cx>(_: &'cx mut ExtCtxt<'_>, span: Span, _: &[TokenTree])
-> Box<dyn MacResult + 'cx> {
DummyResult::any(span)
}
SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition)
}
pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo {
pub fn dummy_derive(edition: Edition) -> SyntaxExtension {
fn expander(_: &mut ExtCtxt<'_>, _: Span, _: &ast::MetaItem, _: Annotatable)
-> Vec<Annotatable> {
Vec::new()
}
SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition)
}
pub fn non_macro_attr(mark_used: bool, edition: Edition) -> SyntaxExtension {
SyntaxExtension::default(SyntaxExtensionKind::NonMacroAttr { mark_used }, edition)
}
pub fn expn_info(&self, call_site: Span, descr: Symbol) -> ExpnInfo {
ExpnInfo {
call_site,
format: self.expn_format(Symbol::intern(format)),
def_site: Some(self.span),
kind: ExpnKind::Macro(self.macro_kind(), descr),
def_site: self.span,
default_transparency: self.default_transparency,
allow_internal_unstable: self.allow_internal_unstable.clone(),
allow_internal_unsafe: self.allow_internal_unsafe,
@@ -696,6 +676,9 @@ pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo {
pub type NamedSyntaxExtension = (Name, SyntaxExtension);
/// Error type that denotes indeterminacy.
pub struct Indeterminate;
pub trait Resolver {
fn next_node_id(&mut self) -> ast::NodeId;
@@ -709,26 +692,11 @@ fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFra
fn resolve_imports(&mut self);
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Mark,
derives_in_scope: Vec<ast::Path>, force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy>;
-> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
fn check_unused_macros(&self);
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Determinacy {
Determined,
Undetermined,
}
impl Determinacy {
pub fn determined(determined: bool) -> Determinacy {
if determined { Determinacy::Determined } else { Determinacy::Undetermined }
}
}
#[derive(Clone)]
pub struct ModuleData {
pub mod_path: Vec<ast::Ident>,
@@ -753,6 +721,7 @@ pub struct ExtCtxt<'a> {
pub resolver: &'a mut dyn Resolver,
pub current_expansion: ExpansionData,
pub expansions: FxHashMap<Span, Vec<String>>,
pub allow_derive_markers: Lrc<[Symbol]>,
}
impl<'a> ExtCtxt<'a> {
@@ -772,6 +741,7 @@ pub fn new(parse_sess: &'a parse::ParseSess,
directory_ownership: DirectoryOwnership::Owned { relative: None },
},
expansions: FxHashMap::default(),
allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(),
}
}
@@ -810,7 +780,7 @@ pub fn expansion_cause(&self) -> Option<Span> {
let mut last_macro = None;
loop {
if ctxt.outer_expn_info().map_or(None, |info| {
if info.format.name() == sym::include {
if info.kind.descr() == sym::include {
// Stop going up the backtrace once include! is encountered
return None;
}
+6 -9
View File
@@ -1,14 +1,13 @@
use crate::attr::HasAttrs;
use crate::ast;
use crate::source_map::{ExpnInfo, ExpnFormat};
use crate::ext::base::ExtCtxt;
use crate::source_map::{ExpnInfo, ExpnKind};
use crate::ext::base::{ExtCtxt, MacroKind};
use crate::ext::build::AstBuilder;
use crate::parse::parser::PathStyle;
use crate::symbol::{Symbol, sym};
use crate::errors::Applicability;
use syntax_pos::Span;
use rustc_data_structures::fx::FxHashSet;
pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
@@ -46,7 +45,7 @@ pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) ->
pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T)
where T: HasAttrs,
{
let (mut names, mut pretty_name) = (FxHashSet::default(), "derive(".to_owned());
let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
for (i, path) in traits.iter().enumerate() {
if i > 0 {
pretty_name.push_str(", ");
@@ -54,14 +53,12 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
pretty_name.push_str(&path.to_string());
names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
}
pretty_name.push(')');
cx.current_expansion.mark.set_expn_info(ExpnInfo::with_unstable(
ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), span, cx.parse_sess.edition,
&[sym::rustc_attrs, sym::structural_match],
let span = span.fresh_expansion(cx.current_expansion.mark, ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
cx.parse_sess.edition, cx.allow_derive_markers.clone(),
));
let span = span.with_ctxt(cx.backtrace());
item.visit_attrs(|attrs| {
if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
let meta = cx.meta_word(span, sym::structural_match);
+173 -229
View File
@@ -5,7 +5,7 @@
use crate::config::StripUnconfigured;
use crate::ext::base::*;
use crate::ext::derive::{add_derived_markers, collect_derives};
use crate::ext::hygiene::{Mark, SyntaxContext};
use crate::ext::hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind};
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use crate::mut_visit::*;
@@ -158,8 +158,8 @@ impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> {
}
impl AstFragmentKind {
fn dummy(self, span: Span) -> Option<AstFragment> {
self.make_from(DummyResult::any(span))
fn dummy(self, span: Span) -> AstFragment {
self.make_from(DummyResult::any(span)).expect("couldn't create a dummy AST fragment")
}
fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
@@ -199,25 +199,34 @@ pub enum InvocationKind {
span: Span,
},
Attr {
attr: Option<ast::Attribute>,
traits: Vec<Path>,
attr: ast::Attribute,
item: Annotatable,
// Required for resolving derive helper attributes.
derives: Vec<Path>,
// We temporarily report errors for attribute macros placed after derives
after_derive: bool,
},
Derive {
path: Path,
item: Annotatable,
item_with_markers: Annotatable,
},
/// "Invocation" that contains all derives from an item,
/// broken into multiple `Derive` invocations when expanded.
/// FIXME: Find a way to remove it.
DeriveContainer {
derives: Vec<Path>,
item: Annotatable,
},
}
impl Invocation {
pub fn span(&self) -> Span {
match self.kind {
InvocationKind::Bang { span, .. } => span,
InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,
InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
InvocationKind::Derive { ref path, .. } => path.span,
match &self.kind {
InvocationKind::Bang { span, .. } => *span,
InvocationKind::Attr { attr, .. } => attr.span,
InvocationKind::Derive { path, .. } => path.span,
InvocationKind::DeriveContainer { item, .. } => item.span(),
}
}
}
@@ -312,9 +321,8 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let scope =
if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
let ext = match self.cx.resolver.resolve_macro_invocation(&invoc, scope, force) {
Ok(ext) => Some(ext),
Err(Determinacy::Determined) => None,
Err(Determinacy::Undetermined) => {
Ok(ext) => ext,
Err(Indeterminate) => {
undetermined_invocations.push(invoc);
continue
}
@@ -323,73 +331,62 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
progress = true;
let ExpansionData { depth, mark, .. } = invoc.expansion_data;
self.cx.current_expansion = invoc.expansion_data.clone();
self.cx.current_expansion.mark = scope;
// FIXME(jseyfried): Refactor out the following logic
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
if let Some(ext) = ext {
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
invoc_fragment_kind.dummy(invoc_span).unwrap()
});
self.collect_invocations(fragment, &[])
} else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind {
if !item.derive_allowed() {
let attr = attr::find_by_name(item.attrs(), sym::derive)
.expect("`derive` attribute should exist");
let span = attr.span;
let mut err = self.cx.mut_span_err(span,
"`derive` may only be applied to \
structs, enums and unions");
if let ast::AttrStyle::Inner = attr.style {
let trait_list = traits.iter()
.map(|t| t.to_string()).collect::<Vec<_>>();
let suggestion = format!("#[derive({})]", trait_list.join(", "));
err.span_suggestion(
span, "try an outer attribute", suggestion,
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
Applicability::MaybeIncorrect
);
}
err.emit();
let fragment = self.expand_invoc(invoc, &ext.kind);
self.collect_invocations(fragment, &[])
} else if let InvocationKind::DeriveContainer { derives: traits, item } = invoc.kind {
if !item.derive_allowed() {
let attr = attr::find_by_name(item.attrs(), sym::derive)
.expect("`derive` attribute should exist");
let span = attr.span;
let mut err = self.cx.mut_span_err(span,
"`derive` may only be applied to \
structs, enums and unions");
if let ast::AttrStyle::Inner = attr.style {
let trait_list = traits.iter()
.map(|t| t.to_string()).collect::<Vec<_>>();
let suggestion = format!("#[derive({})]", trait_list.join(", "));
err.span_suggestion(
span, "try an outer attribute", suggestion,
// We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT
Applicability::MaybeIncorrect
);
}
let mut item = self.fully_configure(item);
item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
let mut item_with_markers = item.clone();
add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
let derives = derives.entry(invoc.expansion_data.mark).or_default();
derives.reserve(traits.len());
invocations.reserve(traits.len());
for path in &traits {
let mark = Mark::fresh(self.cx.current_expansion.mark);
derives.push(mark);
let item = match self.cx.resolver.resolve_macro_path(
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
Ok(ext) => match ext.kind {
SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(),
_ => item.clone(),
},
_ => item.clone(),
};
invocations.push(Invocation {
kind: InvocationKind::Derive { path: path.clone(), item },
fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
mark,
..invoc.expansion_data.clone()
},
});
}
let fragment = invoc.fragment_kind
.expect_from_annotatables(::std::iter::once(item_with_markers));
self.collect_invocations(fragment, derives)
} else {
unreachable!()
err.emit();
}
let mut item = self.fully_configure(item);
item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
let mut item_with_markers = item.clone();
add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
let derives = derives.entry(invoc.expansion_data.mark).or_default();
derives.reserve(traits.len());
invocations.reserve(traits.len());
for path in traits {
let mark = Mark::fresh(self.cx.current_expansion.mark, None);
derives.push(mark);
invocations.push(Invocation {
kind: InvocationKind::Derive {
path,
item: item.clone(),
item_with_markers: item_with_markers.clone(),
},
fragment_kind: invoc.fragment_kind,
expansion_data: ExpansionData {
mark,
..invoc.expansion_data.clone()
},
});
}
let fragment = invoc.fragment_kind
.expect_from_annotatables(::std::iter::once(item_with_markers));
self.collect_invocations(fragment, derives)
} else {
self.collect_invocations(invoc.fragment_kind.dummy(invoc.span()).unwrap(), &[])
unreachable!()
};
if expanded_fragments.len() < depth {
@@ -485,28 +482,22 @@ fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
}
}
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
!self.cx.ecfg.macros_in_extern() {
if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else {
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
if fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern() {
if let SyntaxExtensionKind::NonMacroAttr { .. } = ext {} else {
emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
invoc.span(), GateIssue::Language,
span, GateIssue::Language,
"macro invocations in `extern {}` blocks are experimental");
}
}
let result = match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
InvocationKind::Derive { .. } => self.expand_derive_invoc(invoc, ext)?,
};
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
let info = self.cx.current_expansion.mark.expn_info().unwrap();
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
let mut err = self.cx.struct_span_err(info.call_site,
&format!("recursion limit reached while expanding the macro `{}`",
info.format.name()));
info.kind.descr()));
err.help(&format!(
"consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
suggested_limit));
@@ -515,61 +506,87 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<A
FatalError.raise();
}
Some(result)
}
fn expand_attr_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
-> Option<AstFragment> {
let (attr, mut item) = match invoc.kind {
InvocationKind::Attr { attr, item, .. } => (attr?, item),
_ => unreachable!(),
};
match &ext.kind {
SyntaxExtensionKind::NonMacroAttr { mark_used } => {
attr::mark_known(&attr);
if *mark_used {
attr::mark_used(&attr);
match invoc.kind {
InvocationKind::Bang { mac, .. } => match ext {
SyntaxExtensionKind::Bang(expander) => {
self.gate_proc_macro_expansion_kind(span, fragment_kind);
let tok_result = expander.expand(self.cx, span, mac.node.stream());
let result =
self.parse_ast_fragment(tok_result, fragment_kind, &mac.node.path, span);
self.gate_proc_macro_expansion(span, &result);
result
}
item.visit_attrs(|attrs| attrs.push(attr));
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
SyntaxExtensionKind::LegacyBang(expander) => {
let tok_result = expander.expand(self.cx, span, mac.node.stream());
if let Some(result) = fragment_kind.make_from(tok_result) {
result
} else {
let msg = format!("non-{kind} macro in {kind} position: {path}",
kind = fragment_kind.name(), path = mac.node.path);
self.cx.span_err(span, &msg);
self.cx.trace_macros_diag();
fragment_kind.dummy(span)
}
}
_ => unreachable!()
}
SyntaxExtensionKind::LegacyAttr(expander) => {
let meta = attr.parse_meta(self.cx.parse_sess)
.map_err(|mut e| { e.emit(); }).ok()?;
let item = expander.expand(self.cx, attr.span, &meta, item);
Some(invoc.fragment_kind.expect_from_annotatables(item))
InvocationKind::Attr { attr, mut item, .. } => match ext {
SyntaxExtensionKind::Attr(expander) => {
self.gate_proc_macro_attr_item(span, &item);
let item_tok = TokenTree::token(token::Interpolated(Lrc::new(match item {
Annotatable::Item(item) => token::NtItem(item),
Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
Annotatable::Expr(expr) => token::NtExpr(expr),
})), DUMMY_SP).into();
let input = self.extract_proc_macro_attr_input(attr.tokens, span);
let tok_result = expander.expand(self.cx, span, input, item_tok);
let res = self.parse_ast_fragment(tok_result, fragment_kind, &attr.path, span);
self.gate_proc_macro_expansion(span, &res);
res
}
SyntaxExtensionKind::LegacyAttr(expander) => {
match attr.parse_meta(self.cx.parse_sess) {
Ok(meta) => {
let item = expander.expand(self.cx, span, &meta, item);
fragment_kind.expect_from_annotatables(item)
}
Err(mut err) => {
err.emit();
fragment_kind.dummy(span)
}
}
}
SyntaxExtensionKind::NonMacroAttr { mark_used } => {
attr::mark_known(&attr);
if *mark_used {
attr::mark_used(&attr);
}
item.visit_attrs(|attrs| attrs.push(attr));
fragment_kind.expect_from_annotatables(iter::once(item))
}
_ => unreachable!()
}
SyntaxExtensionKind::Attr(expander) => {
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),
Annotatable::TraitItem(item) => token::NtTraitItem(item.into_inner()),
Annotatable::ImplItem(item) => token::NtImplItem(item.into_inner()),
Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
Annotatable::Expr(expr) => token::NtExpr(expr),
})), DUMMY_SP).into();
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
let tok_result = expander.expand(self.cx, attr.span, input, item_tok);
let res = self.parse_ast_fragment(tok_result, invoc.fragment_kind,
&attr.path, attr.span);
self.gate_proc_macro_expansion(attr.span, &res);
res
}
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::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)
}
_ => {
let msg = &format!("macro `{}` may not be used in attributes", attr.path);
self.cx.span_err(attr.span, msg);
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(attr.span)
InvocationKind::Derive { path, item, item_with_markers } => match ext {
SyntaxExtensionKind::Derive(expander) |
SyntaxExtensionKind::LegacyDerive(expander) => {
let (path, item) = match ext {
SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers),
_ => (path, item),
};
if !item.derive_allowed() {
return fragment_kind.dummy(span);
}
let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span, path };
let span = span.with_ctxt(self.cx.backtrace());
let items = expander.expand(self.cx, span, &meta, item);
fragment_kind.expect_from_annotatables(items)
}
_ => unreachable!()
}
InvocationKind::DeriveContainer { .. } => unreachable!()
}
}
@@ -616,14 +633,10 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
);
}
fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) {
if self.cx.ecfg.proc_macro_hygiene() {
return
}
let fragment = match fragment {
Some(fragment) => fragment,
None => return,
};
fragment.visit_with(&mut DisallowMacros {
span,
@@ -655,58 +668,6 @@ fn visit_mac(&mut self, _mac: &'ast ast::Mac) {
}
}
/// Expand a macro invocation. Returns the resulting expanded AST fragment.
fn expand_bang_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
-> Option<AstFragment> {
let kind = invoc.fragment_kind;
let (mac, span) = match invoc.kind {
InvocationKind::Bang { mac, span } => (mac, span),
_ => unreachable!(),
};
let path = &mac.node.path;
let opt_expanded = match &ext.kind {
SyntaxExtensionKind::Bang(expander) => {
self.gate_proc_macro_expansion_kind(span, kind);
let tok_result = expander.expand(self.cx, span, mac.node.stream());
let result = self.parse_ast_fragment(tok_result, kind, path, span);
self.gate_proc_macro_expansion(span, &result);
result
}
SyntaxExtensionKind::LegacyBang(expander) => {
let tok_result = expander.expand(self.cx, span, mac.node.stream(), Some(ext.span));
kind.make_from(tok_result)
}
SyntaxExtensionKind::Attr(..) |
SyntaxExtensionKind::LegacyAttr(..) |
SyntaxExtensionKind::NonMacroAttr { .. } => {
self.cx.span_err(path.span,
&format!("`{}` can only be used in attributes", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}
};
if opt_expanded.is_some() {
opt_expanded
} else {
let msg = format!("non-{kind} macro in {kind} position: {name}",
name = path.segments[0].ident.name, kind = kind.name());
self.cx.span_err(path.span, &msg);
self.cx.trace_macros_diag();
kind.dummy(span)
}
}
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
AstFragmentKind::Expr => "expressions",
@@ -731,47 +692,17 @@ fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
);
}
/// Expand a derive invocation. Returns the resulting expanded AST fragment.
fn expand_derive_invoc(&mut self,
invoc: Invocation,
ext: &SyntaxExtension)
-> Option<AstFragment> {
let (path, item) = match invoc.kind {
InvocationKind::Derive { path, item } => (path, item),
_ => unreachable!(),
};
if !item.derive_allowed() {
return None;
}
match &ext.kind {
SyntaxExtensionKind::Derive(expander) |
SyntaxExtensionKind::LegacyDerive(expander) => {
let meta = ast::MetaItem { node: ast::MetaItemKind::Word, span: path.span, path };
let span = meta.span.with_ctxt(self.cx.backtrace());
let items = expander.expand(self.cx, span, &meta, item);
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
_ => {
let msg = &format!("macro `{}` may not be used for derive attributes", path);
self.cx.span_err(path.span, msg);
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(path.span)
}
}
}
fn parse_ast_fragment(&mut self,
toks: TokenStream,
kind: AstFragmentKind,
path: &Path,
span: Span)
-> Option<AstFragment> {
-> AstFragment {
let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>());
match parser.parse_ast_fragment(kind, false) {
Ok(fragment) => {
parser.ensure_complete_parse(path, kind.name(), span);
Some(fragment)
fragment
}
Err(mut err) => {
err.set_span(span);
@@ -881,7 +812,17 @@ struct InvocationCollector<'a, 'b> {
impl<'a, 'b> InvocationCollector<'a, 'b> {
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
let mark = Mark::fresh(self.cx.current_expansion.mark);
// Expansion info for all the collected invocations is set upon their resolution,
// with exception of the derive container case which is not resolved and can get
// its expansion info immediately.
let expn_info = match &kind {
InvocationKind::DeriveContainer { item, .. } => Some(ExpnInfo::default(
ExpnKind::Macro(MacroKind::Attr, sym::derive),
item.span(), self.cx.parse_sess.edition,
)),
_ => None,
};
let mark = Mark::fresh(self.cx.current_expansion.mark, expn_info);
self.invocations.push(Invocation {
kind,
fragment_kind,
@@ -900,12 +841,15 @@ fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) ->
fn collect_attr(&mut self,
attr: Option<ast::Attribute>,
traits: Vec<Path>,
derives: Vec<Path>,
item: Annotatable,
kind: AstFragmentKind,
after_derive: bool)
-> AstFragment {
self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
self.collect(kind, match attr {
Some(attr) => InvocationKind::Attr { attr, item, derives, after_derive },
None => InvocationKind::DeriveContainer { derives, item },
})
}
fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)
+6 -8
View File
@@ -88,6 +88,7 @@ pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFrag
struct MacroRulesMacroExpander {
name: ast::Ident,
span: Span,
lhses: Vec<quoted::TokenTree>,
rhses: Vec<quoted::TokenTree>,
valid: bool,
@@ -99,12 +100,11 @@ fn expand<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
input: TokenStream,
def_span: Option<Span>,
) -> Box<dyn MacResult + 'cx> {
if !self.valid {
return DummyResult::any(sp);
}
generic_extension(cx, sp, def_span, self.name, input, &self.lhses, &self.rhses)
generic_extension(cx, sp, self.span, self.name, input, &self.lhses, &self.rhses)
}
}
@@ -117,7 +117,7 @@ fn trace_macros_note(cx: &mut ExtCtxt<'_>, sp: Span, message: String) {
fn generic_extension<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
def_span: Option<Span>,
def_span: Span,
name: ast::Ident,
arg: TokenStream,
lhses: &[quoted::TokenTree],
@@ -199,10 +199,8 @@ fn generic_extension<'cx>(
let span = token.span.substitute_dummy(sp);
let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
err.span_label(span, label);
if let Some(sp) = def_span {
if cx.source_map().span_to_filename(sp).is_real() && !sp.is_dummy() {
err.span_label(cx.source_map().def_span(sp), "when calling this macro");
}
if !def_span.is_dummy() && cx.source_map().span_to_filename(def_span).is_real() {
err.span_label(cx.source_map().def_span(def_span), "when calling this macro");
}
// Check whether there's a missing comma in this macro call, like `println!("{}" a);`
@@ -377,7 +375,7 @@ pub fn compile(
}
let expander: Box<_> =
Box::new(MacroRulesMacroExpander { name: def.ident, lhses, rhses, valid });
Box::new(MacroRulesMacroExpander { name: def.ident, span: def.span, lhses, rhses, valid });
let (default_transparency, transparency_error) =
attr::find_transparency(&def.attrs, body.legacy);
+4 -5
View File
@@ -170,7 +170,7 @@ struct DiagnosticSpanMacroExpansion {
macro_decl_name: String,
/// span where macro was defined (if known)
def_site_span: Option<DiagnosticSpan>,
def_site_span: DiagnosticSpan,
}
#[derive(RustcEncodable)]
@@ -300,14 +300,13 @@ fn from_span_full(span: Span,
None,
backtrace,
je);
let def_site_span = bt.def_site_span.map(|sp| {
Self::from_span_full(sp,
let def_site_span =
Self::from_span_full(bt.def_site_span,
false,
None,
None,
vec![].into_iter(),
je)
});
je);
Box::new(DiagnosticSpanMacroExpansion {
span: call_site,
macro_decl_name: bt.macro_decl_name,
+1 -3
View File
@@ -7,10 +7,8 @@
//! within the SourceMap, which upon request can be converted to line and column
//! information, source code snippets, etc.
pub use syntax_pos::*;
pub use syntax_pos::hygiene::{ExpnFormat, ExpnInfo};
pub use ExpnFormat::*;
pub use syntax_pos::hygiene::{ExpnKind, ExpnInfo};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
+8 -15
View File
@@ -1,26 +1,15 @@
use crate::ast;
use crate::attr;
use crate::edition::Edition;
use crate::ext::hygiene::{Mark, SyntaxContext};
use crate::ext::hygiene::{Mark, MacroKind};
use crate::symbol::{Ident, Symbol, kw, sym};
use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, respan};
use crate::source_map::{ExpnInfo, ExpnKind, dummy_spanned, respan};
use crate::ptr::P;
use crate::tokenstream::TokenStream;
use std::cell::Cell;
use std::iter;
use syntax_pos::{DUMMY_SP, Span};
/// Craft a span that will be ignored by the stability lint's
/// call to source_map's `is_internal` check.
/// The expanded code uses the unstable `#[prelude_import]` attribute.
fn ignored_span(sp: Span, edition: Edition) -> Span {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(Symbol::intern("std_inject")), sp, edition, &[sym::prelude_import]
));
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
}
use syntax_pos::DUMMY_SP;
pub fn injected_crate_name() -> Option<&'static str> {
INJECTED_CRATE_NAME.with(|name| name.get())
@@ -86,7 +75,11 @@ pub fn maybe_inject_crates_ref(
INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
let span = ignored_span(DUMMY_SP, edition);
let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::std_inject), DUMMY_SP, edition,
[sym::prelude_import][..].into(),
));
krate.module.items.insert(0, P(ast::Item {
attrs: vec![ast::Attribute {
style: ast::AttrStyle::Outer,
+7 -20
View File
@@ -15,13 +15,13 @@
use syntax_pos::{DUMMY_SP, NO_EXPANSION, Span, SourceFile, BytePos};
use crate::attr::{self, HasAttrs};
use crate::source_map::{self, SourceMap, ExpnInfo, MacroAttribute, dummy_spanned, respan};
use crate::source_map::{self, SourceMap, ExpnInfo, ExpnKind, dummy_spanned, respan};
use crate::config;
use crate::entry::{self, EntryPointType};
use crate::ext::base::{ExtCtxt, Resolver};
use crate::ext::build::AstBuilder;
use crate::ext::expand::ExpansionConfig;
use crate::ext::hygiene::{self, Mark, SyntaxContext};
use crate::ext::hygiene::{self, Mark, SyntaxContext, MacroKind};
use crate::mut_visit::{*, ExpectOne};
use crate::feature_gate::Features;
use crate::util::map_in_place::MapInPlace;
@@ -43,7 +43,6 @@ struct TestCtxt<'a> {
test_cases: Vec<Test>,
reexport_test_harness_main: Option<Symbol>,
is_libtest: bool,
ctxt: SyntaxContext,
features: &'a Features,
test_runner: Option<ast::Path>,
@@ -259,8 +258,6 @@ fn generate_test_harness(sess: &ParseSess,
let mut cleaner = EntryPointCleaner { depth: 0 };
cleaner.visit_crate(krate);
let mark = Mark::fresh(Mark::root());
let mut econfig = ExpansionConfig::default("test".to_string());
econfig.features = Some(features);
@@ -274,16 +271,10 @@ fn generate_test_harness(sess: &ParseSess,
is_libtest: attr::find_crate_name(&krate.attrs)
.map(|s| s == sym::test).unwrap_or(false),
toplevel_reexport: None,
ctxt: SyntaxContext::empty().apply_mark(mark),
features,
test_runner
};
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(sym::test_case), DUMMY_SP, sess.edition,
&[sym::main, sym::test, sym::rustc_attrs],
));
TestHarnessGenerator {
cx,
tests: Vec::new(),
@@ -291,13 +282,6 @@ fn generate_test_harness(sess: &ParseSess,
}.visit_crate(krate);
}
/// Craft a span that will be ignored by the stability lint's
/// call to source_map's `is_internal` check.
/// The expanded code calls some unstable functions in the test crate.
fn ignored_span(cx: &TestCtxt<'_>, sp: Span) -> Span {
sp.with_ctxt(cx.ctxt)
}
enum HasTestSignature {
Yes,
No(BadTestSignature),
@@ -314,12 +298,15 @@ enum BadTestSignature {
/// Creates a function item for use as the main function of a test build.
/// This function will call the `test_runner` as specified by the crate attribute
fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
// Writing this out by hand with 'ignored_span':
// Writing this out by hand:
// pub fn main() {
// #![main]
// test::test_main_static(&[..tests]);
// }
let sp = ignored_span(cx, DUMMY_SP);
let sp = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::test_case), DUMMY_SP, cx.ext_cx.parse_sess.edition,
[sym::main, sym::test, sym::rustc_attrs][..].into(),
));
let ecx = &cx.ext_cx;
let test_id = Ident::with_empty_ctxt(sym::test);
+15 -7
View File
@@ -72,6 +72,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
let mut register = |name, ext| {
resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext));
};
macro_rules! register {
($( $name:ident: $f:expr, )*) => { $(
register(sym::$name, SyntaxExtension::default(
@@ -125,24 +126,31 @@ macro_rules! register_unstable {
trace_macros: trace_macros::expand_trace_macros,
}
let allow_internal_unstable = Some([sym::test, sym::rustc_attrs][..].into());
register(sym::test_case, SyntaxExtension {
stability: Some(Stability::unstable(
sym::custom_test_frameworks,
Some(Symbol::intern(EXPLAIN_CUSTOM_TEST_FRAMEWORKS)),
50297,
)),
allow_internal_unstable: allow_internal_unstable.clone(),
..SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test_case::expand)), edition
)
});
register(sym::test, SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition
));
register(sym::bench, SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition
));
register(sym::test, SyntaxExtension {
allow_internal_unstable: allow_internal_unstable.clone(),
..SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_test)), edition
)
});
register(sym::bench, SyntaxExtension {
allow_internal_unstable,
..SyntaxExtension::default(
SyntaxExtensionKind::LegacyAttr(Box::new(test::expand_bench)), edition
)
});
// format_args uses `unstable` things internally.
let allow_internal_unstable = Some([sym::fmt_internals][..].into());
register(sym::format_args, SyntaxExtension {
allow_internal_unstable: allow_internal_unstable.clone(),
+5 -7
View File
@@ -4,8 +4,8 @@
use syntax::ast::{self, Ident};
use syntax::attr;
use syntax::source_map::{ExpnInfo, MacroAttribute, respan};
use syntax::ext::base::ExtCtxt;
use syntax::source_map::{ExpnInfo, ExpnKind, respan};
use syntax::ext::base::{ExtCtxt, MacroKind};
use syntax::ext::build::AstBuilder;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::hygiene::Mark;
@@ -346,12 +346,10 @@ fn mk_decls(
custom_attrs: &[ProcMacroDef],
custom_macros: &[ProcMacroDef],
) -> P<ast::Item> {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
&[sym::rustc_attrs, Symbol::intern("proc_macro_internals")],
let span = DUMMY_SP.fresh_expansion(Mark::root(), ExpnInfo::allow_unstable(
ExpnKind::Macro(MacroKind::Attr, sym::proc_macro), DUMMY_SP, cx.parse_sess.edition,
[sym::rustc_attrs, sym::proc_macro_internals][..].into(),
));
let span = DUMMY_SP.apply_mark(mark);
let hidden = cx.meta_list_item_word(span, sym::hidden);
let doc = cx.meta_list(span, sym::doc, vec![hidden]);
+3 -11
View File
@@ -3,13 +3,12 @@
use syntax::ext::base::*;
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ext::hygiene::SyntaxContext;
use syntax::attr;
use syntax::ast;
use syntax::print::pprust;
use syntax::symbol::{Symbol, sym};
use syntax_pos::Span;
use syntax::source_map::{ExpnInfo, MacroAttribute};
use std::iter;
pub fn expand_test(
@@ -60,15 +59,8 @@ pub fn expand_test_or_bench(
return vec![Annotatable::Item(item)];
}
let (sp, attr_sp) = {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(sym::test), attr_sp, cx.parse_sess.edition,
&[sym::rustc_attrs, sym::test],
));
(item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)),
attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)))
};
let ctxt = SyntaxContext::empty().apply_mark(cx.current_expansion.mark);
let (sp, attr_sp) = (item.span.with_ctxt(ctxt), attr_sp.with_ctxt(ctxt));
// Gensym "test" so we can extern crate without conflicting with any local names
let test_id = cx.ident_of("test").gensym();
+2 -12
View File
@@ -11,12 +11,11 @@
use syntax::ext::base::*;
use syntax::ext::build::AstBuilder;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::ext::hygiene::SyntaxContext;
use syntax::ast;
use syntax::source_map::respan;
use syntax::symbol::sym;
use syntax_pos::Span;
use syntax::source_map::{ExpnInfo, MacroAttribute};
pub fn expand(
ecx: &mut ExtCtxt<'_>,
@@ -26,17 +25,8 @@ pub fn expand(
) -> Vec<Annotatable> {
if !ecx.ecfg.should_test { return vec![]; }
let sp = {
let mark = Mark::fresh(Mark::root());
mark.set_expn_info(ExpnInfo::with_unstable(
MacroAttribute(sym::test_case), attr_sp, ecx.parse_sess.edition,
&[sym::test, sym::rustc_attrs],
));
attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
};
let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.mark));
let mut item = anno_item.expect_item();
item = item.map(|mut item| {
item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
item.ident = item.ident.gensym();
+120 -114
View File
@@ -26,20 +26,20 @@
// trigger runtime aborts. (Fortunately these are obvious and easy to fix.)
use crate::GLOBALS;
use crate::Span;
use crate::{Span, DUMMY_SP};
use crate::edition::Edition;
use crate::symbol::{kw, Symbol};
use serialize::{Encodable, Decodable, Encoder, Decoder};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
use std::fmt;
/// A SyntaxContext represents a chain of macro expansions (represented by marks).
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SyntaxContext(u32);
#[derive(Copy, Clone, Debug)]
#[derive(Debug)]
struct SyntaxContextData {
outer_mark: Mark,
transparency: Transparency,
@@ -53,12 +53,15 @@ struct SyntaxContextData {
}
/// A mark is a unique ID associated with a macro expansion.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Mark(u32);
#[derive(Clone, Debug)]
#[derive(Debug)]
struct MarkData {
parent: Mark,
/// Each mark should have an associated expansion info, but sometimes there's a delay between
/// creation of a mark and obtaining its info (e.g. macros are collected first and then
/// resolved later), so we use an `Option` here.
expn_info: Option<ExpnInfo>,
}
@@ -82,11 +85,8 @@ pub enum Transparency {
}
impl Mark {
pub fn fresh(parent: Mark) -> Self {
HygieneData::with(|data| {
data.marks.push(MarkData { parent, expn_info: None });
Mark(data.marks.len() as u32 - 1)
})
pub fn fresh(parent: Mark, expn_info: Option<ExpnInfo>) -> Self {
HygieneData::with(|data| data.fresh_mark(parent, expn_info))
}
/// The mark of the theoretical expansion that generates freshly parsed, unexpanded AST.
@@ -117,7 +117,11 @@ pub fn expn_info(self) -> Option<ExpnInfo> {
#[inline]
pub fn set_expn_info(self, info: ExpnInfo) {
HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
HygieneData::with(|data| {
let old_info = &mut data.marks[self.0 as usize].expn_info;
assert!(old_info.is_none(), "expansion info is reset for a mark");
*old_info = Some(info);
})
}
pub fn is_descendant_of(self, ancestor: Mark) -> bool {
@@ -130,42 +134,14 @@ pub fn outer_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
HygieneData::with(|data| data.is_descendant_of(self, data.outer(ctxt)))
}
/// Computes a mark such that both input marks are descendants of (or equal to) the returned
/// mark. That is, the following holds:
///
/// ```rust
/// let la = least_ancestor(a, b);
/// assert!(a.is_descendant_of(la))
/// assert!(b.is_descendant_of(la))
/// ```
pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
HygieneData::with(|data| {
// Compute the path from a to the root
let mut a_path = FxHashSet::<Mark>::default();
while a != Mark::root() {
a_path.insert(a);
a = data.marks[a.0 as usize].parent;
}
// While the path from b to the root hasn't intersected, move up the tree
while !a_path.contains(&b) {
b = data.marks[b.0 as usize].parent;
}
b
})
}
// Used for enabling some compatibility fallback in resolve.
#[inline]
pub fn looks_like_proc_macro_derive(self) -> bool {
HygieneData::with(|data| {
if data.default_transparency(self) == Transparency::Opaque {
if let Some(expn_info) = &data.marks[self.0 as usize].expn_info {
if let ExpnFormat::MacroAttribute(name) = expn_info.format {
if name.as_str().starts_with("derive(") {
return true;
}
if let Some(expn_info) = data.expn_info(self) {
if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind {
return true;
}
}
}
@@ -182,11 +158,11 @@ pub fn looks_like_proc_macro_derive(self) -> bool {
}
impl HygieneData {
crate fn new() -> Self {
crate fn new(edition: Edition) -> Self {
HygieneData {
marks: vec![MarkData {
parent: Mark::root(),
expn_info: None,
expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)),
}],
syntax_contexts: vec![SyntaxContextData {
outer_mark: Mark::root(),
@@ -204,8 +180,21 @@ fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
}
fn fresh_mark(&mut self, parent: Mark, expn_info: Option<ExpnInfo>) -> Mark {
self.marks.push(MarkData { parent, expn_info });
Mark(self.marks.len() as u32 - 1)
}
fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> {
self.marks[mark.0 as usize].expn_info.as_ref()
if mark != Mark::root() {
Some(self.marks[mark.0 as usize].expn_info.as_ref()
.expect("no expansion info for a mark"))
} else {
// FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion".
// Introduce a method for checking for "no expansion" instead and always return
// `ExpnInfo` from this function instead of the `Option`.
None
}
}
fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
@@ -219,7 +208,7 @@ fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
}
fn default_transparency(&self, mark: Mark) -> Transparency {
self.marks[mark.0 as usize].expn_info.as_ref().map_or(
self.expn_info(mark).map_or(
Transparency::SemiTransparent, |einfo| einfo.default_transparency
)
}
@@ -420,33 +409,6 @@ pub const fn empty() -> Self {
SyntaxContext(raw)
}
// Allocate a new SyntaxContext with the given ExpnInfo. This is used when
// deserializing Spans from the incr. comp. cache.
// FIXME(mw): This method does not restore MarkData::parent or
// SyntaxContextData::prev_ctxt or SyntaxContextData::opaque. These things
// don't seem to be used after HIR lowering, so everything should be fine
// as long as incremental compilation does not kick in before that.
pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
HygieneData::with(|data| {
data.marks.push(MarkData {
parent: Mark::root(),
expn_info: Some(expansion_info),
});
let mark = Mark(data.marks.len() as u32 - 1);
data.syntax_contexts.push(SyntaxContextData {
outer_mark: mark,
transparency: Transparency::SemiTransparent,
prev_ctxt: SyntaxContext::empty(),
opaque: SyntaxContext::empty(),
opaque_and_semitransparent: SyntaxContext::empty(),
dollar_crate_name: kw::DollarCrate,
});
SyntaxContext(data.syntax_contexts.len() as u32 - 1)
})
}
/// Extend a syntax context with a given mark and default transparency for that mark.
pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
HygieneData::with(|data| data.apply_mark(self, mark))
@@ -639,8 +601,23 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
}
}
/// Extra information for tracking spans of macro and syntax sugar expansion
#[derive(Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
impl Span {
/// Creates a fresh expansion with given properties.
/// Expansions are normally created by macros, but in some cases expansions are created for
/// other compiler-generated code to set per-span properties like allowed unstable features.
/// The returned span belongs to the created expansion and has the new properties,
/// but its location is inherited from the current span.
pub fn fresh_expansion(self, parent: Mark, expn_info: ExpnInfo) -> Span {
HygieneData::with(|data| {
let mark = data.fresh_mark(parent, Some(expn_info));
self.with_ctxt(data.apply_mark(SyntaxContext::empty(), mark))
})
}
}
/// A subset of properties from both macro definition and macro call available through global data.
/// Avoid using this if you have access to the original definition or call structures.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ExpnInfo {
// --- The part unique to each expansion.
/// The location of the actual macro invocation or syntax sugar , e.g.
@@ -653,16 +630,14 @@ pub struct ExpnInfo {
/// call_site span would have its own ExpnInfo, with the call_site
/// pointing to the `foo!` invocation.
pub call_site: Span,
/// The format with which the macro was invoked.
pub format: ExpnFormat,
/// The kind of this expansion - macro or compiler desugaring.
pub kind: ExpnKind,
// --- The part specific to the macro/desugaring definition.
// --- FIXME: Share it between expansions with the same definition.
/// The span of the macro definition itself. The macro may not
/// have a sensible definition span (e.g., something defined
/// completely inside libsyntax) in which case this is None.
/// The span of the macro definition (possibly dummy).
/// This span serves only informational purpose and is not used for resolution.
pub def_site: Option<Span>,
pub def_site: Span,
/// Transparency used by `apply_mark` for mark with this expansion info by default.
pub default_transparency: Transparency,
/// List of #[unstable]/feature-gated features that the macro is allowed to use
@@ -681,11 +656,11 @@ pub struct ExpnInfo {
impl ExpnInfo {
/// Constructs an expansion info with default properties.
pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo {
pub fn default(kind: ExpnKind, call_site: Span, edition: Edition) -> ExpnInfo {
ExpnInfo {
call_site,
format,
def_site: None,
kind,
def_site: DUMMY_SP,
default_transparency: Transparency::SemiTransparent,
allow_internal_unstable: None,
allow_internal_unsafe: false,
@@ -694,38 +669,68 @@ pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInf
}
}
pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition,
allow_internal_unstable: &[Symbol]) -> ExpnInfo {
pub fn allow_unstable(kind: ExpnKind, call_site: Span, edition: Edition,
allow_internal_unstable: Lrc<[Symbol]>) -> ExpnInfo {
ExpnInfo {
allow_internal_unstable: Some(allow_internal_unstable.into()),
..ExpnInfo::default(format, call_site, edition)
allow_internal_unstable: Some(allow_internal_unstable),
..ExpnInfo::default(kind, call_site, edition)
}
}
}
/// The source of expansion.
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum ExpnFormat {
/// e.g., #[derive(...)] <item>
MacroAttribute(Symbol),
/// e.g., `format!()`
MacroBang(Symbol),
/// Expansion kind.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ExpnKind {
/// No expansion, aka root expansion. Only `Mark::root()` has this kind.
Root,
/// Expansion produced by a macro.
/// FIXME: Some code injected by the compiler before HIR lowering also gets this kind.
Macro(MacroKind, Symbol),
/// Desugaring done by the compiler during HIR lowering.
CompilerDesugaring(CompilerDesugaringKind)
Desugaring(DesugaringKind)
}
impl ExpnFormat {
pub fn name(&self) -> Symbol {
impl ExpnKind {
pub fn descr(&self) -> Symbol {
match *self {
ExpnFormat::MacroBang(name) | ExpnFormat::MacroAttribute(name) => name,
ExpnFormat::CompilerDesugaring(kind) => kind.name(),
ExpnKind::Root => kw::PathRoot,
ExpnKind::Macro(_, descr) => descr,
ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
}
}
}
/// The kind of macro invocation or definition.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum MacroKind {
/// A bang macro `foo!()`.
Bang,
/// An attribute macro `#[foo]`.
Attr,
/// A derive macro `#[derive(Foo)]`
Derive,
}
impl MacroKind {
pub fn descr(self) -> &'static str {
match self {
MacroKind::Bang => "macro",
MacroKind::Attr => "attribute macro",
MacroKind::Derive => "derive macro",
}
}
pub fn article(self) -> &'static str {
match self {
MacroKind::Attr => "an",
_ => "a",
}
}
}
/// The kind of compiler desugaring.
#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
pub enum CompilerDesugaringKind {
#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub enum DesugaringKind {
/// We desugar `if c { i } else { e }` to `match $ExprKind::Use(c) { true => i, _ => e }`.
/// However, we do not want to blame `c` for unreachability but rather say that `i`
/// is unreachable. This desugaring kind allows us to avoid blaming `c`.
@@ -742,17 +747,18 @@ pub enum CompilerDesugaringKind {
ForLoop,
}
impl CompilerDesugaringKind {
pub fn name(self) -> Symbol {
Symbol::intern(match self {
CompilerDesugaringKind::CondTemporary => "if and while condition",
CompilerDesugaringKind::Async => "async",
CompilerDesugaringKind::Await => "await",
CompilerDesugaringKind::QuestionMark => "?",
CompilerDesugaringKind::TryBlock => "try block",
CompilerDesugaringKind::ExistentialType => "existential type",
CompilerDesugaringKind::ForLoop => "for loop",
})
impl DesugaringKind {
/// The description wording should combine well with "desugaring of {}".
fn descr(self) -> &'static str {
match self {
DesugaringKind::CondTemporary => "`if` or `while` condition",
DesugaringKind::Async => "`async` block or function",
DesugaringKind::Await => "`await` expression",
DesugaringKind::QuestionMark => "operator `?`",
DesugaringKind::TryBlock => "`try` block",
DesugaringKind::ExistentialType => "`existential type`",
DesugaringKind::ForLoop => "`for` loop",
}
}
}
+19 -15
View File
@@ -27,7 +27,7 @@
pub mod edition;
use edition::Edition;
pub mod hygiene;
pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind};
pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind, MacroKind, DesugaringKind};
mod span_encoding;
pub use span_encoding::{Span, DUMMY_SP};
@@ -60,7 +60,7 @@ pub fn new(edition: Edition) -> Globals {
Globals {
symbol_interner: Lock::new(symbol::Interner::fresh()),
span_interner: Lock::new(span_encoding::SpanInterner::default()),
hygiene_data: Lock::new(hygiene::HygieneData::new()),
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
edition,
}
}
@@ -403,10 +403,10 @@ pub fn allows_unstable(&self, feature: Symbol) -> bool {
}
/// Checks if this span arises from a compiler desugaring of kind `kind`.
pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
pub fn is_desugaring(&self, kind: DesugaringKind) -> bool {
match self.ctxt().outer_expn_info() {
Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => k == kind,
Some(info) => match info.kind {
ExpnKind::Desugaring(k) => k == kind,
_ => false,
},
None => false,
@@ -415,10 +415,10 @@ pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool {
/// Returns the compiler desugaring that created this span, or `None`
/// if this span is not from a desugaring.
pub fn compiler_desugaring_kind(&self) -> Option<CompilerDesugaringKind> {
pub fn desugaring_kind(&self) -> Option<DesugaringKind> {
match self.ctxt().outer_expn_info() {
Some(info) => match info.format {
ExpnFormat::CompilerDesugaring(k) => Some(k),
Some(info) => match info.kind {
ExpnKind::Desugaring(k) => Some(k),
_ => None
},
None => None
@@ -441,14 +441,18 @@ pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> {
while let Some(info) = self.ctxt().outer_expn_info() {
// Don't print recursive invocations.
if !info.call_site.source_equal(&prev_span) {
let (pre, post) = match info.format {
ExpnFormat::MacroAttribute(..) => ("#[", "]"),
ExpnFormat::MacroBang(..) => ("", "!"),
ExpnFormat::CompilerDesugaring(..) => ("desugaring of `", "`"),
let (pre, post) = match info.kind {
ExpnKind::Root => break,
ExpnKind::Desugaring(..) => ("desugaring of ", ""),
ExpnKind::Macro(macro_kind, _) => match macro_kind {
MacroKind::Bang => ("", "!"),
MacroKind::Attr => ("#[", "]"),
MacroKind::Derive => ("#[derive(", ")]"),
}
};
result.push(MacroBacktrace {
call_site: info.call_site,
macro_decl_name: format!("{}{}{}", pre, info.format.name(), post),
macro_decl_name: format!("{}{}{}", pre, info.kind.descr(), post),
def_site_span: info.def_site,
});
}
@@ -1363,8 +1367,8 @@ pub struct MacroBacktrace {
/// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
pub macro_decl_name: String,
/// span where macro was defined (if known)
pub def_site_span: Option<Span>,
/// span where macro was defined (possibly dummy)
pub def_site_span: Span,
}
// _____________________________________________________________________________
+2
View File
@@ -508,6 +508,7 @@
proc_macro_expr,
proc_macro_gen,
proc_macro_hygiene,
proc_macro_internals,
proc_macro_mod,
proc_macro_non_items,
proc_macro_path_invoc,
@@ -631,6 +632,7 @@
static_nobundle,
static_recursion,
std,
std_inject,
str,
stringify,
stmt,
@@ -28,8 +28,7 @@ impl TTMacroExpander for Expander {
fn expand<'cx>(&self,
ecx: &'cx mut ExtCtxt,
sp: Span,
_: TokenStream,
_: Option<Span>) -> Box<dyn MacResult+'cx> {
_: TokenStream) -> 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)))
-64
View File
@@ -1,64 +0,0 @@
// edition:2018
use std::sync::Arc;
use std::task::{
Waker, RawWaker, RawWakerVTable,
};
macro_rules! waker_vtable {
($ty:ident) => {
&RawWakerVTable::new(
clone_arc_raw::<$ty>,
wake_arc_raw::<$ty>,
wake_by_ref_arc_raw::<$ty>,
drop_arc_raw::<$ty>,
)
};
}
pub trait ArcWake {
fn wake(self: Arc<Self>);
fn wake_by_ref(arc_self: &Arc<Self>) {
arc_self.clone().wake()
}
fn into_waker(wake: Arc<Self>) -> Waker where Self: Sized
{
let ptr = Arc::into_raw(wake) as *const ();
unsafe {
Waker::from_raw(RawWaker::new(ptr, waker_vtable!(Self)))
}
}
}
unsafe fn increase_refcount<T: ArcWake>(data: *const ()) {
// Retain Arc by creating a copy
let arc: Arc<T> = Arc::from_raw(data as *const T);
let arc_clone = arc.clone();
// Forget the Arcs again, so that the refcount isn't decrased
let _ = Arc::into_raw(arc);
let _ = Arc::into_raw(arc_clone);
}
unsafe fn clone_arc_raw<T: ArcWake>(data: *const ()) -> RawWaker {
increase_refcount::<T>(data);
RawWaker::new(data, waker_vtable!(T))
}
unsafe fn drop_arc_raw<T: ArcWake>(data: *const ()) {
// Drop Arc
let _: Arc<T> = Arc::from_raw(data as *const T);
}
unsafe fn wake_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake(arc);
}
unsafe fn wake_by_ref_arc_raw<T: ArcWake>(data: *const ()) {
let arc: Arc<T> = Arc::from_raw(data as *const T);
ArcWake::wake_by_ref(&arc);
let _ = Arc::into_raw(arc);
}
+1 -1
View File
@@ -7,7 +7,7 @@
// @has some_macros/index.html
// @has - '//a/[@href="attr.some_proc_attr.html"]' 'some_proc_attr'
//! include a link to [some_proc_attr] to make sure it works.
//! include a link to [some_proc_macro] to make sure it works.
extern crate proc_macro;
@@ -7,6 +7,9 @@
//
// See issue #59123 for a full explanation.
// ignore-wasm32-bare (sizes don't match)
// run-pass
// edition:2018
#![feature(async_await)]
@@ -1,9 +1,10 @@
// run-pass
// aux-build:arc_wake.rs
// edition:2018
#![feature(async_await)]
#[path = "../auxiliary/arc_wake.rs"]
mod arc_wake;
extern crate arc_wake;
use std::pin::Pin;
use std::future::Future;
@@ -1,3 +1,5 @@
// run-pass
// aux-build:arc_wake.rs
extern crate arc_wake;
@@ -2,6 +2,8 @@
// handled incorrectly in generators.
// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
// run-pass
#![feature(async_await)]
#![allow(unused)]
@@ -0,0 +1,15 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::*;
#[proc_macro_derive(NoMarker)]
pub fn f(input: TokenStream) -> TokenStream {
if input.to_string().contains("rustc_copy_clone_marker") {
panic!("found `#[rustc_copy_clone_marker]`");
}
TokenStream::new()
}
@@ -0,0 +1,16 @@
// Test that `#[rustc_copy_clone_marker]` is not injected when a user-defined derive shadows
// a built-in derive in non-trivial scope (e.g. in a nested module).
// check-pass
// aux-build:derive-marker-tricky.rs
extern crate derive_marker_tricky;
mod m {
use derive_marker_tricky::NoMarker as Copy;
#[derive(Copy)]
struct S;
}
fn main() {}
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
--> $DIR/feature-gate-asm.rs:3:9
|
LL | asm!("");
| ^^^^^^^^^
| ^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29722
= help: add `#![feature(asm)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
--> $DIR/feature-gate-asm2.rs:5:26
|
LL | println!("{:?}", asm!(""));
| ^^^^^^^^
| ^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29722
= help: add `#![feature(asm)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
--> $DIR/feature-gate-concat_idents.rs:5:13
|
LL | let a = concat_idents!(X, Y_1);
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
--> $DIR/feature-gate-concat_idents.rs:6:13
|
LL | let b = concat_idents!(X, Y_2);
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
--> $DIR/feature-gate-concat_idents2.rs:4:5
|
LL | concat_idents!(a, b);
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
--> $DIR/feature-gate-concat_idents3.rs:7:20
|
LL | assert_eq!(10, concat_idents!(X, Y_1));
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -11,7 +11,7 @@ error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` i
--> $DIR/feature-gate-concat_idents3.rs:8:20
|
LL | assert_eq!(20, concat_idents!(X, Y_2));
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29599
= help: add `#![feature(concat_idents)]` to the crate attributes to enable
@@ -1,8 +1,8 @@
error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature
--> $DIR/feature-gate-custom_test_frameworks.rs:3:1
--> $DIR/feature-gate-custom_test_frameworks.rs:3:3
|
LL | #[test_case]
| ^^^^^^^^^^^^
| ^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/50297
= help: add `#![feature(custom_test_frameworks)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl`
--> $DIR/feature-gate-format_args_nl.rs:2:5
|
LL | format_args_nl!("");
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^
|
= help: add `#![feature(format_args_nl)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'global_asm': `global_asm!` is not
--> $DIR/feature-gate-global_asm.rs:1:1
|
LL | global_asm!("");
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/35119
= help: add `#![feature(global_asm)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
--> $DIR/feature-gate-log_syntax.rs:2:5
|
LL | log_syntax!()
| ^^^^^^^^^^^^^
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(log_syntax)]` to the crate attributes to enable
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not
--> $DIR/feature-gate-log_syntax2.rs:4:22
|
LL | println!("{:?}", log_syntax!());
| ^^^^^^^^^^^^^
| ^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(log_syntax)]` to the crate attributes to enable
@@ -7,12 +7,12 @@ mod unknown { pub macro rustc() {} }
#[rustc::unknown]
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
//~| ERROR macro `rustc::unknown` may not be used in attributes
//~| ERROR expected attribute, found macro `rustc::unknown`
fn f() {}
#[unknown::rustc]
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
//~| ERROR macro `unknown::rustc` may not be used in attributes
//~| ERROR expected attribute, found macro `unknown::rustc`
fn g() {}
#[rustc_dummy]
@@ -7,11 +7,11 @@ LL | #[rustc::unknown]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
error: macro `rustc::unknown` may not be used in attributes
--> $DIR/feature-gate-rustc-attrs.rs:8:1
error: expected attribute, found macro `rustc::unknown`
--> $DIR/feature-gate-rustc-attrs.rs:8:3
|
LL | #[rustc::unknown]
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ not an attribute
error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/feature-gate-rustc-attrs.rs:13:12
@@ -22,11 +22,11 @@ LL | #[unknown::rustc]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
error: macro `unknown::rustc` may not be used in attributes
--> $DIR/feature-gate-rustc-attrs.rs:13:1
error: expected attribute, found macro `unknown::rustc`
--> $DIR/feature-gate-rustc-attrs.rs:13:3
|
LL | #[unknown::rustc]
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ not an attribute
error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/feature-gate-rustc-attrs.rs:20:3
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
--> $DIR/feature-gate-trace_macros.rs:2:5
|
LL | trace_macros!(true);
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -0,0 +1,11 @@
error: implementation of `Stream` is not general enough
--> $DIR/issue-30786.rs:107:22
|
LL | let map = source.map(|x: &_| x);
| ^^^
|
= note: `Stream` would have to be implemented for the type `&'0 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for any lifetime `'0`
= note: but `Stream` is actually implemented for the type `&'1 mut Map<Repeat, [closure@$DIR/issue-30786.rs:107:26: 107:35]>`, for some specific lifetime `'1`
error: aborting due to previous error
+14
View File
@@ -0,0 +1,14 @@
error: higher-ranked subtype error
--> $DIR/issue-30786.rs:111:18
|
LL | let filter = map.filter(|x: &_| true);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: higher-ranked subtype error
--> $DIR/issue-30786.rs:113:17
|
LL | let count = filter.count(); // Assert that we still have a valid stream.
| ^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
+115
View File
@@ -0,0 +1,115 @@
// rust-lang/rust#30786: the use of `for<'b> &'b mut A: Stream<Item=T`
// should act as assertion that item does not borrow from its stream;
// but an earlier buggy rustc allowed `.map(|x: &_| x)` which does
// have such an item.
//
// This tests double-checks that we do not allow such behavior to leak
// through again.
// revisions: migrate nll
// Since we are testing nll (and migration) explicitly as a separate
// revisions, don't worry about the --compare-mode=nll on this test.
// ignore-compare-mode-nll
//[nll]compile-flags: -Z borrowck=mir
pub trait Stream {
type Item;
fn next(self) -> Option<Self::Item>;
}
// Example stream
pub struct Repeat(u64);
impl<'a> Stream for &'a mut Repeat {
type Item = &'a u64;
fn next(self) -> Option<Self::Item> {
Some(&self.0)
}
}
pub struct Map<S, F> {
stream: S,
func: F,
}
impl<'a, A, F, T> Stream for &'a mut Map<A, F>
where &'a mut A: Stream,
F: FnMut(<&'a mut A as Stream>::Item) -> T,
{
type Item = T;
fn next(self) -> Option<T> {
match self.stream.next() {
Some(item) => Some((self.func)(item)),
None => None,
}
}
}
pub struct Filter<S, F> {
stream: S,
func: F,
}
impl<'a, A, F, T> Stream for &'a mut Filter<A, F>
where for<'b> &'b mut A: Stream<Item=T>, // <---- BAD
F: FnMut(&T) -> bool,
{
type Item = <&'a mut A as Stream>::Item;
fn next(self) -> Option<Self::Item> {
while let Some(item) = self.stream.next() {
if (self.func)(&item) {
return Some(item);
}
}
None
}
}
pub trait StreamExt where for<'b> &'b mut Self: Stream {
fn map<F>(self, func: F) -> Map<Self, F>
where Self: Sized,
for<'a> &'a mut Map<Self, F>: Stream,
{
Map {
func: func,
stream: self,
}
}
fn filter<F>(self, func: F) -> Filter<Self, F>
where Self: Sized,
for<'a> &'a mut Filter<Self, F>: Stream,
{
Filter {
func: func,
stream: self,
}
}
fn count(mut self) -> usize
where Self: Sized,
{
let mut count = 0;
while let Some(_) = self.next() {
count += 1;
}
count
}
}
impl<T> StreamExt for T where for<'a> &'a mut T: Stream { }
fn main() {
let source = Repeat(10);
let map = source.map(|x: &_| x);
//[migrate]~^ ERROR implementation of `Stream` is not general enough
//[migrate]~| NOTE `Stream` would have to be implemented for the type `&'0 mut Map
//[migrate]~| NOTE but `Stream` is actually implemented for the type `&'1
let filter = map.filter(|x: &_| true);
//[nll]~^ ERROR higher-ranked subtype error
let count = filter.count(); // Assert that we still have a valid stream.
//[nll]~^ ERROR higher-ranked subtype error
}
@@ -0,0 +1,3 @@
#![feature(decl_macro)]
pub macro stdlib_macro() {}
@@ -0,0 +1,28 @@
#![feature(decl_macro)]
macro a() {
extern crate core as my_core;
mod v {
// Early resolution.
use my_core; //~ ERROR unresolved import `my_core`
}
mod u {
// Late resolution.
fn f() { my_core::mem::drop(0); }
//~^ ERROR failed to resolve: use of undeclared type or module `my_core`
}
}
a!();
mod v {
// Early resolution.
use my_core; //~ ERROR unresolved import `my_core`
}
mod u {
// Late resolution.
fn f() { my_core::mem::drop(0); }
//~^ ERROR failed to resolve: use of undeclared type or module `my_core`
}
fn main() {}
@@ -0,0 +1,37 @@
error[E0432]: unresolved import `my_core`
--> $DIR/extern-prelude-from-opaque-fail.rs:20:9
|
LL | use my_core;
| ^^^^^^^
| |
| no `my_core` in the root
| help: a similar name exists in the module: `my_core`
error[E0432]: unresolved import `my_core`
--> $DIR/extern-prelude-from-opaque-fail.rs:7:13
|
LL | use my_core;
| ^^^^^^^ no `my_core` in the root
...
LL | a!();
| ----- in this macro invocation
error[E0433]: failed to resolve: use of undeclared type or module `my_core`
--> $DIR/extern-prelude-from-opaque-fail.rs:11:18
|
LL | fn f() { my_core::mem::drop(0); }
| ^^^^^^^ use of undeclared type or module `my_core`
...
LL | a!();
| ----- in this macro invocation
error[E0433]: failed to resolve: use of undeclared type or module `my_core`
--> $DIR/extern-prelude-from-opaque-fail.rs:24:14
|
LL | fn f() { my_core::mem::drop(0); }
| ^^^^^^^ use of undeclared type or module `my_core`
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.
@@ -0,0 +1,21 @@
// check-pass
// aux-build:stdlib-prelude.rs
#![feature(decl_macro)]
#![feature(prelude_import)]
extern crate stdlib_prelude;
#[prelude_import]
use stdlib_prelude::*;
macro mac() {
mod m {
use std::mem; // OK (extern prelude)
stdlib_macro!(); // OK (stdlib prelude)
}
}
mac!();
fn main() {}
@@ -0,0 +1,16 @@
// check-pass
#![feature(decl_macro)]
macro mac() {
mod m {
fn f() {
std::mem::drop(0); // OK (extern prelude)
drop(0); // OK (stdlib prelude)
}
}
}
mac!();
fn main() {}
@@ -0,0 +1,14 @@
// Regression test for the issue #44692
macro_rules! hang { () => {
{ //~ ERROR format argument must be a string literal
#[derive(Clone)]
struct S;
""
}
}}
fn main() {
format_args!(hang!());
}
@@ -0,0 +1,17 @@
error: format argument must be a string literal
--> $DIR/derive-in-eager-expansion-hang.rs:4:5
|
LL | / {
LL | | #[derive(Clone)]
LL | | struct S;
LL | |
LL | | ""
LL | | }
| |_____^
help: you might be missing a string literal to format with
|
LL | format_args!("{}", hang!());
| ^^^^^
error: aborting due to previous error
+2 -2
View File
@@ -2,7 +2,7 @@ warning: use of deprecated item 'local_deprecated': local deprecation note
--> $DIR/macro-deprecation.rs:11:5
|
LL | local_deprecated!();
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^
|
= note: #[warn(deprecated)] on by default
@@ -10,5 +10,5 @@ warning: use of deprecated item 'deprecated_macro': deprecation note
--> $DIR/macro-deprecation.rs:12:5
|
LL | deprecated_macro!();
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^
+1 -1
View File
@@ -8,7 +8,7 @@ error: non-type macro in type position: cfg
--> $DIR/macro-error.rs:8:12
|
LL | let _: cfg!(foo) = ();
| ^^^
| ^^^^^^^^^
error: aborting due to 2 previous errors
@@ -1,4 +1,4 @@
#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
#[derive(inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
struct S;
fn main() {}
@@ -1,8 +1,8 @@
error: expected a macro, found built-in attribute
error: expected derive macro, found built-in attribute `inline`
--> $DIR/macro-path-prelude-fail-4.rs:1:10
|
LL | #[derive(inline)]
| ^^^^^^
| ^^^^^^ not a derive macro
error: aborting due to previous error
+5 -5
View File
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'local_unstable'
--> $DIR/macro-stability.rs:19:5
|
LL | local_unstable!();
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^
|
= help: add `#![feature(local_unstable)]` to the crate attributes to enable
@@ -10,7 +10,7 @@ error[E0658]: use of unstable library feature 'local_unstable'
--> $DIR/macro-stability.rs:20:5
|
LL | local_unstable_modern!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(local_unstable)]` to the crate attributes to enable
@@ -18,7 +18,7 @@ error[E0658]: use of unstable library feature 'unstable_macros'
--> $DIR/macro-stability.rs:21:5
|
LL | unstable_macro!();
| ^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^
|
= help: add `#![feature(unstable_macros)]` to the crate attributes to enable
@@ -26,7 +26,7 @@ warning: use of deprecated item 'deprecated_macro': deprecation reason
--> $DIR/macro-stability.rs:24:5
|
LL | deprecated_macro!();
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^
|
= note: #[warn(deprecated)] on by default
@@ -34,7 +34,7 @@ warning: use of deprecated item 'local_deprecated': local deprecation reason
--> $DIR/macro-stability.rs:26:5
|
LL | local_deprecated!();
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
@@ -45,8 +45,6 @@ LL | my_recursive_macro!();
= note: to `my_recursive_macro ! ( ) ;`
= note: expanding `my_recursive_macro! { }`
= note: to `my_recursive_macro ! ( ) ;`
= note: expanding `my_recursive_macro! { }`
= note: to `my_recursive_macro ! ( ) ;`
error: aborting due to 2 previous errors
@@ -25,22 +25,32 @@ fn check_bang1() {
my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
}
fn check_bang2() {
my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
//~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
}
fn check_bang3() {
MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected macro, found derive macro `crate::MyTrait`
}
#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
#[my_macro] //~ ERROR attribute `my_macro` is currently unknown
#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected attribute, found macro `crate::my_macro`
fn check_attr1() {}
#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
fn check_attr2() {}
#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected attribute, found derive macro `MyTrait`
fn check_attr3() {}
#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
//~| ERROR expected derive macro, found macro `crate::my_macro`
struct CheckDerive1;
#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected derive macro, found attribute macro `my_macro_attr`
struct CheckDerive2;
#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
struct CheckDerive3;
@@ -5,52 +5,116 @@ LL | my_macro!();
| ^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:28:5
--> $DIR/macro-namespace-reserved-2.rs:29:5
|
LL | my_macro_attr!();
| ^^^^^^^^^^^^^
LL | crate::my_macro_attr!();
| ^^^^^^^^^^^^^^^^^^^^
error: expected macro, found attribute macro `crate::my_macro_attr`
--> $DIR/macro-namespace-reserved-2.rs:29:5
|
LL | crate::my_macro_attr!();
| ^^^^^^^^^^^^^^^^^^^^ not a macro
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:31:5
--> $DIR/macro-namespace-reserved-2.rs:34:5
|
LL | MyTrait!();
| ^^^^^^^
LL | crate::MyTrait!();
| ^^^^^^^^^^^^^^
error: expected macro, found derive macro `crate::MyTrait`
--> $DIR/macro-namespace-reserved-2.rs:34:5
|
LL | crate::MyTrait!();
| ^^^^^^^^^^^^^^ not a macro
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:34:3
|
LL | #[my_macro]
| ^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:36:3
--> $DIR/macro-namespace-reserved-2.rs:42:3
|
LL | #[my_macro_attr]
| ^^^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:38:3
--> $DIR/macro-namespace-reserved-2.rs:44:3
|
LL | #[MyTrait]
| ^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:41:10
error: expected attribute, found derive macro `MyTrait`
--> $DIR/macro-namespace-reserved-2.rs:44:3
|
LL | #[derive(my_macro)]
| ^^^^^^^^
LL | #[MyTrait]
| ^^^^^^^ not an attribute
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:43:10
--> $DIR/macro-namespace-reserved-2.rs:49:10
|
LL | #[derive(crate::my_macro)]
| ^^^^^^^^^^^^^^^
error: expected derive macro, found macro `crate::my_macro`
--> $DIR/macro-namespace-reserved-2.rs:49:10
|
LL | #[derive(crate::my_macro)]
| ^^^^^^^^^^^^^^^ not a derive macro
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:52:10
|
LL | #[derive(my_macro_attr)]
| ^^^^^^^^^^^^^
error: expected derive macro, found attribute macro `my_macro_attr`
--> $DIR/macro-namespace-reserved-2.rs:52:10
|
LL | #[derive(my_macro_attr)]
| ^^^^^^^^^^^^^ not a derive macro
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:45:10
--> $DIR/macro-namespace-reserved-2.rs:55:10
|
LL | #[derive(MyTrait)]
| ^^^^^^^
error: aborting due to 9 previous errors
error[E0658]: The attribute `my_macro` is currently unknown to the compiler and may have meaning added to it in the future
--> $DIR/macro-namespace-reserved-2.rs:38:3
|
LL | #[my_macro]
| ^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(custom_attribute)]` to the crate attributes to enable
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:39:3
|
LL | #[crate::my_macro]
| ^^^^^^^^^^^^^^^
error: expected attribute, found macro `crate::my_macro`
--> $DIR/macro-namespace-reserved-2.rs:39:3
|
LL | #[crate::my_macro]
| ^^^^^^^^^^^^^^^ not an attribute
error: cannot find derive macro `my_macro` in this scope
--> $DIR/macro-namespace-reserved-2.rs:48:10
|
LL | #[derive(my_macro)]
| ^^^^^^^^
error: cannot find macro `my_macro_attr!` in this scope
--> $DIR/macro-namespace-reserved-2.rs:28:5
|
LL | my_macro_attr!();
| ^^^^^^^^^^^^^
error: cannot find macro `MyTrait!` in this scope
--> $DIR/macro-namespace-reserved-2.rs:33:5
|
LL | MyTrait!();
| ^^^^^^^
error: aborting due to 19 previous errors
For more information about this error, try `rustc --explain E0658`.
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature '__rust_unstable_column': internal
--> $DIR/rust-unstable-column-gated.rs:2:20
|
LL | println!("{}", __rust_unstable_column!());
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: add `#![feature(__rust_unstable_column)]` to the crate attributes to enable
@@ -1,6 +1,6 @@
#[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
#[derive(rustfmt::skip)] //~ ERROR expected derive macro, found tool attribute `rustfmt::skip`
struct S;
fn main() {
rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
rustfmt::skip!(); //~ ERROR expected macro, found tool attribute `rustfmt::skip`
}
@@ -1,14 +1,14 @@
error: expected a macro, found tool attribute
error: expected derive macro, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-2.rs:1:10
|
LL | #[derive(rustfmt::skip)]
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ not a derive macro
error: expected a macro, found tool attribute
error: expected macro, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-2.rs:5:5
|
LL | rustfmt::skip!();
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ not a macro
error: aborting due to 2 previous errors
+4 -4
View File
@@ -2,7 +2,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
--> $DIR/trace_macros-gate.rs:4:5
|
LL | trace_macros!();
| ^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -17,7 +17,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
--> $DIR/trace_macros-gate.rs:6:5
|
LL | trace_macros!(true);
| ^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -26,7 +26,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
--> $DIR/trace_macros-gate.rs:7:5
|
LL | trace_macros!(false);
| ^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29598
= help: add `#![feature(trace_macros)]` to the crate attributes to enable
@@ -35,7 +35,7 @@ error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is
--> $DIR/trace_macros-gate.rs:10:26
|
LL | ($x: ident) => { trace_macros!($x) }
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^
...
LL | expando!(true);
| --------------- in this macro invocation