mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-16 04:55:22 +03:00
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:
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */ }
|
||||
|
||||
@@ -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}`")
|
||||
|
||||
@@ -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)*) => {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,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
|
||||
};
|
||||
|
||||
@@ -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(),
|
||||
)),
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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("&") {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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!(),
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
+3
@@ -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)]
|
||||
+3
-2
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user