mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-29 20:46:07 +03:00
Auto merge of #61945 - Centril:rollup-xdqo2mn, r=Centril
Rollup of 11 pull requests Successful merges: - #61505 (Only show methods that appear in `impl` blocks in the Implementors sections of trait doc pages) - #61701 (move stray run-pass const tests into const/ folder) - #61748 (Tweak transparent enums and unions diagnostic spans) - #61802 (Make MaybeUninit #[repr(transparent)]) - #61839 (ci: Add a script for generating CPU usage graphs) - #61842 (Remove unnecessary lift calls) - #61843 (Turn down the myriad-closures test) - #61896 (rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`.) - #61898 (syntax: Factor out common fields from `SyntaxExtension` variants) - #61938 (create an issue for miri even in status test-fail) - #61941 (Preserve generator and yield source for error messages) Failed merges: r? @ghost
This commit is contained in:
@@ -30,23 +30,8 @@
|
||||
# the second column is always zero.
|
||||
#
|
||||
# Once you've downloaded a file there's various ways to plot it and visualize
|
||||
# it. For command line usage you can use a script like so:
|
||||
#
|
||||
# set timefmt '%Y-%m-%dT%H:%M:%S'
|
||||
# set xdata time
|
||||
# set ylabel "Idle CPU %"
|
||||
# set xlabel "Time"
|
||||
# set datafile sep ','
|
||||
# set term png
|
||||
# set output "printme.png"
|
||||
# set grid
|
||||
# builder = "i686-apple"
|
||||
# plot "cpu-".builder.".csv" using 1:2 with lines title builder
|
||||
#
|
||||
# Executed as `gnuplot < ./foo.plot` it will generate a graph called
|
||||
# `printme.png` which you can then open up. If you know how to improve this
|
||||
# script or the viewing process that would be much appreciated :) (or even if
|
||||
# you know how to automate it!)
|
||||
# it. For command line usage you use the `src/etc/cpu-usage-over-time-plot.sh`
|
||||
# script in this repository.
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
@@ -132,7 +132,7 @@ The advantages over a simple `fn(&str) -> u32` are:
|
||||
In addition to procedural macros, you can define new
|
||||
[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds
|
||||
of extensions. See `Registry::register_syntax_extension` and the
|
||||
`SyntaxExtension` enum. For a more involved macro example, see
|
||||
`SyntaxExtension` struct. For a more involved macro example, see
|
||||
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
|
||||
|
||||
|
||||
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
# A small script to help visualizing CPU usage over time data collected on CI
|
||||
# using `gnuplot`.
|
||||
#
|
||||
# This script is expected to be called with two arguments. The first is the full
|
||||
# commit SHA of the build you're interested in, and the second is the name of
|
||||
# the builder. For example:
|
||||
#
|
||||
# ./src/etc/cpu-usage-over-time-plot.sh e699ea096fcc2fc9ce8e8bcf884e11496a31cc9f i686-mingw-1
|
||||
#
|
||||
# That will generate `$builder.png` in the current directory which you can open
|
||||
# up to see a hopefully pretty graph.
|
||||
#
|
||||
# Improvements to this script are greatly appreciated!
|
||||
|
||||
set -ex
|
||||
|
||||
bucket=rust-lang-ci-evalazure
|
||||
commit=$1
|
||||
builder=$2
|
||||
|
||||
curl -O https://$bucket.s3.amazonaws.com/rustc-builds/$commit/cpu-$builder.csv
|
||||
|
||||
gnuplot <<-EOF
|
||||
reset
|
||||
set timefmt '%Y-%m-%dT%H:%M:%S'
|
||||
set xdata time
|
||||
set ylabel "CPU Usage %"
|
||||
set xlabel "Time"
|
||||
set datafile sep ','
|
||||
set term png size 3000,1000
|
||||
set output "$builder.png"
|
||||
set grid
|
||||
|
||||
f(x) = mean_y
|
||||
fit f(x) 'cpu-$builder.csv' using 1:(100-\$2) via mean_y
|
||||
|
||||
set label 1 gprintf("Average = %g%%", mean_y) center font ",18"
|
||||
set label 1 at graph 0.50, 0.25
|
||||
set xtics rotate by 45 offset -2,-2.4 300
|
||||
set ytics 10
|
||||
set boxwidth 0.5
|
||||
|
||||
plot \\
|
||||
mean_y with lines linetype 1 linecolor rgb "#ff0000" title "average", \\
|
||||
"cpu-$builder.csv" using 1:(100-\$2) with points pointtype 7 pointsize 0.4 title "$builder", \\
|
||||
"" using 1:(100-\$2) smooth bezier linewidth 3 title "bezier"
|
||||
EOF
|
||||
@@ -100,6 +100,7 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![cfg_attr(not(bootstrap), feature(transparent_unions))]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unsized_locals)]
|
||||
#![feature(untagged_unions)]
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
///
|
||||
/// # Layout
|
||||
///
|
||||
/// `MaybeUninit<T>` is guaranteed to have the same size and alignment as `T`:
|
||||
/// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::{MaybeUninit, size_of, align_of};
|
||||
@@ -191,9 +191,23 @@
|
||||
/// assert_eq!(size_of::<Option<bool>>(), 1);
|
||||
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
|
||||
/// ```
|
||||
///
|
||||
/// If `T` is FFI-safe, then so is `MaybeUninit<T>`.
|
||||
///
|
||||
/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size,
|
||||
/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and
|
||||
/// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type
|
||||
/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`.
|
||||
/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the
|
||||
/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact
|
||||
/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not
|
||||
/// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has
|
||||
/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that
|
||||
/// guarantee may evolve.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[derive(Copy)]
|
||||
#[cfg_attr(not(bootstrap), repr(transparent))]
|
||||
pub union MaybeUninit<T> {
|
||||
uninit: (),
|
||||
value: ManuallyDrop<T>,
|
||||
|
||||
@@ -330,7 +330,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
|
||||
hir::ExprKind::DropTemps(ref e) |
|
||||
hir::ExprKind::Unary(_, ref e) |
|
||||
hir::ExprKind::Field(ref e, _) |
|
||||
hir::ExprKind::Yield(ref e) |
|
||||
hir::ExprKind::Yield(ref e, _) |
|
||||
hir::ExprKind::Repeat(ref e, _) => {
|
||||
self.straightline(expr, pred, Some(&**e).into_iter())
|
||||
}
|
||||
|
||||
@@ -1089,7 +1089,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_expr(expr)
|
||||
}
|
||||
}
|
||||
ExprKind::Yield(ref subexpression) => {
|
||||
ExprKind::Yield(ref subexpression, _) => {
|
||||
visitor.visit_expr(subexpression);
|
||||
}
|
||||
ExprKind::Lit(_) | ExprKind::Err => {}
|
||||
|
||||
+101
-74
@@ -62,14 +62,14 @@
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
|
||||
use syntax::source_map::{self, respan, ExpnInfo, CompilerDesugaringKind, Spanned};
|
||||
use syntax::source_map::CompilerDesugaringKind::IfTemporary;
|
||||
use syntax::std_inject;
|
||||
use syntax::symbol::{kw, sym, Symbol};
|
||||
use syntax::tokenstream::{TokenStream, TokenTree};
|
||||
use syntax::parse::token::{self, Token};
|
||||
use syntax::visit::{self, Visitor};
|
||||
use syntax_pos::{DUMMY_SP, edition, Span};
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
|
||||
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
|
||||
|
||||
@@ -95,8 +95,7 @@ pub struct LoweringContext<'a> {
|
||||
|
||||
modules: BTreeMap<NodeId, hir::ModuleItems>,
|
||||
|
||||
is_generator: bool,
|
||||
is_async_body: bool,
|
||||
generator_kind: Option<hir::GeneratorKind>,
|
||||
|
||||
/// Used to get the current `fn`'s def span to point to when using `await`
|
||||
/// outside of an `async fn`.
|
||||
@@ -142,6 +141,9 @@ pub struct LoweringContext<'a> {
|
||||
current_hir_id_owner: Vec<(DefIndex, u32)>,
|
||||
item_local_id_counters: NodeMap<u32>,
|
||||
node_id_to_hir_id: IndexVec<NodeId, hir::HirId>,
|
||||
|
||||
allow_try_trait: Option<Lrc<[Symbol]>>,
|
||||
allow_gen_future: Option<Lrc<[Symbol]>>,
|
||||
}
|
||||
|
||||
pub trait Resolver {
|
||||
@@ -261,12 +263,13 @@ pub fn lower_crate(
|
||||
current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)],
|
||||
item_local_id_counters: Default::default(),
|
||||
node_id_to_hir_id: IndexVec::new(),
|
||||
is_generator: false,
|
||||
is_async_body: false,
|
||||
generator_kind: None,
|
||||
current_item: None,
|
||||
lifetimes_to_define: Vec::new(),
|
||||
is_collecting_in_band_lifetimes: false,
|
||||
in_scope_lifetimes: Vec::new(),
|
||||
allow_try_trait: Some([sym::try_trait][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||
}.lower_crate(krate)
|
||||
}
|
||||
|
||||
@@ -790,18 +793,49 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi
|
||||
})
|
||||
}
|
||||
|
||||
fn record_body(&mut self, arguments: HirVec<hir::Arg>, value: hir::Expr) -> hir::BodyId {
|
||||
if self.is_generator && self.is_async_body {
|
||||
span_err!(
|
||||
self.sess,
|
||||
value.span,
|
||||
E0727,
|
||||
"`async` generators are not yet supported",
|
||||
);
|
||||
self.sess.abort_if_errors();
|
||||
fn generator_movability_for_fn(
|
||||
&mut self,
|
||||
decl: &ast::FnDecl,
|
||||
fn_decl_span: Span,
|
||||
generator_kind: Option<hir::GeneratorKind>,
|
||||
movability: Movability,
|
||||
) -> Option<hir::GeneratorMovability> {
|
||||
match generator_kind {
|
||||
Some(hir::GeneratorKind::Gen) => {
|
||||
if !decl.inputs.is_empty() {
|
||||
span_err!(
|
||||
self.sess,
|
||||
fn_decl_span,
|
||||
E0628,
|
||||
"generators cannot have explicit arguments"
|
||||
);
|
||||
self.sess.abort_if_errors();
|
||||
}
|
||||
Some(match movability {
|
||||
Movability::Movable => hir::GeneratorMovability::Movable,
|
||||
Movability::Static => hir::GeneratorMovability::Static,
|
||||
})
|
||||
},
|
||||
Some(hir::GeneratorKind::Async) => {
|
||||
bug!("non-`async` closure body turned `async` during lowering");
|
||||
},
|
||||
None => {
|
||||
if movability == Movability::Static {
|
||||
span_err!(
|
||||
self.sess,
|
||||
fn_decl_span,
|
||||
E0697,
|
||||
"closures cannot be static"
|
||||
);
|
||||
}
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn record_body(&mut self, arguments: HirVec<hir::Arg>, value: hir::Expr) -> hir::BodyId {
|
||||
let body = hir::Body {
|
||||
is_generator: self.is_generator || self.is_async_body,
|
||||
generator_kind: self.generator_kind,
|
||||
arguments,
|
||||
value,
|
||||
};
|
||||
@@ -848,14 +882,10 @@ fn mark_span_with_reason(
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
) -> Span {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
mark.set_expn_info(source_map::ExpnInfo {
|
||||
call_site: span,
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
def_site: Some(span),
|
||||
format: source_map::CompilerDesugaring(reason),
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: edition::Edition::from_session(),
|
||||
..ExpnInfo::default(source_map::CompilerDesugaring(reason), span, self.sess.edition())
|
||||
});
|
||||
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
||||
}
|
||||
@@ -1142,7 +1172,7 @@ fn make_async_expr(
|
||||
};
|
||||
let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
|
||||
let body_id = self.lower_fn_body(&ast_decl, |this| {
|
||||
this.is_async_body = true;
|
||||
this.generator_kind = Some(hir::GeneratorKind::Async);
|
||||
body(this)
|
||||
});
|
||||
let generator = hir::Expr {
|
||||
@@ -1156,7 +1186,7 @@ fn make_async_expr(
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
CompilerDesugaringKind::Async,
|
||||
span,
|
||||
Some(vec![sym::gen_future].into()),
|
||||
self.allow_gen_future.clone(),
|
||||
);
|
||||
let gen_future = self.expr_std_path(
|
||||
unstable_span, &[sym::future, sym::from_generator], None, ThinVec::new());
|
||||
@@ -1167,12 +1197,10 @@ fn lower_body(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec<hir::Arg>, hir::Expr),
|
||||
) -> hir::BodyId {
|
||||
let prev_is_generator = mem::replace(&mut self.is_generator, false);
|
||||
let prev_is_async_body = mem::replace(&mut self.is_async_body, false);
|
||||
let prev_gen_kind = self.generator_kind.take();
|
||||
let (arguments, result) = f(self);
|
||||
let body_id = self.record_body(arguments, result);
|
||||
self.is_generator = prev_is_generator;
|
||||
self.is_async_body = prev_is_async_body;
|
||||
self.generator_kind = prev_gen_kind;
|
||||
body_id
|
||||
}
|
||||
|
||||
@@ -4382,7 +4410,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
||||
let unstable_span = this.mark_span_with_reason(
|
||||
CompilerDesugaringKind::TryBlock,
|
||||
body.span,
|
||||
Some(vec![sym::try_trait].into()),
|
||||
this.allow_try_trait.clone(),
|
||||
);
|
||||
let mut block = this.lower_block(body, true).into_inner();
|
||||
let tail = block.expr.take().map_or_else(
|
||||
@@ -4475,37 +4503,18 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
||||
|
||||
self.with_new_scopes(|this| {
|
||||
this.current_item = Some(fn_decl_span);
|
||||
let mut is_generator = false;
|
||||
let mut generator_kind = None;
|
||||
let body_id = this.lower_fn_body(decl, |this| {
|
||||
let e = this.lower_expr(body);
|
||||
is_generator = this.is_generator;
|
||||
generator_kind = this.generator_kind;
|
||||
e
|
||||
});
|
||||
let generator_option = if is_generator {
|
||||
if !decl.inputs.is_empty() {
|
||||
span_err!(
|
||||
this.sess,
|
||||
fn_decl_span,
|
||||
E0628,
|
||||
"generators cannot have explicit arguments"
|
||||
);
|
||||
this.sess.abort_if_errors();
|
||||
}
|
||||
Some(match movability {
|
||||
Movability::Movable => hir::GeneratorMovability::Movable,
|
||||
Movability::Static => hir::GeneratorMovability::Static,
|
||||
})
|
||||
} else {
|
||||
if movability == Movability::Static {
|
||||
span_err!(
|
||||
this.sess,
|
||||
fn_decl_span,
|
||||
E0697,
|
||||
"closures cannot be static"
|
||||
);
|
||||
}
|
||||
None
|
||||
};
|
||||
let generator_option = this.generator_movability_for_fn(
|
||||
&decl,
|
||||
fn_decl_span,
|
||||
generator_kind,
|
||||
movability,
|
||||
);
|
||||
hir::ExprKind::Closure(
|
||||
this.lower_capture_clause(capture_clause),
|
||||
fn_decl,
|
||||
@@ -4677,12 +4686,26 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
||||
}
|
||||
|
||||
ExprKind::Yield(ref opt_expr) => {
|
||||
self.is_generator = true;
|
||||
match self.generator_kind {
|
||||
Some(hir::GeneratorKind::Gen) => {},
|
||||
Some(hir::GeneratorKind::Async) => {
|
||||
span_err!(
|
||||
self.sess,
|
||||
e.span,
|
||||
E0727,
|
||||
"`async` generators are not yet supported",
|
||||
);
|
||||
self.sess.abort_if_errors();
|
||||
},
|
||||
None => {
|
||||
self.generator_kind = Some(hir::GeneratorKind::Gen);
|
||||
}
|
||||
}
|
||||
let expr = opt_expr
|
||||
.as_ref()
|
||||
.map(|x| self.lower_expr(x))
|
||||
.unwrap_or_else(|| self.expr_unit(e.span));
|
||||
hir::ExprKind::Yield(P(expr))
|
||||
hir::ExprKind::Yield(P(expr), hir::YieldSource::Yield)
|
||||
}
|
||||
|
||||
ExprKind::Err => hir::ExprKind::Err,
|
||||
@@ -4968,13 +4991,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
|
||||
let unstable_span = self.mark_span_with_reason(
|
||||
CompilerDesugaringKind::QuestionMark,
|
||||
e.span,
|
||||
Some(vec![sym::try_trait].into()),
|
||||
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,
|
||||
try_span,
|
||||
Some(vec![sym::try_trait].into()),
|
||||
self.allow_try_trait.clone(),
|
||||
);
|
||||
|
||||
// `Try::into_result(<expr>)`
|
||||
@@ -5754,19 +5777,23 @@ fn lower_await(
|
||||
// yield ();
|
||||
// }
|
||||
// }
|
||||
if !self.is_async_body {
|
||||
let mut err = struct_span_err!(
|
||||
self.sess,
|
||||
await_span,
|
||||
E0728,
|
||||
"`await` is only allowed inside `async` functions and blocks"
|
||||
);
|
||||
err.span_label(await_span, "only allowed inside `async` functions and blocks");
|
||||
if let Some(item_sp) = self.current_item {
|
||||
err.span_label(item_sp, "this is not `async`");
|
||||
match self.generator_kind {
|
||||
Some(hir::GeneratorKind::Async) => {},
|
||||
Some(hir::GeneratorKind::Gen) |
|
||||
None => {
|
||||
let mut err = struct_span_err!(
|
||||
self.sess,
|
||||
await_span,
|
||||
E0728,
|
||||
"`await` is only allowed inside `async` functions and blocks"
|
||||
);
|
||||
err.span_label(await_span, "only allowed inside `async` functions and blocks");
|
||||
if let Some(item_sp) = self.current_item {
|
||||
err.span_label(item_sp, "this is not `async`");
|
||||
}
|
||||
err.emit();
|
||||
return hir::ExprKind::Err;
|
||||
}
|
||||
err.emit();
|
||||
return hir::ExprKind::Err;
|
||||
}
|
||||
let span = self.mark_span_with_reason(
|
||||
CompilerDesugaringKind::Await,
|
||||
@@ -5776,7 +5803,7 @@ fn lower_await(
|
||||
let gen_future_span = self.mark_span_with_reason(
|
||||
CompilerDesugaringKind::Await,
|
||||
await_span,
|
||||
Some(vec![sym::gen_future].into()),
|
||||
self.allow_gen_future.clone(),
|
||||
);
|
||||
|
||||
// let mut pinned = <expr>;
|
||||
@@ -5864,7 +5891,7 @@ fn lower_await(
|
||||
let unit = self.expr_unit(span);
|
||||
let yield_expr = P(self.expr(
|
||||
span,
|
||||
hir::ExprKind::Yield(P(unit)),
|
||||
hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
|
||||
ThinVec::new(),
|
||||
));
|
||||
self.stmt(span, hir::StmtKind::Expr(yield_expr))
|
||||
|
||||
+56
-16
@@ -1306,7 +1306,7 @@ pub struct BodyId {
|
||||
///
|
||||
/// - an `arguments` array containing the `(x, y)` pattern
|
||||
/// - a `value` containing the `x + y` expression (maybe wrapped in a block)
|
||||
/// - `is_generator` would be false
|
||||
/// - `generator_kind` would be `None`
|
||||
///
|
||||
/// All bodies have an **owner**, which can be accessed via the HIR
|
||||
/// map using `body_owner_def_id()`.
|
||||
@@ -1314,7 +1314,7 @@ pub struct BodyId {
|
||||
pub struct Body {
|
||||
pub arguments: HirVec<Arg>,
|
||||
pub value: Expr,
|
||||
pub is_generator: bool,
|
||||
pub generator_kind: Option<GeneratorKind>,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
@@ -1325,6 +1325,26 @@ pub fn id(&self) -> BodyId {
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of source expression that caused this generator to be created.
|
||||
// Not `IsAsync` because we want to eventually add support for `AsyncGen`
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
|
||||
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
pub enum GeneratorKind {
|
||||
/// An `async` block or function.
|
||||
Async,
|
||||
/// A generator literal created via a `yield` inside a closure.
|
||||
Gen,
|
||||
}
|
||||
|
||||
impl fmt::Display for GeneratorKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
GeneratorKind::Async => "`async` object",
|
||||
GeneratorKind::Gen => "generator",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum BodyOwnerKind {
|
||||
/// Functions and methods.
|
||||
@@ -1531,8 +1551,8 @@ pub enum ExprKind {
|
||||
///
|
||||
/// The final span is the span of the argument block `|...|`.
|
||||
///
|
||||
/// This may also be a generator literal, indicated by the final boolean,
|
||||
/// in that case there is an `GeneratorClause`.
|
||||
/// This may also be a generator literal or an `async block` as indicated by the
|
||||
/// `Option<GeneratorMovability>`.
|
||||
Closure(CaptureClause, P<FnDecl>, BodyId, Span, Option<GeneratorMovability>),
|
||||
/// A block (e.g., `'label: { ... }`).
|
||||
Block(P<Block>, Option<Label>),
|
||||
@@ -1576,7 +1596,7 @@ pub enum ExprKind {
|
||||
Repeat(P<Expr>, AnonConst),
|
||||
|
||||
/// A suspension point for generators (i.e., `yield <expr>`).
|
||||
Yield(P<Expr>),
|
||||
Yield(P<Expr>, YieldSource),
|
||||
|
||||
/// A placeholder for an expression that wasn't syntactically well formed in some way.
|
||||
Err,
|
||||
@@ -1668,12 +1688,12 @@ pub enum LoopIdError {
|
||||
|
||||
impl fmt::Display for LoopIdError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(match *self {
|
||||
f.write_str(match self {
|
||||
LoopIdError::OutsideLoopScope => "not inside loop scope",
|
||||
LoopIdError::UnlabeledCfInWhileCondition =>
|
||||
"unlabeled control flow (break or continue) in while condition",
|
||||
LoopIdError::UnresolvedLabel => "label not found",
|
||||
}, f)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1687,13 +1707,34 @@ pub struct Destination {
|
||||
pub target_id: Result<HirId, LoopIdError>,
|
||||
}
|
||||
|
||||
/// Whether a generator contains self-references, causing it to be `!Unpin`.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, HashStable,
|
||||
RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
|
||||
pub enum GeneratorMovability {
|
||||
/// May contain self-references, `!Unpin`.
|
||||
Static,
|
||||
/// Must not contain self-references, `Unpin`.
|
||||
Movable,
|
||||
}
|
||||
|
||||
/// The yield kind that caused an `ExprKind::Yield`.
|
||||
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum YieldSource {
|
||||
/// An `<expr>.await`.
|
||||
Await,
|
||||
/// A plain `yield`.
|
||||
Yield,
|
||||
}
|
||||
|
||||
impl fmt::Display for YieldSource {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(match self {
|
||||
YieldSource::Await => "`await`",
|
||||
YieldSource::Yield => "`yield`",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, HashStable)]
|
||||
pub enum CaptureClause {
|
||||
CaptureByValue,
|
||||
@@ -2058,11 +2099,10 @@ pub fn is_default(&self) -> bool {
|
||||
|
||||
impl fmt::Display for Unsafety {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(match *self {
|
||||
Unsafety::Normal => "normal",
|
||||
Unsafety::Unsafe => "unsafe",
|
||||
},
|
||||
f)
|
||||
f.write_str(match self {
|
||||
Unsafety::Normal => "normal",
|
||||
Unsafety::Unsafe => "unsafe",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2076,10 +2116,10 @@ pub enum ImplPolarity {
|
||||
|
||||
impl fmt::Debug for ImplPolarity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
ImplPolarity::Positive => "positive".fmt(f),
|
||||
ImplPolarity::Negative => "negative".fmt(f),
|
||||
}
|
||||
f.write_str(match self {
|
||||
ImplPolarity::Positive => "positive",
|
||||
ImplPolarity::Negative => "negative",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1501,7 +1501,7 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
|
||||
|
||||
self.pclose()?;
|
||||
}
|
||||
hir::ExprKind::Yield(ref expr) => {
|
||||
hir::ExprKind::Yield(ref expr, _) => {
|
||||
self.word_space("yield")?;
|
||||
self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?;
|
||||
}
|
||||
|
||||
@@ -335,15 +335,15 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
let hir::Body {
|
||||
ref arguments,
|
||||
ref value,
|
||||
is_generator,
|
||||
} = *self;
|
||||
arguments,
|
||||
value,
|
||||
generator_kind,
|
||||
} = self;
|
||||
|
||||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::Ignore, |hcx| {
|
||||
arguments.hash_stable(hcx, hasher);
|
||||
value.hash_stable(hcx, hasher);
|
||||
is_generator.hash_stable(hcx, hasher);
|
||||
generator_kind.hash_stable(hcx, hasher);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,10 +391,17 @@ fn hash_stable<W: StableHasherResult>(&self,
|
||||
NameValue(lit)
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::syntax_pos::hygiene::Transparency {
|
||||
Transparent,
|
||||
SemiTransparent,
|
||||
Opaque,
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
|
||||
call_site,
|
||||
def_site,
|
||||
format,
|
||||
def_site,
|
||||
default_transparency,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use std::sync::atomic::Ordering;
|
||||
use crate::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use crate::ty::subst::Kind;
|
||||
use crate::ty::{self, BoundVar, InferConst, Lift, List, Ty, TyCtxt, TypeFlags};
|
||||
use crate::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags};
|
||||
use crate::ty::flags::FlagComputation;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
@@ -43,7 +43,7 @@ pub fn canonicalize_query<V>(
|
||||
query_state: &mut OriginalQueryValues<'tcx>,
|
||||
) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
{
|
||||
self.tcx
|
||||
.sess
|
||||
@@ -87,7 +87,7 @@ pub fn canonicalize_query<V>(
|
||||
/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
|
||||
pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
{
|
||||
let mut query_state = OriginalQueryValues::default();
|
||||
Canonicalizer::canonicalize(
|
||||
@@ -101,7 +101,7 @@ pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'tcx, V>
|
||||
|
||||
pub fn canonicalize_user_type_annotation<V>(&self, value: &V) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
{
|
||||
let mut query_state = OriginalQueryValues::default();
|
||||
Canonicalizer::canonicalize(
|
||||
@@ -132,7 +132,7 @@ pub fn canonicalize_hr_query_hack<V>(
|
||||
query_state: &mut OriginalQueryValues<'tcx>,
|
||||
) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
{
|
||||
self.tcx
|
||||
.sess
|
||||
@@ -506,7 +506,7 @@ fn canonicalize<V>(
|
||||
query_state: &mut OriginalQueryValues<'tcx>,
|
||||
) -> Canonicalized<'tcx, V>
|
||||
where
|
||||
V: TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
V: TypeFoldable<'tcx>,
|
||||
{
|
||||
let needs_canonical_flags = if canonicalize_region_mode.any() {
|
||||
TypeFlags::KEEP_IN_LOCAL_TCX |
|
||||
@@ -520,20 +520,12 @@ fn canonicalize<V>(
|
||||
TypeFlags::HAS_CT_PLACEHOLDER
|
||||
};
|
||||
|
||||
let gcx = tcx.global_tcx();
|
||||
|
||||
// Fast path: nothing that needs to be canonicalized.
|
||||
if !value.has_type_flags(needs_canonical_flags) {
|
||||
let out_value = gcx.lift(value).unwrap_or_else(|| {
|
||||
bug!(
|
||||
"failed to lift `{:?}` (nothing to canonicalize)",
|
||||
value
|
||||
)
|
||||
});
|
||||
let canon_value = Canonical {
|
||||
max_universe: ty::UniverseIndex::ROOT,
|
||||
variables: List::empty(),
|
||||
value: out_value,
|
||||
value: value.clone(),
|
||||
};
|
||||
return canon_value;
|
||||
}
|
||||
@@ -553,13 +545,7 @@ fn canonicalize<V>(
|
||||
// Once we have canonicalized `out_value`, it should not
|
||||
// contain anything that ties it to this inference context
|
||||
// anymore, so it should live in the global arena.
|
||||
let out_value = gcx.lift(&out_value).unwrap_or_else(|| {
|
||||
bug!(
|
||||
"failed to lift `{:?}`, canonicalized from `{:?}`",
|
||||
out_value,
|
||||
value
|
||||
)
|
||||
});
|
||||
debug_assert!(!out_value.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX));
|
||||
|
||||
let canonical_variables = tcx.intern_canonical_var_infos(&canonicalizer.variables);
|
||||
|
||||
|
||||
@@ -194,10 +194,10 @@ pub struct QueryResponse<'tcx, R> {
|
||||
pub value: R,
|
||||
}
|
||||
|
||||
pub type Canonicalized<'tcx, V> = Canonical<'tcx, <V as Lift<'tcx>>::Lifted>;
|
||||
pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>;
|
||||
|
||||
pub type CanonicalizedQueryResponse<'tcx, T> =
|
||||
&'tcx Canonical<'tcx, QueryResponse<'tcx, <T as Lift<'tcx>>::Lifted>>;
|
||||
&'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
|
||||
|
||||
/// Indicates whether or not we were able to prove the query to be
|
||||
/// true.
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
use crate::ty::subst::{Kind, UnpackedKind};
|
||||
use crate::ty::{self, BoundVar, InferConst, Lift, Ty, TyCtxt};
|
||||
use crate::ty::{self, BoundVar, InferConst, Ty, TyCtxt};
|
||||
use crate::util::captures::Captures;
|
||||
|
||||
impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||
@@ -53,8 +53,8 @@ pub fn enter_canonical_trait_query<K, R>(
|
||||
) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
|
||||
where
|
||||
K: TypeFoldable<'tcx>,
|
||||
R: Debug + Lift<'tcx> + TypeFoldable<'tcx>,
|
||||
Canonical<'tcx, <QueryResponse<'tcx, R> as Lift<'tcx>>::Lifted>: ArenaAllocatable,
|
||||
R: Debug + TypeFoldable<'tcx>,
|
||||
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
|
||||
{
|
||||
self.enter_with_canonical(
|
||||
DUMMY_SP,
|
||||
@@ -99,8 +99,8 @@ pub fn make_canonicalized_query_response<T>(
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
|
||||
where
|
||||
T: Debug + Lift<'tcx> + TypeFoldable<'tcx>,
|
||||
Canonical<'tcx, <QueryResponse<'tcx, T> as Lift<'tcx>>::Lifted>: ArenaAllocatable,
|
||||
T: Debug + TypeFoldable<'tcx>,
|
||||
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable,
|
||||
{
|
||||
let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
|
||||
let canonical_result = self.canonicalize_response(&query_response);
|
||||
@@ -126,9 +126,9 @@ pub fn make_query_response_ignoring_pending_obligations<T>(
|
||||
&self,
|
||||
inference_vars: CanonicalVarValues<'tcx>,
|
||||
answer: T,
|
||||
) -> Canonical<'tcx, QueryResponse<'tcx, <T as Lift<'tcx>>::Lifted>>
|
||||
) -> Canonical<'tcx, QueryResponse<'tcx, T>>
|
||||
where
|
||||
T: Debug + Lift<'tcx> + TypeFoldable<'tcx>,
|
||||
T: Debug + TypeFoldable<'tcx>,
|
||||
{
|
||||
self.canonicalize_response(&QueryResponse {
|
||||
var_values: inference_vars,
|
||||
@@ -147,7 +147,7 @@ fn make_query_response<T>(
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Result<QueryResponse<'tcx, T>, NoSolution>
|
||||
where
|
||||
T: Debug + TypeFoldable<'tcx> + Lift<'tcx>,
|
||||
T: Debug + TypeFoldable<'tcx>,
|
||||
{
|
||||
let tcx = self.tcx;
|
||||
|
||||
|
||||
@@ -227,16 +227,15 @@ pub fn need_type_info_err(
|
||||
|
||||
pub fn need_type_info_err_in_generator(
|
||||
&self,
|
||||
kind: hir::GeneratorKind,
|
||||
span: Span,
|
||||
ty: Ty<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let ty = self.resolve_vars_if_possible(&ty);
|
||||
let name = self.extract_type_name(&ty, None);
|
||||
|
||||
let mut err = struct_span_err!(self.tcx.sess,
|
||||
span,
|
||||
E0698,
|
||||
"type inside generator must be known in this context");
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx.sess, span, E0698, "type inside {} must be known in this context", kind,
|
||||
);
|
||||
err.span_label(span, InferCtxt::missing_type_msg(&name));
|
||||
err
|
||||
}
|
||||
|
||||
@@ -469,11 +469,6 @@ pub fn infer_opaque_definition_from_instantiation(
|
||||
definition_ty
|
||||
);
|
||||
|
||||
// We can unwrap here because our reverse mapper always
|
||||
// produces things with 'tcx lifetime, though the type folder
|
||||
// obscures that.
|
||||
let definition_ty = gcx.lift(&definition_ty).unwrap();
|
||||
|
||||
definition_ty
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,7 +546,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
|
||||
self.consume_expr(&base);
|
||||
}
|
||||
|
||||
hir::ExprKind::Yield(ref value) => {
|
||||
hir::ExprKind::Yield(ref value, _) => {
|
||||
self.consume_expr(&value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1218,7 +1218,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
|
||||
hir::ExprKind::Type(ref e, _) |
|
||||
hir::ExprKind::DropTemps(ref e) |
|
||||
hir::ExprKind::Unary(_, ref e) |
|
||||
hir::ExprKind::Yield(ref e) |
|
||||
hir::ExprKind::Yield(ref e, _) |
|
||||
hir::ExprKind::Repeat(ref e, _) => {
|
||||
self.propagate_through_expr(&e, succ)
|
||||
}
|
||||
|
||||
@@ -817,10 +817,7 @@ fn cat_upvar(
|
||||
.unwrap_or(ty::ClosureKind::LATTICE_BOTTOM),
|
||||
|
||||
None =>
|
||||
self.tcx.global_tcx()
|
||||
.lift(&closure_substs)
|
||||
.expect("no inference cx, but inference variables in closure ty")
|
||||
.closure_kind(closure_def_id, self.tcx.global_tcx()),
|
||||
closure_substs.closure_kind(closure_def_id, self.tcx.global_tcx()),
|
||||
}
|
||||
}
|
||||
_ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty),
|
||||
|
||||
@@ -331,7 +331,7 @@ pub struct ScopeTree {
|
||||
/// The reason is that semantically, until the `box` expression returns,
|
||||
/// the values are still owned by their containing expressions. So
|
||||
/// we'll see that `&x`.
|
||||
yield_in_scope: FxHashMap<Scope, (Span, usize)>,
|
||||
yield_in_scope: FxHashMap<Scope, YieldData>,
|
||||
|
||||
/// The number of visit_expr and visit_pat calls done in the body.
|
||||
/// Used to sanity check visit_expr/visit_pat call count when
|
||||
@@ -339,6 +339,15 @@ pub struct ScopeTree {
|
||||
body_expr_count: FxHashMap<hir::BodyId, usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct YieldData {
|
||||
/// `Span` of the yield.
|
||||
pub span: Span,
|
||||
/// The number of expressions and patterns appearing before the `yield` in the body + 1.
|
||||
pub expr_and_pat_count: usize,
|
||||
pub source: hir::YieldSource,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Context {
|
||||
/// the root of the current region tree. This is typically the id
|
||||
@@ -695,7 +704,7 @@ pub fn free_scope(&self, tcx: TyCtxt<'tcx>, fr: &ty::FreeRegion) -> Scope {
|
||||
/// returns `Some((span, expr_count))` with the span of a yield we found and
|
||||
/// the number of expressions and patterns appearing before the `yield` in the body + 1.
|
||||
/// If there a are multiple yields in a scope, the one with the highest number is returned.
|
||||
pub fn yield_in_scope(&self, scope: Scope) -> Option<(Span, usize)> {
|
||||
pub fn yield_in_scope(&self, scope: Scope) -> Option<YieldData> {
|
||||
self.yield_in_scope.get(&scope).cloned()
|
||||
}
|
||||
|
||||
@@ -706,14 +715,14 @@ pub fn yield_in_scope_for_expr(&self,
|
||||
scope: Scope,
|
||||
expr_hir_id: hir::HirId,
|
||||
body: &'tcx hir::Body) -> Option<Span> {
|
||||
self.yield_in_scope(scope).and_then(|(span, count)| {
|
||||
self.yield_in_scope(scope).and_then(|YieldData { span, expr_and_pat_count, .. }| {
|
||||
let mut visitor = ExprLocatorVisitor {
|
||||
hir_id: expr_hir_id,
|
||||
result: None,
|
||||
expr_and_pat_count: 0,
|
||||
};
|
||||
visitor.visit_body(body);
|
||||
if count >= visitor.result.unwrap() {
|
||||
if expr_and_pat_count >= visitor.result.unwrap() {
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
@@ -953,12 +962,16 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
||||
|
||||
debug!("resolve_expr post-increment {}, expr = {:?}", visitor.expr_and_pat_count, expr);
|
||||
|
||||
if let hir::ExprKind::Yield(..) = expr.node {
|
||||
if let hir::ExprKind::Yield(_, source) = &expr.node {
|
||||
// Mark this expr's scope and all parent scopes as containing `yield`.
|
||||
let mut scope = Scope { id: expr.hir_id.local_id, data: ScopeData::Node };
|
||||
loop {
|
||||
visitor.scope_tree.yield_in_scope.insert(scope,
|
||||
(expr.span, visitor.expr_and_pat_count));
|
||||
let data = YieldData {
|
||||
span: expr.span,
|
||||
expr_and_pat_count: visitor.expr_and_pat_count,
|
||||
source: *source,
|
||||
};
|
||||
visitor.scope_tree.yield_in_scope.insert(scope, data);
|
||||
|
||||
// Keep traversing up while we can.
|
||||
match visitor.scope_tree.parent_map.get(&scope) {
|
||||
@@ -1302,7 +1315,7 @@ fn visit_body(&mut self, body: &'tcx hir::Body) {
|
||||
resolve_local(self, None, Some(&body.value));
|
||||
}
|
||||
|
||||
if body.is_generator {
|
||||
if body.generator_kind.is_some() {
|
||||
self.scope_tree.body_expr_count.insert(body_id, self.expr_and_pat_count);
|
||||
}
|
||||
|
||||
|
||||
@@ -141,9 +141,9 @@ fn drain_fulfillment_cx_or_panic<T>(
|
||||
&self,
|
||||
fulfill_cx: &mut FulfillmentContext<'tcx>,
|
||||
result: &T,
|
||||
) -> T::Lifted
|
||||
) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx> + ty::Lift<'tcx>,
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
debug!("drain_fulfillment_cx_or_panic()");
|
||||
|
||||
@@ -155,10 +155,6 @@ fn drain_fulfillment_cx_or_panic<T>(
|
||||
}
|
||||
|
||||
let result = self.resolve_vars_if_possible(result);
|
||||
let result = self.tcx.erase_regions(&result);
|
||||
|
||||
self.tcx.lift_to_global(&result).unwrap_or_else(||
|
||||
bug!("Uninferred types/regions/consts in `{:?}`", result)
|
||||
)
|
||||
self.tcx.erase_regions(&result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +409,6 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
|
||||
promoted: None
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||
let evaluated = evaluated.subst(tcx, substs);
|
||||
return evaluated;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,6 @@ fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tc
|
||||
promoted: None,
|
||||
};
|
||||
if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
|
||||
let substs = tcx.lift_to_global(&substs).unwrap();
|
||||
let evaluated = evaluated.subst(tcx, substs);
|
||||
return evaluated;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use crate::traits::query::Fallible;
|
||||
use crate::traits::ObligationCause;
|
||||
use crate::ty::fold::TypeFoldable;
|
||||
use crate::ty::{Lift, ParamEnvAnd, TyCtxt};
|
||||
use crate::ty::{ParamEnvAnd, TyCtxt};
|
||||
|
||||
pub mod ascribe_user_type;
|
||||
pub mod custom;
|
||||
@@ -44,8 +44,8 @@ fn fully_perform(
|
||||
/// which produces the resulting query region constraints.
|
||||
///
|
||||
/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
|
||||
pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'tcx> {
|
||||
type QueryResponse: TypeFoldable<'tcx> + Lift<'tcx>;
|
||||
pub trait QueryTypeOp<'tcx>: fmt::Debug + Sized + TypeFoldable<'tcx> + 'tcx {
|
||||
type QueryResponse: TypeFoldable<'tcx>;
|
||||
|
||||
/// Give query the option for a simple fast path that never
|
||||
/// actually hits the tcx cache lookup etc. Return `Some(r)` with
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn new(value: T) -> Self {
|
||||
|
||||
impl<'tcx, T> super::QueryTypeOp<'tcx> for Normalize<T>
|
||||
where
|
||||
T: Normalizable<'tcx>,
|
||||
T: Normalizable<'tcx> + 'tcx,
|
||||
{
|
||||
type QueryResponse = T;
|
||||
|
||||
|
||||
@@ -132,12 +132,7 @@ pub fn find_associated_item<'tcx>(
|
||||
let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
|
||||
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
|
||||
substs, node_item.node);
|
||||
let substs = infcx.tcx.erase_regions(&substs);
|
||||
tcx.lift(&substs).unwrap_or_else(||
|
||||
bug!("find_method: translate_substs \
|
||||
returned {:?} which contains inference types/regions",
|
||||
substs)
|
||||
)
|
||||
infcx.tcx.erase_regions(&substs)
|
||||
});
|
||||
(node_item.item.def_id, substs)
|
||||
}
|
||||
|
||||
@@ -192,9 +192,12 @@ pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
|
||||
|
||||
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
|
||||
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
|
||||
ty::Array(_, n) => match n.assert_usize(tcx) {
|
||||
Some(n) => format!("array of {} elements", n).into(),
|
||||
None => "array".into(),
|
||||
ty::Array(_, n) => {
|
||||
let n = tcx.lift_to_global(&n).unwrap();
|
||||
match n.assert_usize(tcx) {
|
||||
Some(n) => format!("array of {} elements", n).into(),
|
||||
None => "array".into(),
|
||||
}
|
||||
}
|
||||
ty::Slice(_) => "slice".into(),
|
||||
ty::RawPtr(_) => "*-ptr".into(),
|
||||
|
||||
@@ -2262,7 +2262,6 @@ pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self {
|
||||
|
||||
#[inline]
|
||||
pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> &'tcx Self {
|
||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
||||
let size = tcx.layout_of(ty).unwrap_or_else(|e| {
|
||||
panic!("could not compute layout for {:?}: {:?}", ty, e)
|
||||
}).size;
|
||||
@@ -2289,7 +2288,6 @@ pub fn to_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Opt
|
||||
if self.ty != ty.value {
|
||||
return None;
|
||||
}
|
||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
||||
let size = tcx.layout_of(ty).ok()?.size;
|
||||
self.val.try_to_bits(size)
|
||||
}
|
||||
@@ -2300,15 +2298,14 @@ pub fn to_ptr(&self) -> Option<Pointer> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_bits(&self, tcx: TyCtxt<'_>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option<u128> {
|
||||
pub fn assert_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Option<u128> {
|
||||
assert_eq!(self.ty, ty.value);
|
||||
let ty = tcx.lift_to_global(&ty).unwrap();
|
||||
let size = tcx.layout_of(ty).ok()?.size;
|
||||
self.val.try_to_bits(size)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_bool(&self, tcx: TyCtxt<'_>) -> Option<bool> {
|
||||
pub fn assert_bool(&self, tcx: TyCtxt<'tcx>) -> Option<bool> {
|
||||
self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.bool)).and_then(|v| match v {
|
||||
0 => Some(false),
|
||||
1 => Some(true),
|
||||
@@ -2317,18 +2314,18 @@ pub fn assert_bool(&self, tcx: TyCtxt<'_>) -> Option<bool> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn assert_usize(&self, tcx: TyCtxt<'_>) -> Option<u64> {
|
||||
pub fn assert_usize(&self, tcx: TyCtxt<'tcx>) -> Option<u64> {
|
||||
self.assert_bits(tcx, ParamEnv::empty().and(tcx.types.usize)).map(|v| v as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unwrap_bits(&self, tcx: TyCtxt<'_>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 {
|
||||
pub fn unwrap_bits(&self, tcx: TyCtxt<'tcx>, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> u128 {
|
||||
self.assert_bits(tcx, ty).unwrap_or_else(||
|
||||
bug!("expected bits of {}, got {:#?}", ty.value, self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn unwrap_usize(&self, tcx: TyCtxt<'_>) -> u64 {
|
||||
pub fn unwrap_usize(&self, tcx: TyCtxt<'tcx>) -> u64 {
|
||||
self.assert_usize(tcx).unwrap_or_else(||
|
||||
bug!("expected constant usize, got {:#?}", self))
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
mut_visit::{self, MutVisitor},
|
||||
parse::ParseSess,
|
||||
ptr::P,
|
||||
symbol::{kw, sym, Symbol}
|
||||
symbol::{kw, sym}
|
||||
};
|
||||
use syntax_pos::Span;
|
||||
|
||||
@@ -58,11 +58,10 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
|
||||
fn flat_map_item(&mut self, item: P<Item>) -> SmallVec<[P<Item>; 1]> {
|
||||
debug!("in submodule {}", self.in_submod);
|
||||
|
||||
let name = if attr::contains_name(&item.attrs, sym::global_allocator) {
|
||||
"global_allocator"
|
||||
} else {
|
||||
if !attr::contains_name(&item.attrs, sym::global_allocator) {
|
||||
return mut_visit::noop_flat_map_item(item, self);
|
||||
};
|
||||
}
|
||||
|
||||
match item.node {
|
||||
ItemKind::Static(..) => {}
|
||||
_ => {
|
||||
@@ -87,15 +86,9 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> {
|
||||
|
||||
// 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 {
|
||||
call_site: item.span, // use the call site of the static
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern(name)),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: self.sess.edition,
|
||||
});
|
||||
mark.set_expn_info(ExpnInfo::with_unstable(
|
||||
MacroAttribute(sym::global_allocator), item.span, self.sess.edition, &[sym::rustc_attrs]
|
||||
));
|
||||
|
||||
// Tie the span to the macro expansion info we just created
|
||||
let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax::visit;
|
||||
use syntax::{span_err, span_fatal};
|
||||
@@ -611,33 +611,31 @@ fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, s
|
||||
};
|
||||
|
||||
let extensions = decls.iter().map(|&decl| {
|
||||
match decl {
|
||||
let (name, kind, helper_attrs) = match decl {
|
||||
ProcMacro::CustomDerive { trait_name, attributes, client } => {
|
||||
let attrs = attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
||||
(trait_name, SyntaxExtension::Derive(
|
||||
Box::new(ProcMacroDerive {
|
||||
client,
|
||||
attrs: attrs.clone(),
|
||||
}),
|
||||
attrs,
|
||||
root.edition,
|
||||
))
|
||||
let helper_attrs =
|
||||
attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>();
|
||||
(
|
||||
trait_name,
|
||||
SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive {
|
||||
client, attrs: helper_attrs.clone()
|
||||
})),
|
||||
helper_attrs,
|
||||
)
|
||||
}
|
||||
ProcMacro::Attr { name, client } => {
|
||||
(name, SyntaxExtension::Attr(
|
||||
Box::new(AttrProcMacro { client }),
|
||||
root.edition,
|
||||
))
|
||||
}
|
||||
ProcMacro::Bang { name, client } => {
|
||||
(name, SyntaxExtension::Bang {
|
||||
expander: Box::new(BangProcMacro { client }),
|
||||
allow_internal_unstable: None,
|
||||
edition: root.edition,
|
||||
})
|
||||
}
|
||||
}
|
||||
}).map(|(name, ext)| (Symbol::intern(name), Lrc::new(ext))).collect();
|
||||
ProcMacro::Attr { name, client } => (
|
||||
name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()
|
||||
),
|
||||
ProcMacro::Bang { name, client } => (
|
||||
name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()
|
||||
)
|
||||
};
|
||||
|
||||
(Symbol::intern(name), Lrc::new(SyntaxExtension {
|
||||
helper_attrs,
|
||||
..SyntaxExtension::default(kind, root.edition)
|
||||
}))
|
||||
}).collect();
|
||||
|
||||
// Intentionally leak the dynamic library. We can't ever unload it
|
||||
// since the library can make things that will live arbitrarily long.
|
||||
|
||||
@@ -30,9 +30,11 @@
|
||||
use syntax::attr;
|
||||
use syntax::source_map;
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::parse::source_file_to_stream;
|
||||
use syntax::parse::parser::emit_unclosed_delims;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax_ext::proc_macro_impl::BangProcMacro;
|
||||
use syntax_pos::{Span, NO_EXPANSION, FileName};
|
||||
use rustc_data_structures::bit_set::BitSet;
|
||||
|
||||
@@ -427,14 +429,11 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
|
||||
if let Some(ref proc_macros) = data.proc_macros {
|
||||
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
|
||||
} else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote {
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax_ext::proc_macro_impl::BangProcMacro;
|
||||
|
||||
let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote);
|
||||
let ext = SyntaxExtension::Bang {
|
||||
expander: Box::new(BangProcMacro { client }),
|
||||
allow_internal_unstable: Some(vec![sym::proc_macro_def_site].into()),
|
||||
edition: data.root.edition,
|
||||
let kind = SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }));
|
||||
let ext = SyntaxExtension {
|
||||
allow_internal_unstable: Some([sym::proc_macro_def_site][..].into()),
|
||||
..SyntaxExtension::default(kind, data.root.edition)
|
||||
};
|
||||
return LoadedMacro::ProcMacro(Lrc::new(ext));
|
||||
}
|
||||
|
||||
@@ -509,8 +509,9 @@ pub fn def_kind(&self, index: DefIndex) -> Option<DefKind> {
|
||||
if !self.is_proc_macro(index) {
|
||||
self.entry(index).kind.def_kind()
|
||||
} else {
|
||||
let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind();
|
||||
Some(DefKind::Macro(kind))
|
||||
Some(DefKind::Macro(
|
||||
self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.macro_kind()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -737,7 +738,7 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Sessio
|
||||
if id == CRATE_DEF_INDEX {
|
||||
for (id, &(name, ref ext)) in proc_macros.iter().enumerate() {
|
||||
let res = Res::Def(
|
||||
DefKind::Macro(ext.kind()),
|
||||
DefKind::Macro(ext.macro_kind()),
|
||||
self.local_def_id(DefIndex::from_proc_macro_index(id)),
|
||||
);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
|
||||
@@ -670,7 +670,7 @@ fn visit_terminator_entry(
|
||||
// "Lift" into the gcx -- once regions are erased, this type should be in the
|
||||
// global arenas; this "lift" operation basically just asserts that is true, but
|
||||
// that is useful later.
|
||||
let drop_place_ty = gcx.lift(&drop_place_ty).unwrap();
|
||||
gcx.lift_to_global(&drop_place_ty).unwrap();
|
||||
|
||||
debug!("visit_terminator_drop \
|
||||
loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
|
||||
|
||||
@@ -863,8 +863,8 @@ fn try_promote_type_test_subject(
|
||||
});
|
||||
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
|
||||
|
||||
// `lift` will only fail if we failed to promote some region.
|
||||
let ty = gcx.lift(&ty)?;
|
||||
// `lift_to_global` will only fail if we failed to promote some region.
|
||||
gcx.lift_to_global(&ty)?;
|
||||
|
||||
Some(ClosureOutlivesSubject::Ty(ty))
|
||||
}
|
||||
|
||||
@@ -1864,7 +1864,7 @@ fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
|
||||
// `Sized` bound in no way depends on precise regions, so this
|
||||
// shouldn't affect `is_sized`.
|
||||
let gcx = tcx.global_tcx();
|
||||
let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
|
||||
let erased_ty = tcx.erase_regions(&ty);
|
||||
if !erased_ty.is_sized(gcx.at(span), self.param_env) {
|
||||
// in current MIR construction, all non-control-flow rvalue
|
||||
// expressions evaluate through `as_temp` or `into` a return
|
||||
@@ -2650,7 +2650,7 @@ fn typeck_mir(&mut self, body: &Body<'tcx>) {
|
||||
|
||||
fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
|
||||
where
|
||||
T: type_op::normalize::Normalizable<'tcx> + Copy,
|
||||
T: type_op::normalize::Normalizable<'tcx> + Copy + 'tcx,
|
||||
{
|
||||
debug!("normalize(value={:?}, location={:?})", value, location);
|
||||
let param_env = self.param_env;
|
||||
|
||||
@@ -569,7 +569,7 @@ fn limit_capture_mutability(
|
||||
|
||||
// Helper to get a `-1` value of the appropriate type
|
||||
fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
|
||||
let param_ty = ty::ParamEnv::empty().and(ty);
|
||||
let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits();
|
||||
let n = (!0u128) >> (128 - bits);
|
||||
let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty);
|
||||
@@ -580,7 +580,7 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
// Helper to get the minimum value of the appropriate type
|
||||
fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
|
||||
assert!(ty.is_signed());
|
||||
let param_ty = ty::ParamEnv::empty().and(self.hir.tcx().lift_to_global(&ty).unwrap());
|
||||
let param_ty = ty::ParamEnv::empty().and(ty);
|
||||
let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits();
|
||||
let n = 1 << (bits - 1);
|
||||
let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty);
|
||||
|
||||
@@ -126,7 +126,7 @@ pub fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Body<'tcx> {
|
||||
|
||||
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
||||
|
||||
let (yield_ty, return_ty) = if body.is_generator {
|
||||
let (yield_ty, return_ty) = if body.generator_kind.is_some() {
|
||||
let gen_sig = match ty.sty {
|
||||
ty::Generator(gen_def_id, gen_substs, ..) =>
|
||||
gen_substs.sig(gen_def_id, tcx),
|
||||
@@ -590,7 +590,7 @@ fn construct_fn<'a, 'tcx, A>(
|
||||
return_ty_span,
|
||||
upvar_debuginfo,
|
||||
upvar_mutbls,
|
||||
body.is_generator);
|
||||
body.generator_kind.is_some());
|
||||
|
||||
let call_site_scope = region::Scope {
|
||||
id: body.value.hir_id.local_id,
|
||||
|
||||
@@ -151,7 +151,7 @@ pub(crate) fn on_all_drop_children_bits<'tcx, F>(
|
||||
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, place, ty);
|
||||
|
||||
let gcx = tcx.global_tcx();
|
||||
let erased_ty = gcx.lift(&tcx.erase_regions(&ty)).unwrap();
|
||||
let erased_ty = tcx.erase_regions(&ty);
|
||||
if erased_ty.needs_drop(gcx, ctxt.param_env) {
|
||||
each_child(child);
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
use syntax::ast::*;
|
||||
|
||||
let trunc = |n| {
|
||||
let param_ty = ParamEnv::reveal_all().and(tcx.lift_to_global(&ty).unwrap());
|
||||
let param_ty = ParamEnv::reveal_all().and(ty);
|
||||
let width = tcx.layout_of(param_ty).map_err(|_| LitToConstError::Reported)?.size;
|
||||
trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits());
|
||||
let result = truncate(n, width);
|
||||
|
||||
@@ -763,7 +763,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
|
||||
hir::ExprKind::Array(ref fields) => ExprKind::Array { fields: fields.to_ref() },
|
||||
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() },
|
||||
|
||||
hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() },
|
||||
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: v.to_ref() },
|
||||
hir::ExprKind::Err => unreachable!(),
|
||||
};
|
||||
|
||||
|
||||
@@ -190,12 +190,7 @@ pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) ->
|
||||
}
|
||||
|
||||
pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
let (ty, param_env) = self.tcx.lift_to_global(&(ty, self.param_env)).unwrap_or_else(|| {
|
||||
bug!("MIR: Cx::needs_drop({:?}, {:?}) got \
|
||||
type with inference types/regions",
|
||||
ty, self.param_env);
|
||||
});
|
||||
ty.needs_drop(self.tcx.global_tcx(), param_env)
|
||||
ty.needs_drop(self.tcx.global_tcx(), self.param_env)
|
||||
}
|
||||
|
||||
pub fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
|
||||
@@ -1310,7 +1310,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
|
||||
/// Returns `None` in case of a catch-all, which can't be specialized.
|
||||
fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
|
||||
pat: &Pattern<'tcx>,
|
||||
pcx: PatternContext<'_>)
|
||||
pcx: PatternContext<'tcx>)
|
||||
-> Option<Vec<Constructor<'tcx>>>
|
||||
{
|
||||
match *pat.kind {
|
||||
|
||||
@@ -545,7 +545,7 @@ fn check_expr_kind<'a, 'tcx>(
|
||||
}
|
||||
|
||||
// Generator expressions
|
||||
hir::ExprKind::Yield(ref expr) => {
|
||||
hir::ExprKind::Yield(ref expr, _) => {
|
||||
let _ = v.check_expr(&expr);
|
||||
NotPromotable
|
||||
}
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
||||
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension};
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax::ast;
|
||||
use syntax::feature_gate::AttributeType;
|
||||
@@ -89,8 +88,8 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: Synt
|
||||
if name == sym::macro_rules {
|
||||
panic!("user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
if let SyntaxExtension::LegacyBang { def_info: ref mut def_info @ None, .. } = extension {
|
||||
*def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
|
||||
if extension.def_info.is_none() {
|
||||
extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
|
||||
}
|
||||
self.syntax_exts.push((name, extension));
|
||||
}
|
||||
@@ -98,19 +97,12 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: Synt
|
||||
/// Register a macro of the usual kind.
|
||||
///
|
||||
/// This is a convenience wrapper for `register_syntax_extension`.
|
||||
/// It builds for you a `SyntaxExtension::LegacyBang` that calls `expander`,
|
||||
/// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`,
|
||||
/// and also takes care of interning the macro's name.
|
||||
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
||||
self.register_syntax_extension(Symbol::intern(name), SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(expander),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition: self.sess.edition(),
|
||||
});
|
||||
let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander));
|
||||
let ext = SyntaxExtension::default(kind, self.sess.edition());
|
||||
self.register_syntax_extension(Symbol::intern(name), ext);
|
||||
}
|
||||
|
||||
/// Register a compiler lint pass.
|
||||
|
||||
@@ -772,9 +772,8 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
|
||||
pub fn get_macro(&mut self, res: Res) -> Lrc<SyntaxExtension> {
|
||||
let def_id = match res {
|
||||
Res::Def(DefKind::Macro(..), def_id) => def_id,
|
||||
Res::NonMacroAttr(attr_kind) => return Lrc::new(SyntaxExtension::NonMacroAttr {
|
||||
mark_used: attr_kind == NonMacroAttrKind::Tool,
|
||||
}),
|
||||
Res::NonMacroAttr(attr_kind) =>
|
||||
return self.non_macro_attr(attr_kind == NonMacroAttrKind::Tool),
|
||||
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
|
||||
};
|
||||
if let Some(ext) = self.macro_map.get(&def_id) {
|
||||
|
||||
@@ -41,7 +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;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::symbol::{Symbol, kw, sym};
|
||||
@@ -1668,6 +1668,7 @@ pub struct Resolver<'a> {
|
||||
macro_use_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
|
||||
pub all_macros: FxHashMap<Name, Res>,
|
||||
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
|
||||
non_macro_attrs: [Lrc<SyntaxExtension>; 2],
|
||||
macro_defs: FxHashMap<Mark, DefId>,
|
||||
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
|
||||
|
||||
@@ -1941,6 +1942,10 @@ pub fn new(session: &'a Session,
|
||||
let mut macro_defs = FxHashMap::default();
|
||||
macro_defs.insert(Mark::root(), root_def_id);
|
||||
|
||||
let non_macro_attr = |mark_used| Lrc::new(SyntaxExtension::default(
|
||||
SyntaxExtensionKind::NonMacroAttr { mark_used }, session.edition()
|
||||
));
|
||||
|
||||
Resolver {
|
||||
session,
|
||||
|
||||
@@ -2014,6 +2019,7 @@ pub fn new(session: &'a Session,
|
||||
macro_use_prelude: FxHashMap::default(),
|
||||
all_macros: FxHashMap::default(),
|
||||
macro_map: FxHashMap::default(),
|
||||
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
|
||||
invocations,
|
||||
macro_defs,
|
||||
local_macro_def_scopes: FxHashMap::default(),
|
||||
@@ -2030,6 +2036,10 @@ pub fn arenas() -> ResolverArenas<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn non_macro_attr(&self, mark_used: bool) -> Lrc<SyntaxExtension> {
|
||||
self.non_macro_attrs[mark_used as usize].clone()
|
||||
}
|
||||
|
||||
/// Runs the function on each namespace.
|
||||
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
|
||||
f(self, TypeNS);
|
||||
|
||||
@@ -114,6 +114,22 @@ enum SubNS { Bang, AttrLike }
|
||||
candidate.is_none() || requirement.is_none() || candidate == requirement
|
||||
}
|
||||
|
||||
// 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("::");
|
||||
}
|
||||
if segment.ident.name != kw::PathRoot {
|
||||
path_str.push_str(&segment.ident.as_str())
|
||||
}
|
||||
}
|
||||
path_str
|
||||
}
|
||||
|
||||
impl<'a> base::Resolver for Resolver<'a> {
|
||||
fn next_node_id(&mut self) -> ast::NodeId {
|
||||
self.session.next_node_id()
|
||||
@@ -174,7 +190,7 @@ fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>) {
|
||||
krate: CrateNum::BuiltinMacros,
|
||||
index: DefIndex::from(self.macro_map.len()),
|
||||
};
|
||||
let kind = ext.kind();
|
||||
let kind = ext.macro_kind();
|
||||
self.macro_map.insert(def_id, ext);
|
||||
let binding = self.arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Res(Res::Def(DefKind::Macro(kind), def_id), false),
|
||||
@@ -209,14 +225,19 @@ fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force
|
||||
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),
|
||||
Err(Determinacy::Determined) if kind == MacroKind::Attr => {
|
||||
// Replace unresolved attributes with used inert attributes for better recovery.
|
||||
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true })));
|
||||
}
|
||||
// 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),
|
||||
};
|
||||
|
||||
if let Res::Def(DefKind::Macro(_), def_id) = res {
|
||||
let format = match kind {
|
||||
MacroKind::Derive => format!("derive({})", fast_print_path(path)),
|
||||
_ => fast_print_path(path),
|
||||
};
|
||||
invoc.expansion_data.mark.set_expn_info(ext.expn_info(invoc.span(), &format));
|
||||
|
||||
if let Res::Def(_, def_id) = res {
|
||||
if after_derive {
|
||||
self.session.span_err(invoc.span(),
|
||||
"macro attributes must be placed before `#[derive]`");
|
||||
@@ -226,7 +247,6 @@ fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force
|
||||
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
|
||||
self.definitions.add_parent_module_of_macro_def(invoc.expansion_data.mark,
|
||||
normal_module_def_id);
|
||||
invoc.expansion_data.mark.set_default_transparency(ext.default_transparency());
|
||||
}
|
||||
|
||||
Ok(Some(ext))
|
||||
@@ -241,11 +261,7 @@ fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, invoc_id: Ma
|
||||
|
||||
fn check_unused_macros(&self) {
|
||||
for did in self.unused_macros.iter() {
|
||||
let id_span = match *self.macro_map[did] {
|
||||
SyntaxExtension::LegacyBang { def_info, .. } => def_info,
|
||||
_ => None,
|
||||
};
|
||||
if let Some((id, span)) = id_span {
|
||||
if let Some((id, span)) = self.macro_map[did].def_info {
|
||||
let lint = lint::builtin::UNUSED_MACROS;
|
||||
let msg = "unused macro definition";
|
||||
self.session.buffer_lint(lint, id, span, msg);
|
||||
@@ -585,17 +601,12 @@ struct Flags: u8 {
|
||||
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 let SyntaxExtension::Derive(_, helpers, _) = &*ext {
|
||||
if helpers.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;
|
||||
}
|
||||
}
|
||||
Ok((_, 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) => {}
|
||||
Err(Determinacy::Undetermined) =>
|
||||
|
||||
@@ -37,8 +37,7 @@ fn normalize_ty_after_erasing_regions<'tcx>(
|
||||
);
|
||||
|
||||
let normalized_value = infcx.resolve_vars_if_possible(&normalized_value);
|
||||
let normalized_value = infcx.tcx.erase_regions(&normalized_value);
|
||||
tcx.lift_to_global(&normalized_value).unwrap()
|
||||
infcx.tcx.erase_regions(&normalized_value)
|
||||
}
|
||||
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ fn check_expr_kind(
|
||||
ExprKind::Index(ref base, ref idx) => {
|
||||
self.check_expr_index(base, idx, needs, expr)
|
||||
}
|
||||
ExprKind::Yield(ref value) => {
|
||||
ExprKind::Yield(ref value, _) => {
|
||||
self.check_expr_yield(value, expr)
|
||||
}
|
||||
hir::ExprKind::Err => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use rustc::hir::{self, Pat, PatKind, Expr};
|
||||
use rustc::middle::region;
|
||||
use rustc::middle::region::{self, YieldData};
|
||||
use rustc::ty::{self, Ty};
|
||||
use syntax_pos::Span;
|
||||
use super::FnCtxt;
|
||||
@@ -17,6 +17,7 @@ struct InteriorVisitor<'a, 'tcx> {
|
||||
types: FxHashMap<Ty<'tcx>, usize>,
|
||||
region_scope_tree: &'tcx region::ScopeTree,
|
||||
expr_count: usize,
|
||||
kind: hir::GeneratorKind,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
|
||||
@@ -27,8 +28,8 @@ fn record(&mut self,
|
||||
source_span: Span) {
|
||||
use syntax_pos::DUMMY_SP;
|
||||
|
||||
let live_across_yield = scope.map_or(Some(DUMMY_SP), |s| {
|
||||
self.region_scope_tree.yield_in_scope(s).and_then(|(yield_span, expr_count)| {
|
||||
let live_across_yield = scope.map(|s| {
|
||||
self.region_scope_tree.yield_in_scope(s).and_then(|yield_data| {
|
||||
// If we are recording an expression that is the last yield
|
||||
// in the scope, or that has a postorder CFG index larger
|
||||
// than the one of all of the yields, then its value can't
|
||||
@@ -37,31 +38,43 @@ fn record(&mut self,
|
||||
// See the mega-comment at `yield_in_scope` for a proof.
|
||||
|
||||
debug!("comparing counts yield: {} self: {}, source_span = {:?}",
|
||||
expr_count, self.expr_count, source_span);
|
||||
yield_data.expr_and_pat_count, self.expr_count, source_span);
|
||||
|
||||
if expr_count >= self.expr_count {
|
||||
Some(yield_span)
|
||||
if yield_data.expr_and_pat_count >= self.expr_count {
|
||||
Some(yield_data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
});
|
||||
}).unwrap_or_else(|| Some(YieldData {
|
||||
span: DUMMY_SP,
|
||||
expr_and_pat_count: 0,
|
||||
source: match self.kind { // Guess based on the kind of the current generator.
|
||||
hir::GeneratorKind::Gen => hir::YieldSource::Yield,
|
||||
hir::GeneratorKind::Async => hir::YieldSource::Await,
|
||||
},
|
||||
}));
|
||||
|
||||
if let Some(yield_span) = live_across_yield {
|
||||
if let Some(yield_data) = live_across_yield {
|
||||
let ty = self.fcx.resolve_vars_if_possible(&ty);
|
||||
|
||||
debug!("type in expr = {:?}, scope = {:?}, type = {:?}, count = {}, yield_span = {:?}",
|
||||
expr, scope, ty, self.expr_count, yield_span);
|
||||
expr, scope, ty, self.expr_count, yield_data.span);
|
||||
|
||||
if let Some((unresolved_type, unresolved_type_span)) =
|
||||
self.fcx.unresolved_type_vars(&ty)
|
||||
{
|
||||
let note = format!("the type is part of the {} because of this {}",
|
||||
self.kind,
|
||||
yield_data.source);
|
||||
|
||||
// If unresolved type isn't a ty_var then unresolved_type_span is None
|
||||
self.fcx.need_type_info_err_in_generator(
|
||||
unresolved_type_span.unwrap_or(yield_span),
|
||||
unresolved_type)
|
||||
.span_note(yield_span,
|
||||
"the type is part of the generator because of this `yield`")
|
||||
self.kind,
|
||||
unresolved_type_span.unwrap_or(yield_data.span),
|
||||
unresolved_type,
|
||||
)
|
||||
.span_note(yield_data.span, &*note)
|
||||
.emit();
|
||||
} else {
|
||||
// Map the type to the number of types added before it
|
||||
@@ -80,6 +93,7 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||
def_id: DefId,
|
||||
body_id: hir::BodyId,
|
||||
interior: Ty<'tcx>,
|
||||
kind: hir::GeneratorKind,
|
||||
) {
|
||||
let body = fcx.tcx.hir().body(body_id);
|
||||
let mut visitor = InteriorVisitor {
|
||||
@@ -87,6 +101,7 @@ pub fn resolve_interior<'a, 'tcx>(
|
||||
types: FxHashMap::default(),
|
||||
region_scope_tree: fcx.tcx.region_scope_tree(def_id),
|
||||
expr_count: 0,
|
||||
kind,
|
||||
};
|
||||
intravisit::walk_body(&mut visitor, body);
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ pub struct Inherited<'a, 'tcx> {
|
||||
|
||||
deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
|
||||
|
||||
deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>)>>,
|
||||
deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>, hir::GeneratorKind)>>,
|
||||
|
||||
// Opaque types found in explicit return types and their
|
||||
// associated fresh inference variable. Writeback resolves these
|
||||
@@ -1071,7 +1071,7 @@ fn check_fn<'a, 'tcx>(
|
||||
|
||||
let span = body.value.span;
|
||||
|
||||
if body.is_generator && can_be_generator.is_some() {
|
||||
if body.generator_kind.is_some() && can_be_generator.is_some() {
|
||||
let yield_ty = fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::TypeInference,
|
||||
span,
|
||||
@@ -1108,12 +1108,12 @@ fn check_fn<'a, 'tcx>(
|
||||
// We insert the deferred_generator_interiors entry after visiting the body.
|
||||
// This ensures that all nested generators appear before the entry of this generator.
|
||||
// resolve_generator_interiors relies on this property.
|
||||
let gen_ty = if can_be_generator.is_some() && body.is_generator {
|
||||
let gen_ty = if let (Some(_), Some(gen_kind)) = (can_be_generator, body.generator_kind) {
|
||||
let interior = fcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span,
|
||||
});
|
||||
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior));
|
||||
fcx.deferred_generator_interiors.borrow_mut().push((body.id(), interior, gen_kind));
|
||||
Some(GeneratorTypes {
|
||||
yield_ty: fcx.yield_ty.unwrap(),
|
||||
interior,
|
||||
@@ -1788,32 +1788,71 @@ fn check_packed_inner<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, stack: &mut Vec<De
|
||||
false
|
||||
}
|
||||
|
||||
/// Emit an error when encountering more or less than one variant in a transparent enum.
|
||||
fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: &'tcx ty::AdtDef, sp: Span, did: DefId) {
|
||||
let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
|
||||
tcx.hir().span_if_local(variant.def_id).unwrap()
|
||||
}).collect();
|
||||
let msg = format!(
|
||||
"needs exactly one variant, but has {}",
|
||||
adt.variants.len(),
|
||||
);
|
||||
let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg);
|
||||
err.span_label(sp, &msg);
|
||||
if let &[ref start.., ref end] = &variant_spans[..] {
|
||||
for variant_span in start {
|
||||
err.span_label(*variant_span, "");
|
||||
}
|
||||
err.span_label(*end, &format!("too many variants in `{}`", tcx.def_path_str(did)));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Emit an error when encountering more or less than one non-zero-sized field in a transparent
|
||||
/// enum.
|
||||
fn bad_non_zero_sized_fields<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
adt: &'tcx ty::AdtDef,
|
||||
field_count: usize,
|
||||
field_spans: impl Iterator<Item = Span>,
|
||||
sp: Span,
|
||||
) {
|
||||
let msg = format!("needs exactly one non-zero-sized field, but has {}", field_count);
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
sp,
|
||||
E0690,
|
||||
"{}transparent {} {}",
|
||||
if adt.is_enum() { "the variant of a " } else { "" },
|
||||
adt.descr(),
|
||||
msg,
|
||||
);
|
||||
err.span_label(sp, &msg);
|
||||
for sp in field_spans {
|
||||
err.span_label(sp, "this field is non-zero-sized");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
|
||||
let adt = tcx.adt_def(def_id);
|
||||
if !adt.repr.transparent() {
|
||||
return;
|
||||
}
|
||||
let sp = tcx.sess.source_map().def_span(sp);
|
||||
|
||||
if adt.is_enum() {
|
||||
if !tcx.features().transparent_enums {
|
||||
emit_feature_err(&tcx.sess.parse_sess,
|
||||
sym::transparent_enums,
|
||||
sp,
|
||||
GateIssue::Language,
|
||||
"transparent enums are unstable");
|
||||
emit_feature_err(
|
||||
&tcx.sess.parse_sess,
|
||||
sym::transparent_enums,
|
||||
sp,
|
||||
GateIssue::Language,
|
||||
"transparent enums are unstable",
|
||||
);
|
||||
}
|
||||
if adt.variants.len() != 1 {
|
||||
let variant_spans: Vec<_> = adt.variants.iter().map(|variant| {
|
||||
tcx.hir().span_if_local(variant.def_id).unwrap()
|
||||
}).collect();
|
||||
let mut err = struct_span_err!(tcx.sess, sp, E0731,
|
||||
"transparent enum needs exactly one variant, but has {}",
|
||||
adt.variants.len());
|
||||
if !variant_spans.is_empty() {
|
||||
err.span_note(variant_spans, &format!("the following variants exist on `{}`",
|
||||
tcx.def_path_str(def_id)));
|
||||
}
|
||||
err.emit();
|
||||
bad_variant_count(tcx, adt, sp, def_id);
|
||||
if adt.variants.is_empty() {
|
||||
// Don't bother checking the fields. No variants (and thus no fields) exist.
|
||||
return;
|
||||
@@ -1841,28 +1880,24 @@ fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, def_id: DefId) {
|
||||
(span, zst, align1)
|
||||
});
|
||||
|
||||
let non_zst_fields = field_infos.clone().filter(|(_span, zst, _align1)| !*zst);
|
||||
let non_zst_fields = field_infos.clone().filter_map(|(span, zst, _align1)| if !zst {
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
let non_zst_count = non_zst_fields.clone().count();
|
||||
if non_zst_count != 1 {
|
||||
let field_spans: Vec<_> = non_zst_fields.map(|(span, _zst, _align1)| span).collect();
|
||||
|
||||
let mut err = struct_span_err!(tcx.sess, sp, E0690,
|
||||
"{}transparent {} needs exactly one non-zero-sized field, but has {}",
|
||||
if adt.is_enum() { "the variant of a " } else { "" },
|
||||
adt.descr(),
|
||||
non_zst_count);
|
||||
if !field_spans.is_empty() {
|
||||
err.span_note(field_spans,
|
||||
&format!("the following non-zero-sized fields exist on `{}`:",
|
||||
tcx.def_path_str(def_id)));
|
||||
}
|
||||
err.emit();
|
||||
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
|
||||
}
|
||||
for (span, zst, align1) in field_infos {
|
||||
if zst && !align1 {
|
||||
span_err!(tcx.sess, span, E0691,
|
||||
"zero-sized field in transparent {} has alignment larger than 1",
|
||||
adt.descr());
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
span,
|
||||
E0691,
|
||||
"zero-sized field in transparent {} has alignment larger than 1",
|
||||
adt.descr(),
|
||||
).span_label(span, "has alignment larger than 1").emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2598,9 +2633,9 @@ fn check_casts(&self) {
|
||||
|
||||
fn resolve_generator_interiors(&self, def_id: DefId) {
|
||||
let mut generators = self.deferred_generator_interiors.borrow_mut();
|
||||
for (body_id, interior) in generators.drain(..) {
|
||||
for (body_id, interior, kind) in generators.drain(..) {
|
||||
self.select_obligations_where_possible(false);
|
||||
generator_interior::resolve_interior(self, def_id, body_id, interior);
|
||||
generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3922,52 +3957,6 @@ fn could_remove_semicolon(&self, blk: &'tcx hir::Block, expected_ty: Ty<'tcx>) -
|
||||
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
|
||||
}
|
||||
|
||||
// Rewrite `SelfCtor` to `Ctor`
|
||||
pub fn rewrite_self_ctor(
|
||||
&self,
|
||||
res: Res,
|
||||
span: Span,
|
||||
) -> Result<Res, ErrorReported> {
|
||||
let tcx = self.tcx;
|
||||
if let Res::SelfCtor(impl_def_id) = res {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let adt_def = ty.ty_adt_def();
|
||||
|
||||
match adt_def {
|
||||
Some(adt_def) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
let ctor_def_id = variant.ctor_def_id.unwrap();
|
||||
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
|
||||
}
|
||||
_ => {
|
||||
let mut err = tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.help("did you mean to use one of the enum's variants?");
|
||||
},
|
||||
AdtKind::Struct |
|
||||
AdtKind::Union => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use curly brackets",
|
||||
String::from("Self { /* fields */ }"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
Err(ErrorReported)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiates the given path, which must refer to an item with the given
|
||||
// number of type parameters and type.
|
||||
pub fn instantiate_value_path(&self,
|
||||
@@ -3987,12 +3976,8 @@ pub fn instantiate_value_path(&self,
|
||||
|
||||
let tcx = self.tcx;
|
||||
|
||||
let res = match self.rewrite_self_ctor(res, span) {
|
||||
Ok(res) => res,
|
||||
Err(ErrorReported) => return (tcx.types.err, res),
|
||||
};
|
||||
let path_segs = match res {
|
||||
Res::Local(_) => vec![],
|
||||
Res::Local(_) | Res::SelfCtor(_) => vec![],
|
||||
Res::Def(kind, def_id) =>
|
||||
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
|
||||
_ => bug!("instantiate_value_path on {:?}", res),
|
||||
@@ -4097,13 +4082,53 @@ pub fn instantiate_value_path(&self,
|
||||
tcx.generics_of(*def_id).has_self
|
||||
}).unwrap_or(false);
|
||||
|
||||
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
|
||||
let ty = self.impl_self_ty(span, impl_def_id).ty;
|
||||
let adt_def = ty.ty_adt_def();
|
||||
|
||||
match ty.sty {
|
||||
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
|
||||
let variant = adt_def.non_enum_variant();
|
||||
let ctor_def_id = variant.ctor_def_id.unwrap();
|
||||
(
|
||||
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
|
||||
Some(substs),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
let mut err = tcx.sess.struct_span_err(span,
|
||||
"the `Self` constructor can only be used with tuple or unit structs");
|
||||
if let Some(adt_def) = adt_def {
|
||||
match adt_def.adt_kind() {
|
||||
AdtKind::Enum => {
|
||||
err.help("did you mean to use one of the enum's variants?");
|
||||
},
|
||||
AdtKind::Struct |
|
||||
AdtKind::Union => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use curly brackets",
|
||||
String::from("Self { /* fields */ }"),
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
||||
return (tcx.types.err, res)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(res, None)
|
||||
};
|
||||
let def_id = res.def_id();
|
||||
|
||||
// The things we are substituting into the type should not contain
|
||||
// escaping late-bound regions, and nor should the base type scheme.
|
||||
let ty = tcx.type_of(def_id);
|
||||
|
||||
let substs = AstConv::create_substs_for_generic_args(
|
||||
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
|
||||
tcx,
|
||||
def_id,
|
||||
&[][..],
|
||||
@@ -4173,7 +4198,7 @@ pub fn instantiate_value_path(&self,
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
));
|
||||
assert!(!substs.has_escaping_bound_vars());
|
||||
assert!(!ty.has_escaping_bound_vars());
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
use std::iter::once;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::symbol::sym;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@@ -470,18 +470,12 @@ fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemE
|
||||
})
|
||||
}
|
||||
LoadedMacro::ProcMacro(ext) => {
|
||||
let helpers = match &*ext {
|
||||
&SyntaxExtension::Derive(_, ref syms, ..) => { syms.clean(cx) }
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: ext.kind(),
|
||||
helpers,
|
||||
kind: ext.macro_kind(),
|
||||
helpers: ext.helper_attrs.clean(cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// A trait's generics clause actually contains all of the predicates for all of
|
||||
|
||||
@@ -3066,7 +3066,7 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter<'
|
||||
_ => false,
|
||||
};
|
||||
render_impl(w, cx, implementor, AssocItemLink::Anchor(None), RenderMode::Normal,
|
||||
implementor.impl_item.stable_since(), false, Some(use_absolute), false)?;
|
||||
implementor.impl_item.stable_since(), false, Some(use_absolute), false, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3077,7 +3077,7 @@ fn render_impls(cx: &Context, w: &mut fmt::Formatter<'_>,
|
||||
let did = i.trait_did().unwrap();
|
||||
let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
|
||||
render_impl(w, cx, i, assoc_link,
|
||||
RenderMode::Normal, containing_item.stable_since(), true, None, false)?;
|
||||
RenderMode::Normal, containing_item.stable_since(), true, None, false, true)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -3307,7 +3307,7 @@ fn trait_item(w: &mut fmt::Formatter<'_>, cx: &Context, m: &clean::Item, t: &cle
|
||||
);
|
||||
render_impl(w, cx, &implementor, assoc_link,
|
||||
RenderMode::Normal, implementor.impl_item.stable_since(), false,
|
||||
None, true)?;
|
||||
None, true, false)?;
|
||||
}
|
||||
write_loading_content(w, "")?;
|
||||
}
|
||||
@@ -3979,7 +3979,7 @@ fn render_assoc_items(w: &mut fmt::Formatter<'_>,
|
||||
};
|
||||
for i in &non_trait {
|
||||
render_impl(w, cx, i, AssocItemLink::Anchor(None), render_mode,
|
||||
containing_item.stable_since(), true, None, false)?;
|
||||
containing_item.stable_since(), true, None, false, true)?;
|
||||
}
|
||||
}
|
||||
if let AssocItemRender::DerefFor { .. } = what {
|
||||
@@ -4161,7 +4161,8 @@ fn spotlight_decl(decl: &clean::FnDecl) -> Result<String, fmt::Error> {
|
||||
|
||||
fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocItemLink<'_>,
|
||||
render_mode: RenderMode, outer_version: Option<&str>, show_def_docs: bool,
|
||||
use_absolute: Option<bool>, is_on_foreign_type: bool) -> fmt::Result {
|
||||
use_absolute: Option<bool>, is_on_foreign_type: bool,
|
||||
show_default_items: bool) -> fmt::Result {
|
||||
if render_mode == RenderMode::Normal {
|
||||
let id = cx.derive_id(match i.inner_impl().trait_ {
|
||||
Some(ref t) => if is_on_foreign_type {
|
||||
@@ -4345,9 +4346,13 @@ fn render_default_items(w: &mut fmt::Formatter<'_>,
|
||||
|
||||
// If we've implemented a trait, then also emit documentation for all
|
||||
// default items which weren't overridden in the implementation block.
|
||||
if let Some(t) = trait_ {
|
||||
render_default_items(w, cx, t, &i.inner_impl(),
|
||||
render_mode, outer_version, show_def_docs)?;
|
||||
// We don't emit documentation for default items if they appear in the
|
||||
// Implementations on Foreign Types or Implementors sections.
|
||||
if show_default_items {
|
||||
if let Some(t) = trait_ {
|
||||
render_default_items(w, cx, t, &i.inner_impl(),
|
||||
render_mode, outer_version, show_def_docs)?;
|
||||
}
|
||||
}
|
||||
write!(w, "</div>")?;
|
||||
|
||||
|
||||
@@ -423,7 +423,7 @@ fn fold_crate(&mut self, mut c: Crate) -> Crate {
|
||||
|
||||
/// Resolves a string as a macro.
|
||||
fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtensionKind};
|
||||
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| {
|
||||
@@ -433,7 +433,7 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
|
||||
if let Res::Def(DefKind::Macro(MacroKind::ProcMacroStub), _) = res {
|
||||
// skip proc-macro stubs, they'll cause `get_macro` to crash
|
||||
} else {
|
||||
if let SyntaxExtension::LegacyBang { .. } = *resolver.get_macro(res) {
|
||||
if let SyntaxExtensionKind::LegacyBang(..) = resolver.get_macro(res).kind {
|
||||
return Some(res.map_id(|_| panic!("unexpected id")));
|
||||
}
|
||||
}
|
||||
|
||||
+88
-86
@@ -15,6 +15,7 @@
|
||||
use errors::{DiagnosticBuilder, DiagnosticId};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use syntax_pos::{Span, MultiSpan, DUMMY_SP};
|
||||
use syntax_pos::hygiene::{ExpnInfo, ExpnFormat};
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
@@ -548,37 +549,19 @@ pub fn article(self) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum representing the different kinds of syntax extensions.
|
||||
pub enum SyntaxExtension {
|
||||
/// A syntax extension kind.
|
||||
pub enum SyntaxExtensionKind {
|
||||
/// A token-based function-like macro.
|
||||
Bang {
|
||||
Bang(
|
||||
/// An expander with signature TokenStream -> TokenStream.
|
||||
expander: Box<dyn ProcMacro + sync::Sync + sync::Send>,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
edition: Edition,
|
||||
},
|
||||
Box<dyn ProcMacro + sync::Sync + sync::Send>,
|
||||
),
|
||||
|
||||
/// An AST-based function-like macro.
|
||||
LegacyBang {
|
||||
LegacyBang(
|
||||
/// An expander with signature TokenStream -> AST.
|
||||
expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||
/// Some info about the macro's definition point.
|
||||
def_info: Option<(ast::NodeId, Span)>,
|
||||
/// Hygienic properties of identifiers produced by this macro.
|
||||
transparency: Transparency,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||
allow_internal_unsafe: bool,
|
||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||
local_inner_macros: bool,
|
||||
/// The macro's feature name and tracking issue number if it is unstable.
|
||||
unstable_feature: Option<(Symbol, u32)>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
edition: Edition,
|
||||
},
|
||||
Box<dyn TTMacroExpander + sync::Sync + sync::Send>,
|
||||
),
|
||||
|
||||
/// A token-based attribute macro.
|
||||
Attr(
|
||||
@@ -586,8 +569,6 @@ pub enum SyntaxExtension {
|
||||
/// The first TokenSteam is the attribute itself, the second is the annotated item.
|
||||
/// The produced TokenSteam replaces the input TokenSteam.
|
||||
Box<dyn AttrProcMacro + sync::Sync + sync::Send>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
Edition,
|
||||
),
|
||||
|
||||
/// An AST-based attribute macro.
|
||||
@@ -599,7 +580,8 @@ pub enum SyntaxExtension {
|
||||
),
|
||||
|
||||
/// A trivial attribute "macro" that does nothing,
|
||||
/// only keeps the attribute and marks it as known.
|
||||
/// only keeps the attribute and marks it as inert,
|
||||
/// thus making it ineligible for further expansion.
|
||||
NonMacroAttr {
|
||||
/// Suppresses the `unused_attributes` lint for this attribute.
|
||||
mark_used: bool,
|
||||
@@ -610,10 +592,6 @@ pub enum SyntaxExtension {
|
||||
/// An expander with signature TokenStream -> TokenStream (not yet).
|
||||
/// The produced TokenSteam is appended to the input TokenSteam.
|
||||
Box<dyn MultiItemModifier + sync::Sync + sync::Send>,
|
||||
/// Names of helper attributes registered by this macro.
|
||||
Vec<Symbol>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
Edition,
|
||||
),
|
||||
|
||||
/// An AST-based derive macro.
|
||||
@@ -624,42 +602,91 @@ pub enum SyntaxExtension {
|
||||
),
|
||||
}
|
||||
|
||||
/// A struct representing a macro definition in "lowered" form ready for expansion.
|
||||
pub struct SyntaxExtension {
|
||||
/// A syntax extension kind.
|
||||
pub kind: SyntaxExtensionKind,
|
||||
/// Some info about the macro's definition point.
|
||||
pub def_info: Option<(ast::NodeId, Span)>,
|
||||
/// Hygienic properties of spans produced by this macro by default.
|
||||
pub default_transparency: Transparency,
|
||||
/// Whitelist of unstable features that are treated as stable inside this macro.
|
||||
pub allow_internal_unstable: Option<Lrc<[Symbol]>>,
|
||||
/// Suppresses the `unsafe_code` lint for code produced by this macro.
|
||||
pub allow_internal_unsafe: bool,
|
||||
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`) for this macro.
|
||||
pub local_inner_macros: bool,
|
||||
/// The macro's feature name and tracking issue number if it is unstable.
|
||||
pub unstable_feature: Option<(Symbol, u32)>,
|
||||
/// Names of helper attributes registered by this macro.
|
||||
pub helper_attrs: Vec<Symbol>,
|
||||
/// Edition of the crate in which this macro is defined.
|
||||
pub edition: Edition,
|
||||
}
|
||||
|
||||
impl SyntaxExtensionKind {
|
||||
/// When a syntax extension is constructed,
|
||||
/// its transparency can often be inferred from its kind.
|
||||
fn default_transparency(&self) -> Transparency {
|
||||
match self {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::Attr(..) |
|
||||
SyntaxExtensionKind::Derive(..) |
|
||||
SyntaxExtensionKind::NonMacroAttr { .. } => Transparency::Opaque,
|
||||
SyntaxExtensionKind::LegacyBang(..) |
|
||||
SyntaxExtensionKind::LegacyAttr(..) |
|
||||
SyntaxExtensionKind::LegacyDerive(..) => Transparency::SemiTransparent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SyntaxExtension {
|
||||
/// Returns which kind of macro calls this syntax extension.
|
||||
pub fn kind(&self) -> MacroKind {
|
||||
match *self {
|
||||
SyntaxExtension::Bang { .. } |
|
||||
SyntaxExtension::LegacyBang { .. } => MacroKind::Bang,
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => MacroKind::Attr,
|
||||
SyntaxExtension::Derive(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => MacroKind::Derive,
|
||||
pub fn macro_kind(&self) -> MacroKind {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::LegacyBang(..) => MacroKind::Bang,
|
||||
SyntaxExtensionKind::Attr(..) |
|
||||
SyntaxExtensionKind::LegacyAttr(..) |
|
||||
SyntaxExtensionKind::NonMacroAttr { .. } => MacroKind::Attr,
|
||||
SyntaxExtensionKind::Derive(..) |
|
||||
SyntaxExtensionKind::LegacyDerive(..) => MacroKind::Derive,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_transparency(&self) -> Transparency {
|
||||
match *self {
|
||||
SyntaxExtension::LegacyBang { transparency, .. } => transparency,
|
||||
SyntaxExtension::Bang { .. } |
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::Derive(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => Transparency::Opaque,
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => Transparency::SemiTransparent,
|
||||
/// Constructs a syntax extension with default properties.
|
||||
pub fn default(kind: SyntaxExtensionKind, edition: Edition) -> SyntaxExtension {
|
||||
SyntaxExtension {
|
||||
def_info: None,
|
||||
default_transparency: kind.default_transparency(),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
helper_attrs: Vec::new(),
|
||||
edition,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn edition(&self, default_edition: Edition) -> Edition {
|
||||
match *self {
|
||||
SyntaxExtension::Bang { edition, .. } |
|
||||
SyntaxExtension::LegacyBang { edition, .. } |
|
||||
SyntaxExtension::Attr(.., edition) |
|
||||
SyntaxExtension::Derive(.., edition) => edition,
|
||||
// Unstable legacy stuff
|
||||
SyntaxExtension::NonMacroAttr { .. } |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::LegacyDerive(..) => default_edition,
|
||||
fn expn_format(&self, symbol: Symbol) -> ExpnFormat {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..) |
|
||||
SyntaxExtensionKind::LegacyBang(..) => ExpnFormat::MacroBang(symbol),
|
||||
_ => ExpnFormat::MacroAttribute(symbol),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expn_info(&self, call_site: Span, format: &str) -> ExpnInfo {
|
||||
ExpnInfo {
|
||||
call_site,
|
||||
format: self.expn_format(Symbol::intern(format)),
|
||||
def_site: self.def_info.map(|(_, span)| span),
|
||||
default_transparency: self.default_transparency,
|
||||
allow_internal_unstable: self.allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe: self.allow_internal_unsafe,
|
||||
local_inner_macros: self.local_inner_macros,
|
||||
edition: self.edition,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -699,31 +726,6 @@ pub fn determined(determined: bool) -> Determinacy {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DummyResolver;
|
||||
|
||||
impl Resolver for DummyResolver {
|
||||
fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
|
||||
|
||||
fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
|
||||
|
||||
fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {}
|
||||
fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
|
||||
_derives: &[Mark]) {}
|
||||
fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
|
||||
|
||||
fn resolve_imports(&mut self) {}
|
||||
fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool)
|
||||
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
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> {
|
||||
Err(Determinacy::Determined)
|
||||
}
|
||||
fn check_unused_macros(&self) {}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ModuleData {
|
||||
pub mod_path: Vec<ast::Ident>,
|
||||
|
||||
@@ -60,15 +60,10 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P
|
||||
}
|
||||
pretty_name.push(')');
|
||||
|
||||
cx.current_expansion.mark.set_expn_info(ExpnInfo {
|
||||
call_site: span,
|
||||
def_site: None,
|
||||
format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::structural_match].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
});
|
||||
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.with_ctxt(cx.backtrace());
|
||||
item.visit_attrs(|attrs| {
|
||||
|
||||
+35
-145
@@ -1,7 +1,7 @@
|
||||
use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
|
||||
use crate::ast::{MacStmtStyle, StmtKind, ItemKind};
|
||||
use crate::attr::{self, HasAttrs};
|
||||
use crate::source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
|
||||
use crate::source_map::{dummy_spanned, respan};
|
||||
use crate::config::StripUnconfigured;
|
||||
use crate::ext::base::*;
|
||||
use crate::ext::derive::{add_derived_markers, collect_derives};
|
||||
@@ -22,7 +22,6 @@
|
||||
use errors::{Applicability, FatalError};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use syntax_pos::{Span, DUMMY_SP, FileName};
|
||||
use syntax_pos::hygiene::ExpnFormat;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
@@ -189,23 +188,6 @@ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
|
||||
}
|
||||
}
|
||||
|
||||
fn macro_bang_format(path: &ast::Path) -> ExpnFormat {
|
||||
// We don't want to format a path using pretty-printing,
|
||||
// `format!("{}", path)`, because that tries to insert
|
||||
// line-breaks and is slow.
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
MacroBang(Symbol::intern(&path_str))
|
||||
}
|
||||
|
||||
pub struct Invocation {
|
||||
pub kind: InvocationKind,
|
||||
fragment_kind: AstFragmentKind,
|
||||
@@ -388,8 +370,8 @@ fn expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
|
||||
derives.push(mark);
|
||||
let item = match self.cx.resolver.resolve_macro_path(
|
||||
path, MacroKind::Derive, Mark::root(), Vec::new(), false) {
|
||||
Ok(ext) => match *ext {
|
||||
SyntaxExtension::LegacyDerive(..) => item_with_markers.clone(),
|
||||
Ok(ext) => match ext.kind {
|
||||
SyntaxExtensionKind::LegacyDerive(..) => item_with_markers.clone(),
|
||||
_ => item.clone(),
|
||||
},
|
||||
_ => item.clone(),
|
||||
@@ -509,7 +491,7 @@ 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_enabled() {
|
||||
if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else {
|
||||
if let SyntaxExtensionKind::NonMacroAttr { .. } = ext.kind {} else {
|
||||
emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
|
||||
invoc.span(), GateIssue::Language,
|
||||
"macro invocations in `extern {}` blocks are experimental");
|
||||
@@ -548,34 +530,22 @@ fn expand_attr_invoc(&mut self,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let SyntaxExtension::NonMacroAttr { mark_used: false } = *ext {} else {
|
||||
// Macro attrs are always used when expanded,
|
||||
// non-macro attrs are considered used when the field says so.
|
||||
attr::mark_used(&attr);
|
||||
}
|
||||
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern(&attr.path.to_string())),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ext.edition(self.cx.parse_sess.edition),
|
||||
});
|
||||
|
||||
match *ext {
|
||||
SyntaxExtension::NonMacroAttr { .. } => {
|
||||
match &ext.kind {
|
||||
SyntaxExtensionKind::NonMacroAttr { mark_used } => {
|
||||
attr::mark_known(&attr);
|
||||
if *mark_used {
|
||||
attr::mark_used(&attr);
|
||||
}
|
||||
item.visit_attrs(|attrs| attrs.push(attr));
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
|
||||
}
|
||||
SyntaxExtension::LegacyAttr(ref mac) => {
|
||||
SyntaxExtensionKind::LegacyAttr(expander) => {
|
||||
let meta = attr.parse_meta(self.cx.parse_sess)
|
||||
.map_err(|mut e| { e.emit(); }).ok()?;
|
||||
let item = mac.expand(self.cx, attr.span, &meta, item);
|
||||
let item = expander.expand(self.cx, attr.span, &meta, item);
|
||||
Some(invoc.fragment_kind.expect_from_annotatables(item))
|
||||
}
|
||||
SyntaxExtension::Attr(ref mac, ..) => {
|
||||
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),
|
||||
@@ -586,13 +556,13 @@ fn expand_attr_invoc(&mut self,
|
||||
Annotatable::Expr(expr) => token::NtExpr(expr),
|
||||
})), DUMMY_SP).into();
|
||||
let input = self.extract_proc_macro_attr_input(attr.tokens, attr.span);
|
||||
let tok_result = mac.expand(self.cx, attr.span, input, item_tok);
|
||||
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
|
||||
}
|
||||
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||
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)
|
||||
@@ -693,7 +663,7 @@ fn expand_bang_invoc(&mut self,
|
||||
invoc: Invocation,
|
||||
ext: &SyntaxExtension)
|
||||
-> Option<AstFragment> {
|
||||
let (mark, kind) = (invoc.expansion_data.mark, invoc.fragment_kind);
|
||||
let kind = invoc.fragment_kind;
|
||||
let (mac, ident, span) = match invoc.kind {
|
||||
InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
|
||||
_ => unreachable!(),
|
||||
@@ -701,21 +671,13 @@ fn expand_bang_invoc(&mut self,
|
||||
let path = &mac.node.path;
|
||||
|
||||
let ident = ident.unwrap_or_else(|| Ident::invalid());
|
||||
let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture
|
||||
def_site_span: Option<Span>,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
// can't infer this type
|
||||
unstable_feature: Option<(Symbol, u32)>,
|
||||
edition| {
|
||||
|
||||
let validate = |this: &mut Self| {
|
||||
// feature-gate the macro invocation
|
||||
if let Some((feature, issue)) = unstable_feature {
|
||||
if let Some((feature, issue)) = ext.unstable_feature {
|
||||
let crate_span = this.cx.current_expansion.crate_span.unwrap();
|
||||
// don't stability-check macros in the same crate
|
||||
// (the only time this is null is for syntax extensions registered as macros)
|
||||
if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span))
|
||||
if ext.def_info.map_or(false, |(_, def_span)| !crate_span.contains(def_span))
|
||||
&& !span.allows_unstable(feature)
|
||||
&& this.cx.ecfg.features.map_or(true, |feats| {
|
||||
// macro features will count as lib features
|
||||
@@ -734,62 +696,39 @@ fn expand_bang_invoc(&mut self,
|
||||
this.cx.trace_macros_diag();
|
||||
return Err(kind.dummy(span));
|
||||
}
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: span,
|
||||
def_site: def_site_span,
|
||||
format: macro_bang_format(path),
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
edition,
|
||||
});
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let opt_expanded = match *ext {
|
||||
SyntaxExtension::LegacyBang {
|
||||
ref expander,
|
||||
def_info,
|
||||
ref allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
edition,
|
||||
..
|
||||
} => {
|
||||
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
||||
allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
edition) {
|
||||
let opt_expanded = match &ext.kind {
|
||||
SyntaxExtensionKind::LegacyBang(expander) => {
|
||||
if let Err(dummy_span) = validate(self) {
|
||||
dummy_span
|
||||
} else {
|
||||
kind.make_from(expander.expand(
|
||||
self.cx,
|
||||
span,
|
||||
mac.node.stream(),
|
||||
def_info.map(|(_, s)| s),
|
||||
ext.def_info.map(|(_, s)| s),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
SyntaxExtension::Attr(..) |
|
||||
SyntaxExtension::LegacyAttr(..) |
|
||||
SyntaxExtension::NonMacroAttr { .. } => {
|
||||
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)
|
||||
}
|
||||
|
||||
SyntaxExtension::Derive(..) | SyntaxExtension::LegacyDerive(..) => {
|
||||
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
|
||||
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
|
||||
self.cx.trace_macros_diag();
|
||||
kind.dummy(span)
|
||||
}
|
||||
|
||||
SyntaxExtension::Bang { ref expander, ref allow_internal_unstable, edition } => {
|
||||
SyntaxExtensionKind::Bang(expander) => {
|
||||
if ident.name != kw::Invalid {
|
||||
let msg =
|
||||
format!("macro {}! expects no ident argument, given '{}'", path, ident);
|
||||
@@ -798,19 +737,6 @@ fn expand_bang_invoc(&mut self,
|
||||
kind.dummy(span)
|
||||
} else {
|
||||
self.gate_proc_macro_expansion_kind(span, kind);
|
||||
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
|
||||
call_site: span,
|
||||
// FIXME procedural macros do not have proper span info
|
||||
// yet, when they do, we should use it here.
|
||||
def_site: None,
|
||||
format: macro_bang_format(path),
|
||||
// FIXME probably want to follow macro_rules macros here.
|
||||
allow_internal_unstable: allow_internal_unstable.clone(),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition,
|
||||
});
|
||||
|
||||
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);
|
||||
@@ -867,55 +793,19 @@ fn expand_derive_invoc(&mut self,
|
||||
return None;
|
||||
}
|
||||
|
||||
let pretty_name = Symbol::intern(&format!("derive({})", path));
|
||||
let span = path.span;
|
||||
let attr = ast::Attribute {
|
||||
path, span,
|
||||
tokens: TokenStream::empty(),
|
||||
// irrelevant:
|
||||
id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false,
|
||||
};
|
||||
|
||||
let mut expn_info = ExpnInfo {
|
||||
call_site: span,
|
||||
def_site: None,
|
||||
format: MacroAttribute(pretty_name),
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ext.edition(self.cx.parse_sess.edition),
|
||||
};
|
||||
|
||||
match ext {
|
||||
SyntaxExtension::Derive(expander, ..) | SyntaxExtension::LegacyDerive(expander) => {
|
||||
let meta = match ext {
|
||||
SyntaxExtension::Derive(..) => ast::MetaItem { // FIXME(jseyfried) avoid this
|
||||
path: Path::from_ident(Ident::invalid()),
|
||||
span: DUMMY_SP,
|
||||
node: ast::MetaItemKind::Word,
|
||||
},
|
||||
_ => {
|
||||
expn_info.allow_internal_unstable = Some(vec![
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("derive_clone_copy"),
|
||||
Symbol::intern("derive_eq"),
|
||||
// RustcDeserialize and RustcSerialize
|
||||
Symbol::intern("libstd_sys_internals"),
|
||||
].into());
|
||||
attr.meta()?
|
||||
}
|
||||
};
|
||||
|
||||
invoc.expansion_data.mark.set_expn_info(expn_info);
|
||||
let span = span.with_ctxt(self.cx.backtrace());
|
||||
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", attr.path);
|
||||
self.cx.span_err(span, msg);
|
||||
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(span)
|
||||
invoc.fragment_kind.dummy(path.span)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{ast, attr};
|
||||
use crate::edition::Edition;
|
||||
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension, TTMacroExpander};
|
||||
use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
|
||||
use crate::ext::expand::{AstFragment, AstFragmentKind};
|
||||
use crate::ext::hygiene::Transparency;
|
||||
use crate::ext::tt::macro_parser::{Success, Error, Failure};
|
||||
@@ -376,7 +377,7 @@ pub fn compile(
|
||||
valid,
|
||||
});
|
||||
|
||||
let transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
|
||||
let default_transparency = if attr::contains_name(&def.attrs, sym::rustc_transparent_macro) {
|
||||
Transparency::Transparent
|
||||
} else if body.legacy {
|
||||
Transparency::SemiTransparent
|
||||
@@ -426,14 +427,15 @@ pub fn compile(
|
||||
}
|
||||
});
|
||||
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander,
|
||||
SyntaxExtension {
|
||||
kind: SyntaxExtensionKind::LegacyBang(expander),
|
||||
def_info: Some((def.id, def.span)),
|
||||
transparency,
|
||||
default_transparency,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unsafe,
|
||||
local_inner_macros,
|
||||
unstable_feature,
|
||||
helper_attrs: Vec::new(),
|
||||
edition,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,15 +16,9 @@
|
||||
/// 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 {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(Symbol::intern("std_inject")),
|
||||
allow_internal_unstable: Some(vec![sym::prelude_import].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition,
|
||||
});
|
||||
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))
|
||||
}
|
||||
|
||||
|
||||
@@ -280,15 +280,10 @@ fn generate_test_harness(sess: &ParseSess,
|
||||
test_runner
|
||||
};
|
||||
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test_case),
|
||||
allow_internal_unstable: Some(vec![sym::main, sym::test, sym::rustc_attrs].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: sess.edition,
|
||||
});
|
||||
mark.set_expn_info(ExpnInfo::with_unstable(
|
||||
MacroAttribute(sym::test_case), DUMMY_SP, sess.edition,
|
||||
&[sym::main, sym::test, sym::rustc_attrs],
|
||||
));
|
||||
|
||||
TestHarnessGenerator {
|
||||
cx,
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast::{self, MetaItem};
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxExtension, Resolver, MultiItemModifier};
|
||||
use syntax::edition::Edition;
|
||||
use syntax::ext::base::{Annotatable, ExtCtxt, Resolver, MultiItemModifier};
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax_pos::Span;
|
||||
@@ -67,11 +68,25 @@ pub fn is_builtin_trait(name: ast::Name) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_builtin_derives(resolver: &mut dyn Resolver) {
|
||||
pub fn register_builtin_derives(resolver: &mut dyn Resolver, edition: Edition) {
|
||||
let allow_internal_unstable = Some([
|
||||
sym::core_intrinsics,
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("derive_clone_copy"),
|
||||
Symbol::intern("derive_eq"),
|
||||
Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize
|
||||
][..].into());
|
||||
|
||||
$(
|
||||
resolver.add_builtin(
|
||||
ast::Ident::with_empty_ctxt(Symbol::intern($name)),
|
||||
Lrc::new(SyntaxExtension::LegacyDerive(Box::new(BuiltinDerive($func))))
|
||||
Lrc::new(SyntaxExtension {
|
||||
allow_internal_unstable: allow_internal_unstable.clone(),
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($func))),
|
||||
edition,
|
||||
)
|
||||
}),
|
||||
);
|
||||
)*
|
||||
}
|
||||
@@ -148,24 +163,11 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
|
||||
|
||||
/// Constructs an expression that calls an intrinsic
|
||||
fn call_intrinsic(cx: &ExtCtxt<'_>,
|
||||
mut span: Span,
|
||||
span: Span,
|
||||
intrinsic: &str,
|
||||
args: Vec<P<ast::Expr>>)
|
||||
-> P<ast::Expr> {
|
||||
let intrinsic_allowed_via_allow_internal_unstable = cx
|
||||
.current_expansion.mark.expn_info().unwrap()
|
||||
.allow_internal_unstable.map_or(false, |features| features.iter().any(|&s|
|
||||
s == sym::core_intrinsics
|
||||
));
|
||||
if intrinsic_allowed_via_allow_internal_unstable {
|
||||
span = span.with_ctxt(cx.backtrace());
|
||||
} else { // Avoid instability errors with user defined curstom derives, cc #36316
|
||||
let mut info = cx.current_expansion.mark.expn_info().unwrap();
|
||||
info.allow_internal_unstable = Some(vec![sym::core_intrinsics].into());
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
mark.set_expn_info(info);
|
||||
span = span.with_ctxt(SyntaxContext::empty().apply_mark(mark));
|
||||
}
|
||||
let span = span.with_ctxt(cx.backtrace());
|
||||
let path = cx.std_path(&[sym::intrinsics, Symbol::intern(intrinsic)]);
|
||||
let call = cx.expr_call_global(span, path, args);
|
||||
|
||||
|
||||
+31
-39
@@ -43,32 +43,31 @@
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::ast;
|
||||
|
||||
use syntax::ext::base::{MacroExpanderFn, NamedSyntaxExtension, SyntaxExtension};
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::ext::base::MacroExpanderFn;
|
||||
use syntax::ext::base::{NamedSyntaxExtension, SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::edition::Edition;
|
||||
use syntax::symbol::{sym, Symbol};
|
||||
|
||||
pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
|
||||
user_exts: Vec<NamedSyntaxExtension>,
|
||||
edition: Edition) {
|
||||
deriving::register_builtin_derives(resolver);
|
||||
deriving::register_builtin_derives(resolver, edition);
|
||||
|
||||
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(Symbol::intern(stringify!($name)),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new($f as MacroExpanderFn),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
register(Symbol::intern(stringify!($name)), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)), edition
|
||||
));
|
||||
)* }
|
||||
}
|
||||
macro_rules! register_attr {
|
||||
($( $name:ident: $f:expr, )*) => { $(
|
||||
register(Symbol::intern(stringify!($name)), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyAttr(Box::new($f)), edition
|
||||
));
|
||||
)* }
|
||||
}
|
||||
|
||||
@@ -97,33 +96,26 @@ macro_rules! register {
|
||||
assert: assert::expand_assert,
|
||||
}
|
||||
|
||||
register(sym::test_case, SyntaxExtension::LegacyAttr(Box::new(test_case::expand)));
|
||||
register(sym::test, SyntaxExtension::LegacyAttr(Box::new(test::expand_test)));
|
||||
register(sym::bench, SyntaxExtension::LegacyAttr(Box::new(test::expand_bench)));
|
||||
register_attr! {
|
||||
test_case: test_case::expand,
|
||||
test: test::expand_test,
|
||||
bench: test::expand_bench,
|
||||
}
|
||||
|
||||
// format_args uses `unstable` things internally.
|
||||
register(Symbol::intern("format_args"),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(format::expand_format_args),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
register(sym::format_args_nl,
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(format::expand_format_args_nl),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: Some(vec![sym::fmt_internals].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition,
|
||||
});
|
||||
let allow_internal_unstable = Some([sym::fmt_internals][..].into());
|
||||
register(Symbol::intern("format_args"), SyntaxExtension {
|
||||
allow_internal_unstable: allow_internal_unstable.clone(),
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args)), edition
|
||||
)
|
||||
});
|
||||
register(sym::format_args_nl, SyntaxExtension {
|
||||
allow_internal_unstable,
|
||||
..SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(format::expand_format_args_nl)), edition
|
||||
)
|
||||
});
|
||||
|
||||
for (name, ext) in user_exts {
|
||||
register(name, ext);
|
||||
|
||||
@@ -347,18 +347,10 @@ fn mk_decls(
|
||||
custom_macros: &[ProcMacroDef],
|
||||
) -> P<ast::Item> {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::proc_macro),
|
||||
allow_internal_unstable: Some(vec![
|
||||
sym::rustc_attrs,
|
||||
Symbol::intern("proc_macro_internals"),
|
||||
].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
});
|
||||
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.apply_mark(mark);
|
||||
|
||||
let hidden = cx.meta_list_item_word(span, sym::hidden);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use syntax::ast;
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use syntax_pos::Span;
|
||||
use syntax::source_map::{ExpnInfo, MacroAttribute};
|
||||
use std::iter;
|
||||
|
||||
@@ -62,15 +62,10 @@ pub fn expand_test_or_bench(
|
||||
|
||||
let (sp, attr_sp) = {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test),
|
||||
allow_internal_unstable: Some(vec![sym::rustc_attrs, sym::test].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: cx.parse_sess.edition,
|
||||
});
|
||||
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)))
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
use syntax::ast;
|
||||
use syntax::source_map::respan;
|
||||
use syntax::symbol::sym;
|
||||
use syntax_pos::{DUMMY_SP, Span};
|
||||
use syntax_pos::Span;
|
||||
use syntax::source_map::{ExpnInfo, MacroAttribute};
|
||||
use syntax::feature_gate;
|
||||
|
||||
@@ -37,15 +37,10 @@ pub fn expand(
|
||||
|
||||
let sp = {
|
||||
let mark = Mark::fresh(Mark::root());
|
||||
mark.set_expn_info(ExpnInfo {
|
||||
call_site: DUMMY_SP,
|
||||
def_site: None,
|
||||
format: MacroAttribute(sym::test_case),
|
||||
allow_internal_unstable: Some(vec![sym::test, sym::rustc_attrs].into()),
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition: ecx.parse_sess.edition,
|
||||
});
|
||||
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))
|
||||
};
|
||||
|
||||
|
||||
@@ -59,13 +59,12 @@ struct SyntaxContextData {
|
||||
#[derive(Clone, Debug)]
|
||||
struct MarkData {
|
||||
parent: Mark,
|
||||
default_transparency: Transparency,
|
||||
expn_info: Option<ExpnInfo>,
|
||||
}
|
||||
|
||||
/// A property of a macro expansion that determines how identifiers
|
||||
/// produced by that expansion are resolved.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum Transparency {
|
||||
/// Identifier produced by a transparent expansion is always resolved at call-site.
|
||||
/// Call-site spans in procedural macros, hygiene opt-out in `macro` should use this.
|
||||
@@ -85,12 +84,7 @@ pub enum Transparency {
|
||||
impl Mark {
|
||||
pub fn fresh(parent: Mark) -> Self {
|
||||
HygieneData::with(|data| {
|
||||
data.marks.push(MarkData {
|
||||
parent,
|
||||
// By default expansions behave like `macro_rules`.
|
||||
default_transparency: Transparency::SemiTransparent,
|
||||
expn_info: None,
|
||||
});
|
||||
data.marks.push(MarkData { parent, expn_info: None });
|
||||
Mark(data.marks.len() as u32 - 1)
|
||||
})
|
||||
}
|
||||
@@ -118,7 +112,7 @@ pub fn parent(self) -> Mark {
|
||||
|
||||
#[inline]
|
||||
pub fn expn_info(self) -> Option<ExpnInfo> {
|
||||
HygieneData::with(|data| data.expn_info(self))
|
||||
HygieneData::with(|data| data.expn_info(self).cloned())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -126,12 +120,6 @@ pub fn set_expn_info(self, info: ExpnInfo) {
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].expn_info = Some(info))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_default_transparency(self, transparency: Transparency) {
|
||||
assert_ne!(self, Mark::root());
|
||||
HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency)
|
||||
}
|
||||
|
||||
pub fn is_descendant_of(self, ancestor: Mark) -> bool {
|
||||
HygieneData::with(|data| data.is_descendant_of(self, ancestor))
|
||||
}
|
||||
@@ -172,9 +160,8 @@ pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
|
||||
#[inline]
|
||||
pub fn looks_like_proc_macro_derive(self) -> bool {
|
||||
HygieneData::with(|data| {
|
||||
let mark_data = &data.marks[self.0 as usize];
|
||||
if mark_data.default_transparency == Transparency::Opaque {
|
||||
if let Some(expn_info) = &mark_data.expn_info {
|
||||
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;
|
||||
@@ -199,9 +186,6 @@ impl HygieneData {
|
||||
HygieneData {
|
||||
marks: vec![MarkData {
|
||||
parent: Mark::root(),
|
||||
// If the root is opaque, then loops searching for an opaque mark
|
||||
// will automatically stop after reaching it.
|
||||
default_transparency: Transparency::Opaque,
|
||||
expn_info: None,
|
||||
}],
|
||||
syntax_contexts: vec![SyntaxContextData {
|
||||
@@ -220,8 +204,8 @@ fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
|
||||
GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
|
||||
}
|
||||
|
||||
fn expn_info(&self, mark: Mark) -> Option<ExpnInfo> {
|
||||
self.marks[mark.0 as usize].expn_info.clone()
|
||||
fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> {
|
||||
self.marks[mark.0 as usize].expn_info.as_ref()
|
||||
}
|
||||
|
||||
fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
|
||||
@@ -235,7 +219,9 @@ fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
|
||||
}
|
||||
|
||||
fn default_transparency(&self, mark: Mark) -> Transparency {
|
||||
self.marks[mark.0 as usize].default_transparency
|
||||
self.marks[mark.0 as usize].expn_info.as_ref().map_or(
|
||||
Transparency::SemiTransparent, |einfo| einfo.default_transparency
|
||||
)
|
||||
}
|
||||
|
||||
fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext {
|
||||
@@ -427,7 +413,6 @@ pub fn allocate_directly(expansion_info: ExpnInfo) -> Self {
|
||||
HygieneData::with(|data| {
|
||||
data.marks.push(MarkData {
|
||||
parent: Mark::root(),
|
||||
default_transparency: Transparency::SemiTransparent,
|
||||
expn_info: Some(expansion_info),
|
||||
});
|
||||
|
||||
@@ -613,7 +598,7 @@ pub fn outer(self) -> Mark {
|
||||
/// `ctxt.outer().expn_info()`.
|
||||
#[inline]
|
||||
pub fn outer_expn_info(self) -> Option<ExpnInfo> {
|
||||
HygieneData::with(|data| data.expn_info(data.outer(self)))
|
||||
HygieneData::with(|data| data.expn_info(data.outer(self)).cloned())
|
||||
}
|
||||
|
||||
/// `ctxt.outer_and_expn_info()` is equivalent to but faster than
|
||||
@@ -622,7 +607,7 @@ pub fn outer_expn_info(self) -> Option<ExpnInfo> {
|
||||
pub fn outer_and_expn_info(self) -> (Mark, Option<ExpnInfo>) {
|
||||
HygieneData::with(|data| {
|
||||
let outer = data.outer(self);
|
||||
(outer, data.expn_info(outer))
|
||||
(outer, data.expn_info(outer).cloned())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -651,6 +636,7 @@ 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)]
|
||||
pub struct ExpnInfo {
|
||||
// --- The part unique to each expansion.
|
||||
/// The location of the actual macro invocation or syntax sugar , e.g.
|
||||
/// `let x = foo!();` or `if let Some(y) = x {}`
|
||||
///
|
||||
@@ -661,13 +647,18 @@ 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 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.
|
||||
/// This span serves only informational purpose and is not used for resolution.
|
||||
pub def_site: Option<Span>,
|
||||
/// The format with which the macro was invoked.
|
||||
pub format: ExpnFormat,
|
||||
/// 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
|
||||
/// internally without forcing the whole crate to opt-in
|
||||
/// to them.
|
||||
@@ -682,6 +673,30 @@ pub struct ExpnInfo {
|
||||
pub edition: Edition,
|
||||
}
|
||||
|
||||
impl ExpnInfo {
|
||||
/// Constructs an expansion info with default properties.
|
||||
pub fn default(format: ExpnFormat, call_site: Span, edition: Edition) -> ExpnInfo {
|
||||
ExpnInfo {
|
||||
call_site,
|
||||
format,
|
||||
def_site: None,
|
||||
default_transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
edition,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_unstable(format: ExpnFormat, call_site: Span, edition: Edition,
|
||||
allow_internal_unstable: &[Symbol]) -> ExpnInfo {
|
||||
ExpnInfo {
|
||||
allow_internal_unstable: Some(allow_internal_unstable.into()),
|
||||
..ExpnInfo::default(format, call_site, edition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The source of expansion.
|
||||
#[derive(Clone, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||
pub enum ExpnFormat {
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
use std::borrow::ToOwned;
|
||||
use syntax::ast;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::base::{SyntaxExtension, TTMacroExpander, ExtCtxt, MacResult, MacEager};
|
||||
use syntax::ext::hygiene::Transparency;
|
||||
use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager};
|
||||
use syntax::print::pprust;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
@@ -38,15 +38,7 @@ fn expand<'cx>(&self,
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
let args = reg.args().to_owned();
|
||||
reg.register_syntax_extension(Symbol::intern("plugin_args"),
|
||||
SyntaxExtension::LegacyBang {
|
||||
expander: Box::new(Expander { args: args, }),
|
||||
def_info: None,
|
||||
transparency: Transparency::SemiTransparent,
|
||||
allow_internal_unstable: None,
|
||||
allow_internal_unsafe: false,
|
||||
local_inner_macros: false,
|
||||
unstable_feature: None,
|
||||
edition: reg.sess.edition(),
|
||||
});
|
||||
reg.register_syntax_extension(Symbol::intern("plugin_args"), SyntaxExtension::default(
|
||||
SyntaxExtensionKind::LegacyBang(Box::new(Expander { args })), reg.sess.edition()
|
||||
));
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ fn function() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Make 2^12 functions, each containing 16 closures,
|
||||
// resulting in 2^16 closures overall.
|
||||
go_bacterial!(mk_fn 1 1 1 1 1 1 1 1 1 1 1 1);
|
||||
// Make 2^8 functions, each containing 16 closures,
|
||||
// resulting in 2^12 closures overall.
|
||||
go_bacterial!(mk_fn 1 1 1 1 1 1 1 1);
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ async fn bar<T>() -> () {}
|
||||
|
||||
async fn foo() {
|
||||
bar().await;
|
||||
//~^ ERROR type inside generator must be known in this context
|
||||
//~^ ERROR type inside `async` object must be known in this context
|
||||
//~| NOTE cannot infer type for `T`
|
||||
//~| NOTE the type is part of the generator because of this `yield`
|
||||
//~| NOTE the type is part of the `async` object because of this `await`
|
||||
//~| NOTE in this expansion of desugaring of `await`
|
||||
}
|
||||
fn main() {}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
error[E0698]: type inside generator must be known in this context
|
||||
error[E0698]: type inside `async` object must be known in this context
|
||||
--> $DIR/unresolved_type_param.rs:9:5
|
||||
|
|
||||
LL | bar().await;
|
||||
| ^^^ cannot infer type for `T`
|
||||
|
|
||||
note: the type is part of the generator because of this `yield`
|
||||
note: the type is part of the `async` object because of this `await`
|
||||
--> $DIR/unresolved_type_param.rs:9:5
|
||||
|
|
||||
LL | bar().await;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
error[E0658]: transparent enums are unstable
|
||||
--> $DIR/feature-gate-transparent_enums.rs:2:1
|
||||
|
|
||||
LL | / enum OkButUnstableEnum {
|
||||
LL | | Foo((), String, ()),
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | enum OkButUnstableEnum {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/60405
|
||||
= help: add #![feature(transparent_enums)] to the crate attributes to enable
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user