Auto merge of #82896 - Dylan-DPC:rollup-9setmme, r=Dylan-DPC
Rollup of 10 pull requests Successful merges: - #82047 (bypass auto_da_alloc for metadata files) - #82415 (expand: Refactor module loading) - #82557 (Add natvis for Result, NonNull, CString, CStr, and Cow) - #82613 (Remove Item::kind, use tagged enum. Rename variants to match) - #82642 (Fix jemalloc usage on OSX) - #82682 (Implement built-in attribute macro `#[cfg_eval]` + some refactoring) - #82684 (Disable destination propagation on all mir-opt-levels) - #82755 (Refactor confirm_builtin_call, remove partial if) - #82857 (Edit ructc_ast_lowering docs) - #82862 (Generalize Write impl for Vec<u8> to Vec<u8, A>) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
8f349be278
62 changed files with 1375 additions and 868 deletions
|
@ -4568,6 +4568,7 @@ name = "rustdoc-json-types"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -24,6 +24,20 @@ fn main() {
|
||||||
static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc;
|
static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc;
|
||||||
#[used]
|
#[used]
|
||||||
static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free;
|
static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free;
|
||||||
|
|
||||||
|
// On OSX, jemalloc doesn't directly override malloc/free, but instead
|
||||||
|
// registers itself with the allocator's zone APIs in a ctor. However,
|
||||||
|
// the linker doesn't seem to consider ctors as "used" when statically
|
||||||
|
// linking, so we need to explicitly depend on the function.
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
extern "C" {
|
||||||
|
fn _rjem_je_zone_register();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[used]
|
||||||
|
static _F7: unsafe extern "C" fn() = _rjem_je_zone_register;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rustc_driver::set_sigpipe_handler();
|
rustc_driver::set_sigpipe_handler();
|
||||||
|
|
|
@ -915,16 +915,6 @@ impl Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tokens_mut(&mut self) -> Option<&mut LazyTokenStream> {
|
|
||||||
match self.kind {
|
|
||||||
StmtKind::Local(ref mut local) => local.tokens.as_mut(),
|
|
||||||
StmtKind::Item(ref mut item) => item.tokens.as_mut(),
|
|
||||||
StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens.as_mut(),
|
|
||||||
StmtKind::Empty => None,
|
|
||||||
StmtKind::MacCall(ref mut mac) => mac.tokens.as_mut(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_trailing_semicolon(&self) -> bool {
|
pub fn has_trailing_semicolon(&self) -> bool {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
StmtKind::Semi(_) => true,
|
StmtKind::Semi(_) => true,
|
||||||
|
|
|
@ -11,13 +11,7 @@ use super::{AttrVec, Attribute, Stmt, StmtKind};
|
||||||
pub trait AstLike: Sized {
|
pub trait AstLike: Sized {
|
||||||
fn attrs(&self) -> &[Attribute];
|
fn attrs(&self) -> &[Attribute];
|
||||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
|
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
|
||||||
/// Called by `Parser::collect_tokens` to store the collected
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>>;
|
||||||
/// tokens inside an AST node
|
|
||||||
fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {
|
|
||||||
// This default impl makes this trait easier to implement
|
|
||||||
// in tools like `rust-analyzer`
|
|
||||||
panic!("`finalize_tokens` is not supported!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: AstLike + 'static> AstLike for P<T> {
|
impl<T: AstLike + 'static> AstLike for P<T> {
|
||||||
|
@ -27,8 +21,8 @@ impl<T: AstLike + 'static> AstLike for P<T> {
|
||||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||||
(**self).visit_attrs(f);
|
(**self).visit_attrs(f);
|
||||||
}
|
}
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
(**self).finalize_tokens(tokens)
|
(**self).tokens_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,12 +36,12 @@ fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||||
|
|
||||||
impl AstLike for StmtKind {
|
impl AstLike for StmtKind {
|
||||||
fn attrs(&self) -> &[Attribute] {
|
fn attrs(&self) -> &[Attribute] {
|
||||||
match *self {
|
match self {
|
||||||
StmtKind::Local(ref local) => local.attrs(),
|
StmtKind::Local(local) => local.attrs(),
|
||||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(),
|
StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(),
|
||||||
StmtKind::Item(ref item) => item.attrs(),
|
StmtKind::Item(item) => item.attrs(),
|
||||||
StmtKind::Empty => &[],
|
StmtKind::Empty => &[],
|
||||||
StmtKind::MacCall(ref mac) => &*mac.attrs,
|
StmtKind::MacCall(mac) => &mac.attrs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,17 +54,14 @@ impl AstLike for StmtKind {
|
||||||
StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
|
StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
let stmt_tokens = match self {
|
Some(match self {
|
||||||
StmtKind::Local(ref mut local) => &mut local.tokens,
|
StmtKind::Local(local) => &mut local.tokens,
|
||||||
StmtKind::Item(ref mut item) => &mut item.tokens,
|
StmtKind::Item(item) => &mut item.tokens,
|
||||||
StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens,
|
StmtKind::Expr(expr) | StmtKind::Semi(expr) => &mut expr.tokens,
|
||||||
StmtKind::Empty => return,
|
StmtKind::Empty => return None,
|
||||||
StmtKind::MacCall(ref mut mac) => &mut mac.tokens,
|
StmtKind::MacCall(mac) => &mut mac.tokens,
|
||||||
};
|
})
|
||||||
if stmt_tokens.is_none() {
|
|
||||||
*stmt_tokens = Some(tokens);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +73,8 @@ impl AstLike for Stmt {
|
||||||
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
|
||||||
self.kind.visit_attrs(f);
|
self.kind.visit_attrs(f);
|
||||||
}
|
}
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
self.kind.finalize_tokens(tokens)
|
self.kind.tokens_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,17 +83,13 @@ impl AstLike for Attribute {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
match &mut self.kind {
|
Some(match &mut self.kind {
|
||||||
AttrKind::Normal(_, attr_tokens) => {
|
AttrKind::Normal(_, tokens) => tokens,
|
||||||
if attr_tokens.is_none() {
|
kind @ AttrKind::DocComment(..) => {
|
||||||
*attr_tokens = Some(tokens);
|
panic!("Called tokens_mut on doc comment attr {:?}", kind)
|
||||||
}
|
|
||||||
}
|
|
||||||
AttrKind::DocComment(..) => {
|
|
||||||
panic!("Called finalize_tokens on doc comment attr {:?}", self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +102,8 @@ impl<T: AstLike> AstLike for Option<T> {
|
||||||
inner.visit_attrs(f);
|
inner.visit_attrs(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
if let Some(inner) = self {
|
self.as_mut().and_then(|inner| inner.tokens_mut())
|
||||||
inner.finalize_tokens(tokens);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,11 +137,8 @@ macro_rules! derive_has_tokens_and_attrs {
|
||||||
VecOrAttrVec::visit(&mut self.attrs, f)
|
VecOrAttrVec::visit(&mut self.attrs, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
if self.tokens.is_none() {
|
Some(&mut self.tokens)
|
||||||
self.tokens = Some(tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)* }
|
)* }
|
||||||
|
@ -173,7 +155,9 @@ macro_rules! derive_has_attrs_no_tokens {
|
||||||
VecOrAttrVec::visit(&mut self.attrs, f)
|
VecOrAttrVec::visit(&mut self.attrs, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {}
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)* }
|
)* }
|
||||||
}
|
}
|
||||||
|
@ -185,14 +169,10 @@ macro_rules! derive_has_tokens_no_attrs {
|
||||||
&[]
|
&[]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {
|
fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
|
||||||
}
|
|
||||||
|
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
|
||||||
if self.tokens.is_none() {
|
|
||||||
self.tokens = Some(tokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
|
Some(&mut self.tokens)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)* }
|
)* }
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
//! For the simpler lowering steps, IDs and spans should be preserved. Unlike
|
//! For the simpler lowering steps, IDs and spans should be preserved. Unlike
|
||||||
//! expansion we do not preserve the process of lowering in the spans, so spans
|
//! expansion we do not preserve the process of lowering in the spans, so spans
|
||||||
//! should not be modified here. When creating a new node (as opposed to
|
//! should not be modified here. When creating a new node (as opposed to
|
||||||
//! 'folding' an existing one), then you create a new ID using `next_id()`.
|
//! "folding" an existing one), create a new ID using `next_id()`.
|
||||||
//!
|
//!
|
||||||
//! You must ensure that IDs are unique. That means that you should only use the
|
//! You must ensure that IDs are unique. That means that you should only use the
|
||||||
//! ID from an AST node in a single HIR node (you can assume that AST node-IDs
|
//! ID from an AST node in a single HIR node (you can assume that AST node-IDs
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
//! span and spans don't need to be kept in order, etc. Where code is preserved
|
//! span and spans don't need to be kept in order, etc. Where code is preserved
|
||||||
//! by lowering, it should have the same span as in the AST. Where HIR nodes are
|
//! by lowering, it should have the same span as in the AST. Where HIR nodes are
|
||||||
//! new it is probably best to give a span for the whole AST node being lowered.
|
//! new it is probably best to give a span for the whole AST node being lowered.
|
||||||
//! All nodes should have real spans, don't use dummy spans. Tools are likely to
|
//! All nodes should have real spans; don't use dummy spans. Tools are likely to
|
||||||
//! get confused if the spans from leaf AST nodes occur in multiple places
|
//! get confused if the spans from leaf AST nodes occur in multiple places
|
||||||
//! in the HIR, especially for multiple identifiers.
|
//! in the HIR, especially for multiple identifiers.
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||||
/// librustc_middle is independent of the parser, we use dynamic dispatch here.
|
/// librustc_middle is independent of the parser, we use dynamic dispatch here.
|
||||||
nt_to_tokenstream: NtToTokenstream,
|
nt_to_tokenstream: NtToTokenstream,
|
||||||
|
|
||||||
/// Used to allocate HIR nodes
|
/// Used to allocate HIR nodes.
|
||||||
arena: &'hir Arena<'hir>,
|
arena: &'hir Arena<'hir>,
|
||||||
|
|
||||||
/// The items being lowered are collected here.
|
/// The items being lowered are collected here.
|
||||||
|
@ -128,7 +128,7 @@ struct LoweringContext<'a, 'hir: 'a> {
|
||||||
is_in_trait_impl: bool,
|
is_in_trait_impl: bool,
|
||||||
is_in_dyn_type: bool,
|
is_in_dyn_type: bool,
|
||||||
|
|
||||||
/// What to do when we encounter either an "anonymous lifetime
|
/// What to do when we encounter an "anonymous lifetime
|
||||||
/// reference". The term "anonymous" is meant to encompass both
|
/// reference". The term "anonymous" is meant to encompass both
|
||||||
/// `'_` lifetimes as well as fully elided cases where nothing is
|
/// `'_` lifetimes as well as fully elided cases where nothing is
|
||||||
/// written at all (e.g., `&T` or `std::cell::Ref<T>`).
|
/// written at all (e.g., `&T` or `std::cell::Ref<T>`).
|
||||||
|
@ -238,11 +238,13 @@ enum ImplTraitContext<'b, 'a> {
|
||||||
OtherOpaqueTy {
|
OtherOpaqueTy {
|
||||||
/// Set of lifetimes that this opaque type can capture, if it uses
|
/// Set of lifetimes that this opaque type can capture, if it uses
|
||||||
/// them. This includes lifetimes bound since we entered this context.
|
/// them. This includes lifetimes bound since we entered this context.
|
||||||
/// For example, in
|
/// For example:
|
||||||
///
|
///
|
||||||
|
/// ```
|
||||||
/// type A<'b> = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
|
/// type A<'b> = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// the inner opaque type captures `'a` because it uses it. It doesn't
|
/// Here the inner opaque type captures `'a` because it uses it. It doesn't
|
||||||
/// need to capture `'b` because it already inherits the lifetime
|
/// need to capture `'b` because it already inherits the lifetime
|
||||||
/// parameter from `A`.
|
/// parameter from `A`.
|
||||||
// FIXME(impl_trait): but `required_region_bounds` will ICE later
|
// FIXME(impl_trait): but `required_region_bounds` will ICE later
|
||||||
|
@ -2110,7 +2112,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
|
hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms `-> T` into `Future<Output = T>`
|
/// Transforms `-> T` into `Future<Output = T>`.
|
||||||
fn lower_async_fn_output_type_to_future_bound(
|
fn lower_async_fn_output_type_to_future_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
output: &FnRetTy,
|
output: &FnRetTy,
|
||||||
|
|
157
compiler/rustc_builtin_macros/src/cfg_eval.rs
Normal file
157
compiler/rustc_builtin_macros/src/cfg_eval.rs
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
use crate::util::check_builtin_macro_attribute;
|
||||||
|
|
||||||
|
use rustc_ast::mut_visit::{self, MutVisitor};
|
||||||
|
use rustc_ast::ptr::P;
|
||||||
|
use rustc_ast::{self as ast, AstLike};
|
||||||
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
|
use rustc_expand::config::StripUnconfigured;
|
||||||
|
use rustc_expand::configure;
|
||||||
|
use rustc_span::symbol::sym;
|
||||||
|
use rustc_span::Span;
|
||||||
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
|
crate fn expand(
|
||||||
|
ecx: &mut ExtCtxt<'_>,
|
||||||
|
_span: Span,
|
||||||
|
meta_item: &ast::MetaItem,
|
||||||
|
annotatable: Annotatable,
|
||||||
|
) -> Vec<Annotatable> {
|
||||||
|
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
|
||||||
|
cfg_eval(ecx, annotatable)
|
||||||
|
}
|
||||||
|
|
||||||
|
crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
|
||||||
|
let mut visitor = CfgEval {
|
||||||
|
cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false },
|
||||||
|
};
|
||||||
|
let mut annotatable = visitor.configure_annotatable(annotatable);
|
||||||
|
if visitor.cfg.modified {
|
||||||
|
// Erase the tokens if cfg-stripping modified the item
|
||||||
|
// This will cause us to synthesize fake tokens
|
||||||
|
// when `nt_to_tokenstream` is called on this item.
|
||||||
|
if let Some(tokens) = annotatable.tokens_mut() {
|
||||||
|
*tokens = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec![annotatable]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CfgEval<'a> {
|
||||||
|
cfg: StripUnconfigured<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CfgEval<'_> {
|
||||||
|
fn configure<T: AstLike>(&mut self, node: T) -> Option<T> {
|
||||||
|
self.cfg.configure(node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_annotatable(&mut self, annotatable: Annotatable) -> Annotatable {
|
||||||
|
// Since the item itself has already been configured by the InvocationCollector,
|
||||||
|
// we know that fold result vector will contain exactly one element
|
||||||
|
match annotatable {
|
||||||
|
Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
|
||||||
|
Annotatable::TraitItem(item) => {
|
||||||
|
Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::ImplItem(item) => {
|
||||||
|
Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::ForeignItem(item) => {
|
||||||
|
Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::Stmt(stmt) => {
|
||||||
|
Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
|
||||||
|
}
|
||||||
|
Annotatable::Expr(mut expr) => Annotatable::Expr({
|
||||||
|
self.visit_expr(&mut expr);
|
||||||
|
expr
|
||||||
|
}),
|
||||||
|
Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
|
||||||
|
Annotatable::Field(field) => {
|
||||||
|
Annotatable::Field(self.flat_map_field(field).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::FieldPat(fp) => {
|
||||||
|
Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::GenericParam(param) => {
|
||||||
|
Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::Param(param) => {
|
||||||
|
Annotatable::Param(self.flat_map_param(param).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::StructField(sf) => {
|
||||||
|
Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap())
|
||||||
|
}
|
||||||
|
Annotatable::Variant(v) => {
|
||||||
|
Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutVisitor for CfgEval<'_> {
|
||||||
|
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||||
|
self.cfg.configure_expr(expr);
|
||||||
|
mut_visit::noop_visit_expr(expr, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||||
|
let mut expr = configure!(self, expr);
|
||||||
|
mut_visit::noop_visit_expr(&mut expr, self);
|
||||||
|
Some(expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_generic_param(
|
||||||
|
&mut self,
|
||||||
|
param: ast::GenericParam,
|
||||||
|
) -> SmallVec<[ast::GenericParam; 1]> {
|
||||||
|
mut_visit::noop_flat_map_generic_param(configure!(self, param), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
|
||||||
|
mut_visit::noop_flat_map_stmt(configure!(self, stmt), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||||
|
mut_visit::noop_flat_map_item(configure!(self, item), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||||
|
mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
||||||
|
mut_visit::noop_flat_map_assoc_item(configure!(self, item), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_foreign_item(
|
||||||
|
&mut self,
|
||||||
|
foreign_item: P<ast::ForeignItem>,
|
||||||
|
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
||||||
|
mut_visit::noop_flat_map_foreign_item(configure!(self, foreign_item), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
|
||||||
|
mut_visit::noop_flat_map_arm(configure!(self, arm), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
|
||||||
|
mut_visit::noop_flat_map_field(configure!(self, field), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
|
||||||
|
mut_visit::noop_flat_map_field_pattern(configure!(self, fp), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
|
||||||
|
mut_visit::noop_flat_map_param(configure!(self, p), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
|
||||||
|
mut_visit::noop_flat_map_struct_field(configure!(self, sf), self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
|
||||||
|
mut_visit::noop_flat_map_variant(configure!(self, variant), self)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
|
use crate::cfg_eval::cfg_eval;
|
||||||
|
|
||||||
use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
||||||
use rustc_errors::{struct_span_err, Applicability};
|
use rustc_errors::{struct_span_err, Applicability};
|
||||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
||||||
use rustc_expand::config::StripUnconfigured;
|
|
||||||
use rustc_feature::AttributeTemplate;
|
use rustc_feature::AttributeTemplate;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
@ -51,26 +52,7 @@ impl MultiItemModifier for Expander {
|
||||||
|
|
||||||
// FIXME: Try to cache intermediate results to avoid collecting same paths multiple times.
|
// FIXME: Try to cache intermediate results to avoid collecting same paths multiple times.
|
||||||
match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) {
|
match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) {
|
||||||
Ok(()) => {
|
Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
|
||||||
let mut visitor =
|
|
||||||
StripUnconfigured { sess, features: ecx.ecfg.features, modified: false };
|
|
||||||
let mut item = visitor.fully_configure(item);
|
|
||||||
if visitor.modified {
|
|
||||||
// Erase the tokens if cfg-stripping modified the item
|
|
||||||
// This will cause us to synthesize fake tokens
|
|
||||||
// when `nt_to_tokenstream` is called on this item.
|
|
||||||
match &mut item {
|
|
||||||
Annotatable::Item(item) => item,
|
|
||||||
Annotatable::Stmt(stmt) => match &mut stmt.kind {
|
|
||||||
StmtKind::Item(item) => item,
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
.tokens = None;
|
|
||||||
}
|
|
||||||
ExpandResult::Ready(vec![item])
|
|
||||||
}
|
|
||||||
Err(Indeterminate) => ExpandResult::Retry(item),
|
Err(Indeterminate) => ExpandResult::Retry(item),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ mod asm;
|
||||||
mod assert;
|
mod assert;
|
||||||
mod cfg;
|
mod cfg;
|
||||||
mod cfg_accessible;
|
mod cfg_accessible;
|
||||||
|
mod cfg_eval;
|
||||||
mod compile_error;
|
mod compile_error;
|
||||||
mod concat;
|
mod concat;
|
||||||
mod concat_idents;
|
mod concat_idents;
|
||||||
|
@ -89,6 +90,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
|
||||||
register_attr! {
|
register_attr! {
|
||||||
bench: test::expand_bench,
|
bench: test::expand_bench,
|
||||||
cfg_accessible: cfg_accessible::Expander,
|
cfg_accessible: cfg_accessible::Expander,
|
||||||
|
cfg_eval: cfg_eval::expand,
|
||||||
derive: derive::Expander,
|
derive: derive::Expander,
|
||||||
global_allocator: global_allocator::expand,
|
global_allocator: global_allocator::expand,
|
||||||
test: test::expand_test,
|
test: test::expand_test,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_expand::base::{self, *};
|
use rustc_expand::base::{self, *};
|
||||||
use rustc_expand::module::DirectoryOwnership;
|
use rustc_expand::module::DirOwnership;
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::parser::{ForceCollect, Parser};
|
||||||
use rustc_parse::{self, new_parser_from_file};
|
use rustc_parse::{self, new_parser_from_file};
|
||||||
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
|
||||||
|
@ -101,7 +101,7 @@ pub fn expand_include<'cx>(
|
||||||
None => return DummyResult::any(sp),
|
None => return DummyResult::any(sp),
|
||||||
};
|
};
|
||||||
// The file will be added to the code map by the parser
|
// The file will be added to the code map by the parser
|
||||||
let mut file = match cx.resolve_path(file, sp) {
|
let file = match cx.resolve_path(file, sp) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -114,10 +114,9 @@ pub fn expand_include<'cx>(
|
||||||
// then the path of `bar.rs` should be relative to the directory of `file`.
|
// then the path of `bar.rs` should be relative to the directory of `file`.
|
||||||
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
|
// See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion.
|
||||||
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
|
// `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained.
|
||||||
file.pop();
|
let dir_path = file.parent().unwrap_or(&file).to_owned();
|
||||||
cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None };
|
cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path));
|
||||||
let mod_path = cx.current_expansion.module.mod_path.clone();
|
cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None };
|
||||||
cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file });
|
|
||||||
|
|
||||||
struct ExpandResult<'a> {
|
struct ExpandResult<'a> {
|
||||||
p: Parser<'a>,
|
p: Parser<'a>,
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::expand::{self, AstFragment, Invocation};
|
use crate::expand::{self, AstFragment, Invocation};
|
||||||
use crate::module::DirectoryOwnership;
|
use crate::module::DirOwnership;
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, Nonterminal};
|
use rustc_ast::token::{self, Nonterminal};
|
||||||
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream};
|
use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream};
|
||||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||||
use rustc_ast::{self as ast, AstLike, Attribute, NodeId, PatKind};
|
use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
|
||||||
use rustc_attr::{self as attr, Deprecation, Stability};
|
use rustc_attr::{self as attr, Deprecation, Stability};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::sync::{self, Lrc};
|
use rustc_data_structures::sync::{self, Lrc};
|
||||||
|
@ -81,8 +81,22 @@ impl AstLike for Annotatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_tokens(&mut self, tokens: LazyTokenStream) {
|
fn tokens_mut(&mut self) -> Option<&mut Option<LazyTokenStream>> {
|
||||||
panic!("Called finalize_tokens on an Annotatable: {:?}", tokens);
|
match self {
|
||||||
|
Annotatable::Item(item) => item.tokens_mut(),
|
||||||
|
Annotatable::TraitItem(trait_item) => trait_item.tokens_mut(),
|
||||||
|
Annotatable::ImplItem(impl_item) => impl_item.tokens_mut(),
|
||||||
|
Annotatable::ForeignItem(foreign_item) => foreign_item.tokens_mut(),
|
||||||
|
Annotatable::Stmt(stmt) => stmt.tokens_mut(),
|
||||||
|
Annotatable::Expr(expr) => expr.tokens_mut(),
|
||||||
|
Annotatable::Arm(arm) => arm.tokens_mut(),
|
||||||
|
Annotatable::Field(field) => field.tokens_mut(),
|
||||||
|
Annotatable::FieldPat(fp) => fp.tokens_mut(),
|
||||||
|
Annotatable::GenericParam(gp) => gp.tokens_mut(),
|
||||||
|
Annotatable::Param(p) => p.tokens_mut(),
|
||||||
|
Annotatable::StructField(sf) => sf.tokens_mut(),
|
||||||
|
Annotatable::Variant(v) => v.tokens_mut(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,10 +914,26 @@ pub trait ResolverExpand {
|
||||||
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
|
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Default)]
|
||||||
pub struct ModuleData {
|
pub struct ModuleData {
|
||||||
|
/// Path to the module starting from the crate name, like `my_crate::foo::bar`.
|
||||||
pub mod_path: Vec<Ident>,
|
pub mod_path: Vec<Ident>,
|
||||||
pub directory: PathBuf,
|
/// Stack of paths to files loaded by out-of-line module items,
|
||||||
|
/// used to detect and report recursive module inclusions.
|
||||||
|
pub file_path_stack: Vec<PathBuf>,
|
||||||
|
/// Directory to search child module files in,
|
||||||
|
/// often (but not necessarily) the parent of the top file path on the `file_path_stack`.
|
||||||
|
pub dir_path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModuleData {
|
||||||
|
pub fn with_dir_path(&self, dir_path: PathBuf) -> ModuleData {
|
||||||
|
ModuleData {
|
||||||
|
mod_path: self.mod_path.clone(),
|
||||||
|
file_path_stack: self.file_path_stack.clone(),
|
||||||
|
dir_path,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -911,10 +941,13 @@ pub struct ExpansionData {
|
||||||
pub id: ExpnId,
|
pub id: ExpnId,
|
||||||
pub depth: usize,
|
pub depth: usize,
|
||||||
pub module: Rc<ModuleData>,
|
pub module: Rc<ModuleData>,
|
||||||
pub directory_ownership: DirectoryOwnership,
|
pub dir_ownership: DirOwnership,
|
||||||
pub prior_type_ascription: Option<(Span, bool)>,
|
pub prior_type_ascription: Option<(Span, bool)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OnExternModLoaded<'a> =
|
||||||
|
Option<&'a dyn Fn(Ident, Vec<Attribute>, Vec<P<Item>>, Span) -> (Vec<Attribute>, Vec<P<Item>>)>;
|
||||||
|
|
||||||
/// One of these is made during expansion and incrementally updated as we go;
|
/// One of these is made during expansion and incrementally updated as we go;
|
||||||
/// when a macro expansion occurs, the resulting nodes have the `backtrace()
|
/// when a macro expansion occurs, the resulting nodes have the `backtrace()
|
||||||
/// -> expn_data` of their expansion context stored into their span.
|
/// -> expn_data` of their expansion context stored into their span.
|
||||||
|
@ -932,7 +965,7 @@ pub struct ExtCtxt<'a> {
|
||||||
/// Called directly after having parsed an external `mod foo;` in expansion.
|
/// Called directly after having parsed an external `mod foo;` in expansion.
|
||||||
///
|
///
|
||||||
/// `Ident` is the module name.
|
/// `Ident` is the module name.
|
||||||
pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>,
|
pub(super) extern_mod_loaded: OnExternModLoaded<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExtCtxt<'a> {
|
impl<'a> ExtCtxt<'a> {
|
||||||
|
@ -940,7 +973,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
ecfg: expand::ExpansionConfig<'a>,
|
ecfg: expand::ExpansionConfig<'a>,
|
||||||
resolver: &'a mut dyn ResolverExpand,
|
resolver: &'a mut dyn ResolverExpand,
|
||||||
extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>,
|
extern_mod_loaded: OnExternModLoaded<'a>,
|
||||||
) -> ExtCtxt<'a> {
|
) -> ExtCtxt<'a> {
|
||||||
ExtCtxt {
|
ExtCtxt {
|
||||||
sess,
|
sess,
|
||||||
|
@ -952,8 +985,8 @@ impl<'a> ExtCtxt<'a> {
|
||||||
current_expansion: ExpansionData {
|
current_expansion: ExpansionData {
|
||||||
id: ExpnId::root(),
|
id: ExpnId::root(),
|
||||||
depth: 0,
|
depth: 0,
|
||||||
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
|
module: Default::default(),
|
||||||
directory_ownership: DirectoryOwnership::Owned { relative: None },
|
dir_ownership: DirOwnership::Owned { relative: None },
|
||||||
prior_type_ascription: None,
|
prior_type_ascription: None,
|
||||||
},
|
},
|
||||||
force_mode: false,
|
force_mode: false,
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
//! Conditional compilation stripping.
|
//! Conditional compilation stripping.
|
||||||
|
|
||||||
use crate::base::Annotatable;
|
|
||||||
|
|
||||||
use rustc_ast::mut_visit::*;
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{DelimToken, Token, TokenKind};
|
use rustc_ast::token::{DelimToken, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{DelimSpan, LazyTokenStream, Spacing, TokenStream, TokenTree};
|
||||||
|
@ -22,8 +19,6 @@ use rustc_span::edition::{Edition, ALL_EDITIONS};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
|
||||||
|
|
||||||
/// A folder that strips out items that do not belong in the current configuration.
|
/// A folder that strips out items that do not belong in the current configuration.
|
||||||
pub struct StripUnconfigured<'a> {
|
pub struct StripUnconfigured<'a> {
|
||||||
pub sess: &'a Session,
|
pub sess: &'a Session,
|
||||||
|
@ -272,7 +267,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
/// Gives compiler warnings if any `cfg_attr` does not contain any
|
/// Gives compiler warnings if any `cfg_attr` does not contain any
|
||||||
/// attributes and is in the original source code. Gives compiler errors if
|
/// attributes and is in the original source code. Gives compiler errors if
|
||||||
/// the syntax of any `cfg_attr` is incorrect.
|
/// the syntax of any `cfg_attr` is incorrect.
|
||||||
pub fn process_cfg_attrs<T: AstLike>(&mut self, node: &mut T) {
|
fn process_cfg_attrs<T: AstLike>(&mut self, node: &mut T) {
|
||||||
node.visit_attrs(|attrs| {
|
node.visit_attrs(|attrs| {
|
||||||
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
|
attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
|
||||||
});
|
});
|
||||||
|
@ -387,7 +382,7 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if a node with the given attributes should be included in this configuration.
|
/// Determines if a node with the given attributes should be included in this configuration.
|
||||||
pub fn in_cfg(&self, attrs: &[Attribute]) -> bool {
|
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
|
||||||
attrs.iter().all(|attr| {
|
attrs.iter().all(|attr| {
|
||||||
if !is_cfg(self.sess, attr) {
|
if !is_cfg(self.sess, attr) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -427,16 +422,8 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit attributes on expression and statements (but not attributes on items in blocks).
|
|
||||||
fn visit_expr_attrs(&mut self, attrs: &[Attribute]) {
|
|
||||||
// flag the offending attributes
|
|
||||||
for attr in attrs.iter() {
|
|
||||||
self.maybe_emit_expr_attr_err(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If attributes are not allowed on expressions, emit an error for `attr`
|
/// If attributes are not allowed on expressions, emit an error for `attr`
|
||||||
pub fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
crate fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
||||||
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
|
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
|
||||||
let mut err = feature_err(
|
let mut err = feature_err(
|
||||||
&self.sess.parse_sess,
|
&self.sess.parse_sess,
|
||||||
|
@ -453,49 +440,10 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
|
|
||||||
let ast::ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
|
|
||||||
items.flat_map_in_place(|item| self.configure(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
|
|
||||||
match vdata {
|
|
||||||
ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => {
|
|
||||||
fields.flat_map_in_place(|field| self.configure(field))
|
|
||||||
}
|
|
||||||
ast::VariantData::Unit(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) {
|
|
||||||
match item {
|
|
||||||
ast::ItemKind::Struct(def, _generics) | ast::ItemKind::Union(def, _generics) => {
|
|
||||||
self.configure_variant_data(def)
|
|
||||||
}
|
|
||||||
ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => {
|
|
||||||
variants.flat_map_in_place(|variant| self.configure(variant));
|
|
||||||
for variant in variants {
|
|
||||||
self.configure_variant_data(&mut variant.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) {
|
|
||||||
match expr_kind {
|
|
||||||
ast::ExprKind::Match(_m, arms) => {
|
|
||||||
arms.flat_map_in_place(|arm| self.configure(arm));
|
|
||||||
}
|
|
||||||
ast::ExprKind::Struct(_path, fields, _base) => {
|
|
||||||
fields.flat_map_in_place(|field| self.configure(field));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
|
pub fn configure_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||||
self.visit_expr_attrs(expr.attrs());
|
for attr in expr.attrs.iter() {
|
||||||
|
self.maybe_emit_expr_attr_err(attr);
|
||||||
|
}
|
||||||
|
|
||||||
// If an expr is valid to cfg away it will have been removed by the
|
// If an expr is valid to cfg away it will have been removed by the
|
||||||
// outer stmt or expression folder before descending in here.
|
// outer stmt or expression folder before descending in here.
|
||||||
|
@ -511,117 +459,6 @@ impl<'a> StripUnconfigured<'a> {
|
||||||
|
|
||||||
self.process_cfg_attrs(expr)
|
self.process_cfg_attrs(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn configure_pat(&mut self, pat: &mut P<ast::Pat>) {
|
|
||||||
if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind {
|
|
||||||
fields.flat_map_in_place(|field| self.configure(field));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) {
|
|
||||||
fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
|
|
||||||
// Since the item itself has already been configured by the InvocationCollector,
|
|
||||||
// we know that fold result vector will contain exactly one element
|
|
||||||
match item {
|
|
||||||
Annotatable::Item(item) => Annotatable::Item(self.flat_map_item(item).pop().unwrap()),
|
|
||||||
Annotatable::TraitItem(item) => {
|
|
||||||
Annotatable::TraitItem(self.flat_map_trait_item(item).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::ImplItem(item) => {
|
|
||||||
Annotatable::ImplItem(self.flat_map_impl_item(item).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::ForeignItem(item) => {
|
|
||||||
Annotatable::ForeignItem(self.flat_map_foreign_item(item).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::Stmt(stmt) => {
|
|
||||||
Annotatable::Stmt(stmt.map(|stmt| self.flat_map_stmt(stmt).pop().unwrap()))
|
|
||||||
}
|
|
||||||
Annotatable::Expr(mut expr) => Annotatable::Expr({
|
|
||||||
self.visit_expr(&mut expr);
|
|
||||||
expr
|
|
||||||
}),
|
|
||||||
Annotatable::Arm(arm) => Annotatable::Arm(self.flat_map_arm(arm).pop().unwrap()),
|
|
||||||
Annotatable::Field(field) => {
|
|
||||||
Annotatable::Field(self.flat_map_field(field).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::FieldPat(fp) => {
|
|
||||||
Annotatable::FieldPat(self.flat_map_field_pattern(fp).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::GenericParam(param) => {
|
|
||||||
Annotatable::GenericParam(self.flat_map_generic_param(param).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::Param(param) => {
|
|
||||||
Annotatable::Param(self.flat_map_param(param).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::StructField(sf) => {
|
|
||||||
Annotatable::StructField(self.flat_map_struct_field(sf).pop().unwrap())
|
|
||||||
}
|
|
||||||
Annotatable::Variant(v) => {
|
|
||||||
Annotatable::Variant(self.flat_map_variant(v).pop().unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> MutVisitor for StripUnconfigured<'a> {
|
|
||||||
fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
|
|
||||||
self.configure_foreign_mod(foreign_mod);
|
|
||||||
noop_visit_foreign_mod(foreign_mod, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
|
|
||||||
self.configure_item_kind(item);
|
|
||||||
noop_visit_item_kind(item, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
|
||||||
self.configure_expr(expr);
|
|
||||||
self.configure_expr_kind(&mut expr.kind);
|
|
||||||
noop_visit_expr(expr, self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
|
||||||
let mut expr = configure!(self, expr);
|
|
||||||
self.configure_expr_kind(&mut expr.kind);
|
|
||||||
noop_visit_expr(&mut expr, self);
|
|
||||||
Some(expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flat_map_generic_param(
|
|
||||||
&mut self,
|
|
||||||
param: ast::GenericParam,
|
|
||||||
) -> SmallVec<[ast::GenericParam; 1]> {
|
|
||||||
noop_flat_map_generic_param(configure!(self, param), self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
|
|
||||||
noop_flat_map_stmt(configure!(self, stmt), self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
|
||||||
noop_flat_map_item(configure!(self, item), self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
|
||||||
noop_flat_map_assoc_item(configure!(self, item), self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
|
|
||||||
noop_flat_map_assoc_item(configure!(self, item), self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
|
|
||||||
self.configure_pat(pat);
|
|
||||||
noop_visit_pat(pat, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
|
|
||||||
self.configure_fn_decl(&mut fn_decl);
|
|
||||||
noop_visit_fn_decl(fn_decl, self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
|
fn is_cfg(sess: &Session, attr: &Attribute) -> bool {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::config::StripUnconfigured;
|
||||||
use crate::configure;
|
use crate::configure;
|
||||||
use crate::hygiene::SyntaxContext;
|
use crate::hygiene::SyntaxContext;
|
||||||
use crate::mbe::macro_rules::annotate_err_with_kind;
|
use crate::mbe::macro_rules::annotate_err_with_kind;
|
||||||
use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership};
|
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
|
||||||
use crate::placeholders::{placeholder, PlaceholderExpander};
|
use crate::placeholders::{placeholder, PlaceholderExpander};
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
|
@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
// FIXME: Avoid visiting the crate as a `Mod` item,
|
// FIXME: Avoid visiting the crate as a `Mod` item,
|
||||||
// make crate a first class expansion target instead.
|
// make crate a first class expansion target instead.
|
||||||
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
|
pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
|
||||||
let mut module = ModuleData {
|
let file_path = match self.cx.source_map().span_to_unmapped_path(krate.span) {
|
||||||
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
|
|
||||||
directory: match self.cx.source_map().span_to_unmapped_path(krate.span) {
|
|
||||||
FileName::Real(name) => name.into_local_path(),
|
FileName::Real(name) => name.into_local_path(),
|
||||||
other => PathBuf::from(other.to_string()),
|
other => PathBuf::from(other.to_string()),
|
||||||
},
|
|
||||||
};
|
};
|
||||||
module.directory.pop();
|
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
|
||||||
self.cx.root_path = module.directory.clone();
|
self.cx.root_path = dir_path.clone();
|
||||||
self.cx.current_expansion.module = Rc::new(module);
|
self.cx.current_expansion.module = Rc::new(ModuleData {
|
||||||
|
mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
|
||||||
|
file_path_stack: vec![file_path],
|
||||||
|
dir_path,
|
||||||
|
});
|
||||||
|
|
||||||
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
|
let krate_item = AstFragment::Items(smallvec![P(ast::Item {
|
||||||
attrs: krate.attrs,
|
attrs: krate.attrs,
|
||||||
|
@ -1245,10 +1246,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_block(&mut self, block: &mut P<Block>) {
|
fn visit_block(&mut self, block: &mut P<Block>) {
|
||||||
let old_directory_ownership = self.cx.current_expansion.directory_ownership;
|
let orig_dir_ownership = mem::replace(
|
||||||
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
|
&mut self.cx.current_expansion.dir_ownership,
|
||||||
|
DirOwnership::UnownedViaBlock,
|
||||||
|
);
|
||||||
noop_visit_block(block, self);
|
noop_visit_block(block, self);
|
||||||
self.cx.current_expansion.directory_ownership = old_directory_ownership;
|
self.cx.current_expansion.dir_ownership = orig_dir_ownership;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
|
||||||
|
@ -1276,63 +1279,76 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
|
ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => {
|
||||||
let sess = &self.cx.sess.parse_sess;
|
let (file_path, dir_path, dir_ownership) = match mod_kind {
|
||||||
let orig_ownership = self.cx.current_expansion.directory_ownership;
|
ModKind::Loaded(_, inline, _) => {
|
||||||
let mut module = (*self.cx.current_expansion.module).clone();
|
|
||||||
|
|
||||||
let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop.
|
|
||||||
let dir = Directory { ownership: orig_ownership, path: module.directory };
|
|
||||||
let Directory { ownership, path } = match mod_kind {
|
|
||||||
ModKind::Loaded(_, Inline::Yes, _) => {
|
|
||||||
// Inline `mod foo { ... }`, but we still need to push directories.
|
// Inline `mod foo { ... }`, but we still need to push directories.
|
||||||
|
assert!(
|
||||||
|
*inline == Inline::Yes,
|
||||||
|
"`mod` item is loaded from a file for the second time"
|
||||||
|
);
|
||||||
|
let (dir_path, dir_ownership) = mod_dir_path(
|
||||||
|
&self.cx.sess,
|
||||||
|
ident,
|
||||||
|
&attrs,
|
||||||
|
&self.cx.current_expansion.module,
|
||||||
|
self.cx.current_expansion.dir_ownership,
|
||||||
|
);
|
||||||
item.attrs = attrs;
|
item.attrs = attrs;
|
||||||
push_directory(&self.cx.sess, ident, &item.attrs, dir)
|
(None, dir_path, dir_ownership)
|
||||||
}
|
|
||||||
ModKind::Loaded(_, Inline::No, _) => {
|
|
||||||
panic!("`mod` item is loaded from a file for the second time")
|
|
||||||
}
|
}
|
||||||
ModKind::Unloaded => {
|
ModKind::Unloaded => {
|
||||||
// We have an outline `mod foo;` so we need to parse the file.
|
// We have an outline `mod foo;` so we need to parse the file.
|
||||||
let (items, inner_span, dir) =
|
let old_attrs_len = attrs.len();
|
||||||
parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed);
|
let ParsedExternalMod {
|
||||||
|
mut items,
|
||||||
|
inner_span,
|
||||||
|
file_path,
|
||||||
|
dir_path,
|
||||||
|
dir_ownership,
|
||||||
|
} = parse_external_mod(
|
||||||
|
&self.cx.sess,
|
||||||
|
ident,
|
||||||
|
span,
|
||||||
|
&self.cx.current_expansion.module,
|
||||||
|
self.cx.current_expansion.dir_ownership,
|
||||||
|
&mut attrs,
|
||||||
|
);
|
||||||
|
|
||||||
let krate =
|
|
||||||
ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] };
|
|
||||||
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
|
if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded {
|
||||||
extern_mod_loaded(&krate, ident);
|
(attrs, items) = extern_mod_loaded(ident, attrs, items, inner_span);
|
||||||
}
|
}
|
||||||
|
|
||||||
*mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span);
|
*mod_kind = ModKind::Loaded(items, Inline::No, inner_span);
|
||||||
item.attrs = krate.attrs;
|
item.attrs = attrs;
|
||||||
// File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure.
|
if item.attrs.len() > old_attrs_len {
|
||||||
item = match self.configure(item) {
|
// If we loaded an out-of-line module and added some inner attributes,
|
||||||
Some(node) => node,
|
// then we need to re-configure it.
|
||||||
None => {
|
// FIXME: Attributes also need to be recollected
|
||||||
if *pushed {
|
// for resolution and expansion.
|
||||||
sess.included_mod_stack.borrow_mut().pop();
|
item = configure!(self, item);
|
||||||
}
|
}
|
||||||
return Default::default();
|
(Some(file_path), dir_path, dir_ownership)
|
||||||
}
|
|
||||||
};
|
|
||||||
dir
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the module info before we flat map.
|
// Set the module info before we flat map.
|
||||||
self.cx.current_expansion.directory_ownership = ownership;
|
let mut module = self.cx.current_expansion.module.with_dir_path(dir_path);
|
||||||
module.directory = path;
|
|
||||||
module.mod_path.push(ident);
|
module.mod_path.push(ident);
|
||||||
|
if let Some(file_path) = file_path {
|
||||||
|
module.file_path_stack.push(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
let orig_module =
|
let orig_module =
|
||||||
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
|
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
|
||||||
|
let orig_dir_ownership =
|
||||||
|
mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
|
||||||
|
|
||||||
let result = noop_flat_map_item(item, self);
|
let result = noop_flat_map_item(item, self);
|
||||||
|
|
||||||
// Restore the module info.
|
// Restore the module info.
|
||||||
|
self.cx.current_expansion.dir_ownership = orig_dir_ownership;
|
||||||
self.cx.current_expansion.module = orig_module;
|
self.cx.current_expansion.module = orig_module;
|
||||||
self.cx.current_expansion.directory_ownership = orig_ownership;
|
|
||||||
if *pushed {
|
|
||||||
sess.included_mod_stack.borrow_mut().pop();
|
|
||||||
}
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
#![feature(bool_to_option)]
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
|
#![feature(destructuring_assignment)]
|
||||||
#![feature(or_patterns)]
|
#![feature(or_patterns)]
|
||||||
#![feature(proc_macro_diagnostic)]
|
#![feature(proc_macro_diagnostic)]
|
||||||
#![feature(proc_macro_internals)]
|
#![feature(proc_macro_internals)]
|
||||||
|
|
|
@ -1,140 +1,121 @@
|
||||||
|
use crate::base::ModuleData;
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::{token, Attribute, Item};
|
use rustc_ast::{token, Attribute, Item};
|
||||||
use rustc_errors::{struct_span_err, PResult};
|
use rustc_errors::{struct_span_err, DiagnosticBuilder};
|
||||||
use rustc_parse::new_parser_from_file;
|
use rustc_parse::new_parser_from_file;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::source_map::{FileName, Span};
|
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::path::{self, Path, PathBuf};
|
use std::path::{self, Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Directory {
|
|
||||||
pub path: PathBuf,
|
|
||||||
pub ownership: DirectoryOwnership,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum DirectoryOwnership {
|
pub enum DirOwnership {
|
||||||
Owned {
|
Owned {
|
||||||
// None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
|
// None if `mod.rs`, `Some("foo")` if we're in `foo.rs`.
|
||||||
relative: Option<Ident>,
|
relative: Option<Ident>,
|
||||||
},
|
},
|
||||||
UnownedViaBlock,
|
UnownedViaBlock,
|
||||||
UnownedViaMod,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Information about the path to a module.
|
|
||||||
// Public for rustfmt usage.
|
|
||||||
pub struct ModulePath<'a> {
|
|
||||||
name: String,
|
|
||||||
path_exists: bool,
|
|
||||||
pub result: PResult<'a, ModulePathSuccess>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public for rustfmt usage.
|
// Public for rustfmt usage.
|
||||||
pub struct ModulePathSuccess {
|
pub struct ModulePathSuccess {
|
||||||
pub path: PathBuf,
|
pub file_path: PathBuf,
|
||||||
pub ownership: DirectoryOwnership,
|
pub dir_ownership: DirOwnership,
|
||||||
|
}
|
||||||
|
|
||||||
|
crate struct ParsedExternalMod {
|
||||||
|
pub items: Vec<P<Item>>,
|
||||||
|
pub inner_span: Span,
|
||||||
|
pub file_path: PathBuf,
|
||||||
|
pub dir_path: PathBuf,
|
||||||
|
pub dir_ownership: DirOwnership,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ModError<'a> {
|
||||||
|
CircularInclusion(Vec<PathBuf>),
|
||||||
|
ModInBlock(Option<Ident>),
|
||||||
|
FileNotFound(Ident, PathBuf),
|
||||||
|
MultipleCandidates(Ident, String, String),
|
||||||
|
ParserError(DiagnosticBuilder<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn parse_external_mod(
|
crate fn parse_external_mod(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
id: Ident,
|
ident: Ident,
|
||||||
span: Span, // The span to blame on errors.
|
span: Span, // The span to blame on errors.
|
||||||
Directory { mut ownership, path }: Directory,
|
module: &ModuleData,
|
||||||
|
mut dir_ownership: DirOwnership,
|
||||||
attrs: &mut Vec<Attribute>,
|
attrs: &mut Vec<Attribute>,
|
||||||
pop_mod_stack: &mut bool,
|
) -> ParsedExternalMod {
|
||||||
) -> (Vec<P<Item>>, Span, Directory) {
|
|
||||||
// We bail on the first error, but that error does not cause a fatal error... (1)
|
// We bail on the first error, but that error does not cause a fatal error... (1)
|
||||||
let result: PResult<'_, _> = try {
|
let result: Result<_, ModError<'_>> = try {
|
||||||
// Extract the file path and the new ownership.
|
// Extract the file path and the new ownership.
|
||||||
let mp = submod_path(sess, id, span, &attrs, ownership, &path)?;
|
let mp = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)?;
|
||||||
ownership = mp.ownership;
|
dir_ownership = mp.dir_ownership;
|
||||||
|
|
||||||
// Ensure file paths are acyclic.
|
// Ensure file paths are acyclic.
|
||||||
let mut included_mod_stack = sess.parse_sess.included_mod_stack.borrow_mut();
|
if let Some(pos) = module.file_path_stack.iter().position(|p| p == &mp.file_path) {
|
||||||
error_on_circular_module(&sess.parse_sess, span, &mp.path, &included_mod_stack)?;
|
Err(ModError::CircularInclusion(module.file_path_stack[pos..].to_vec()))?;
|
||||||
included_mod_stack.push(mp.path.clone());
|
}
|
||||||
*pop_mod_stack = true; // We have pushed, so notify caller.
|
|
||||||
drop(included_mod_stack);
|
|
||||||
|
|
||||||
// Actually parse the external file as a module.
|
// Actually parse the external file as a module.
|
||||||
let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span));
|
let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span));
|
||||||
let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?;
|
let (mut inner_attrs, items, inner_span) =
|
||||||
|
parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
|
||||||
attrs.append(&mut inner_attrs);
|
attrs.append(&mut inner_attrs);
|
||||||
(items, inner_span)
|
(items, inner_span, mp.file_path)
|
||||||
};
|
};
|
||||||
// (1) ...instead, we return a dummy module.
|
// (1) ...instead, we return a dummy module.
|
||||||
let (items, inner_span) = result.map_err(|mut err| err.emit()).unwrap_or_default();
|
let (items, inner_span, file_path) =
|
||||||
|
result.map_err(|err| err.report(sess, span)).unwrap_or_default();
|
||||||
|
|
||||||
// Extract the directory path for submodules of the module.
|
// Extract the directory path for submodules of the module.
|
||||||
let path = sess.source_map().span_to_unmapped_path(inner_span);
|
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
|
||||||
let mut path = match path {
|
|
||||||
FileName::Real(name) => name.into_local_path(),
|
|
||||||
other => PathBuf::from(other.to_string()),
|
|
||||||
};
|
|
||||||
path.pop();
|
|
||||||
|
|
||||||
(items, inner_span, Directory { ownership, path })
|
ParsedExternalMod { items, inner_span, file_path, dir_path, dir_ownership }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_on_circular_module<'a>(
|
crate fn mod_dir_path(
|
||||||
sess: &'a ParseSess,
|
|
||||||
span: Span,
|
|
||||||
path: &Path,
|
|
||||||
included_mod_stack: &[PathBuf],
|
|
||||||
) -> PResult<'a, ()> {
|
|
||||||
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
|
|
||||||
let mut err = String::from("circular modules: ");
|
|
||||||
for p in &included_mod_stack[i..] {
|
|
||||||
err.push_str(&p.to_string_lossy());
|
|
||||||
err.push_str(" -> ");
|
|
||||||
}
|
|
||||||
err.push_str(&path.to_string_lossy());
|
|
||||||
return Err(sess.span_diagnostic.struct_span_err(span, &err[..]));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn push_directory(
|
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
id: Ident,
|
ident: Ident,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
Directory { mut ownership, mut path }: Directory,
|
module: &ModuleData,
|
||||||
) -> Directory {
|
mut dir_ownership: DirOwnership,
|
||||||
if let Some(filename) = sess.first_attr_value_str_by_name(attrs, sym::path) {
|
) -> (PathBuf, DirOwnership) {
|
||||||
path.push(&*filename.as_str());
|
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) {
|
||||||
ownership = DirectoryOwnership::Owned { relative: None };
|
// For inline modules file path from `#[path]` is actually the directory path
|
||||||
} else {
|
// for historical reasons, so we don't pop the last segment here.
|
||||||
|
return (file_path, DirOwnership::Owned { relative: None });
|
||||||
|
}
|
||||||
|
|
||||||
// We have to push on the current module name in the case of relative
|
// We have to push on the current module name in the case of relative
|
||||||
// paths in order to ensure that any additional module paths from inline
|
// paths in order to ensure that any additional module paths from inline
|
||||||
// `mod x { ... }` come after the relative extension.
|
// `mod x { ... }` come after the relative extension.
|
||||||
//
|
//
|
||||||
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
|
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
|
||||||
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
|
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
|
||||||
if let DirectoryOwnership::Owned { relative } = &mut ownership {
|
let mut dir_path = module.dir_path.clone();
|
||||||
|
if let DirOwnership::Owned { relative } = &mut dir_ownership {
|
||||||
if let Some(ident) = relative.take() {
|
if let Some(ident) = relative.take() {
|
||||||
// Remove the relative offset.
|
// Remove the relative offset.
|
||||||
path.push(&*ident.as_str());
|
dir_path.push(&*ident.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path.push(&*id.as_str());
|
dir_path.push(&*ident.as_str());
|
||||||
}
|
|
||||||
Directory { ownership, path }
|
(dir_path, dir_ownership)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn submod_path<'a>(
|
fn mod_file_path<'a>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
id: Ident,
|
ident: Ident,
|
||||||
span: Span,
|
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
ownership: DirectoryOwnership,
|
|
||||||
dir_path: &Path,
|
dir_path: &Path,
|
||||||
) -> PResult<'a, ModulePathSuccess> {
|
dir_ownership: DirOwnership,
|
||||||
if let Some(path) = submod_path_from_attr(sess, attrs, dir_path) {
|
) -> Result<ModulePathSuccess, ModError<'a>> {
|
||||||
let ownership = match path.file_name().and_then(|s| s.to_str()) {
|
if let Some(file_path) = mod_file_path_from_attr(sess, attrs, dir_path) {
|
||||||
// All `#[path]` files are treated as though they are a `mod.rs` file.
|
// All `#[path]` files are treated as though they are a `mod.rs` file.
|
||||||
// This means that `mod foo;` declarations inside `#[path]`-included
|
// This means that `mod foo;` declarations inside `#[path]`-included
|
||||||
// files are siblings,
|
// files are siblings,
|
||||||
|
@ -142,91 +123,33 @@ fn submod_path<'a>(
|
||||||
// Note that this will produce weirdness when a file named `foo.rs` is
|
// Note that this will produce weirdness when a file named `foo.rs` is
|
||||||
// `#[path]` included and contains a `mod foo;` declaration.
|
// `#[path]` included and contains a `mod foo;` declaration.
|
||||||
// If you encounter this, it's your own darn fault :P
|
// If you encounter this, it's your own darn fault :P
|
||||||
Some(_) => DirectoryOwnership::Owned { relative: None },
|
let dir_ownership = DirOwnership::Owned { relative: None };
|
||||||
_ => DirectoryOwnership::UnownedViaMod,
|
return Ok(ModulePathSuccess { file_path, dir_ownership });
|
||||||
|
}
|
||||||
|
|
||||||
|
let relative = match dir_ownership {
|
||||||
|
DirOwnership::Owned { relative } => relative,
|
||||||
|
DirOwnership::UnownedViaBlock => None,
|
||||||
};
|
};
|
||||||
return Ok(ModulePathSuccess { ownership, path });
|
let result = default_submod_path(&sess.parse_sess, ident, relative, dir_path);
|
||||||
|
match dir_ownership {
|
||||||
|
DirOwnership::Owned { .. } => result,
|
||||||
|
DirOwnership::UnownedViaBlock => Err(ModError::ModInBlock(match result {
|
||||||
|
Ok(_) | Err(ModError::MultipleCandidates(..)) => Some(ident),
|
||||||
|
_ => None,
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
|
|
||||||
let relative = match ownership {
|
|
||||||
DirectoryOwnership::Owned { relative } => relative,
|
|
||||||
DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None,
|
|
||||||
};
|
|
||||||
let ModulePath { path_exists, name, result } =
|
|
||||||
default_submod_path(&sess.parse_sess, id, span, relative, dir_path);
|
|
||||||
match ownership {
|
|
||||||
DirectoryOwnership::Owned { .. } => Ok(result?),
|
|
||||||
DirectoryOwnership::UnownedViaBlock => {
|
|
||||||
let _ = result.map_err(|mut err| err.cancel());
|
|
||||||
error_decl_mod_in_block(&sess.parse_sess, span, path_exists, &name)
|
|
||||||
}
|
|
||||||
DirectoryOwnership::UnownedViaMod => {
|
|
||||||
let _ = result.map_err(|mut err| err.cancel());
|
|
||||||
error_cannot_declare_mod_here(&sess.parse_sess, span, path_exists, &name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_decl_mod_in_block<'a, T>(
|
|
||||||
sess: &'a ParseSess,
|
|
||||||
span: Span,
|
|
||||||
path_exists: bool,
|
|
||||||
name: &str,
|
|
||||||
) -> PResult<'a, T> {
|
|
||||||
let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute";
|
|
||||||
let mut err = sess.span_diagnostic.struct_span_err(span, msg);
|
|
||||||
if path_exists {
|
|
||||||
let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name);
|
|
||||||
err.span_note(span, &msg);
|
|
||||||
}
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn error_cannot_declare_mod_here<'a, T>(
|
|
||||||
sess: &'a ParseSess,
|
|
||||||
span: Span,
|
|
||||||
path_exists: bool,
|
|
||||||
name: &str,
|
|
||||||
) -> PResult<'a, T> {
|
|
||||||
let mut err =
|
|
||||||
sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location");
|
|
||||||
if !span.is_dummy() {
|
|
||||||
if let FileName::Real(src_name) = sess.source_map().span_to_filename(span) {
|
|
||||||
let src_path = src_name.into_local_path();
|
|
||||||
if let Some(stem) = src_path.file_stem() {
|
|
||||||
let mut dest_path = src_path.clone();
|
|
||||||
dest_path.set_file_name(stem);
|
|
||||||
dest_path.push("mod.rs");
|
|
||||||
err.span_note(
|
|
||||||
span,
|
|
||||||
&format!(
|
|
||||||
"maybe move this module `{}` to its own directory via `{}`",
|
|
||||||
src_path.display(),
|
|
||||||
dest_path.display()
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if path_exists {
|
|
||||||
err.span_note(
|
|
||||||
span,
|
|
||||||
&format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Err(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derive a submodule path from the first found `#[path = "path_string"]`.
|
/// Derive a submodule path from the first found `#[path = "path_string"]`.
|
||||||
/// The provided `dir_path` is joined with the `path_string`.
|
/// The provided `dir_path` is joined with the `path_string`.
|
||||||
pub(super) fn submod_path_from_attr(
|
fn mod_file_path_from_attr(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
dir_path: &Path,
|
dir_path: &Path,
|
||||||
) -> Option<PathBuf> {
|
) -> Option<PathBuf> {
|
||||||
// Extract path string from first `#[path = "path_string"]` attribute.
|
// Extract path string from first `#[path = "path_string"]` attribute.
|
||||||
let path_string = sess.first_attr_value_str_by_name(attrs, sym::path)?;
|
let path_string = sess.first_attr_value_str_by_name(attrs, sym::path)?.as_str();
|
||||||
let path_string = path_string.as_str();
|
|
||||||
|
|
||||||
// On windows, the base path might have the form
|
// On windows, the base path might have the form
|
||||||
// `\\?\foo\bar` in which case it does not tolerate
|
// `\\?\foo\bar` in which case it does not tolerate
|
||||||
|
@ -242,15 +165,14 @@ pub(super) fn submod_path_from_attr(
|
||||||
// Public for rustfmt usage.
|
// Public for rustfmt usage.
|
||||||
pub fn default_submod_path<'a>(
|
pub fn default_submod_path<'a>(
|
||||||
sess: &'a ParseSess,
|
sess: &'a ParseSess,
|
||||||
id: Ident,
|
ident: Ident,
|
||||||
span: Span,
|
|
||||||
relative: Option<Ident>,
|
relative: Option<Ident>,
|
||||||
dir_path: &Path,
|
dir_path: &Path,
|
||||||
) -> ModulePath<'a> {
|
) -> Result<ModulePathSuccess, ModError<'a>> {
|
||||||
// If we're in a foo.rs file instead of a mod.rs file,
|
// If we're in a foo.rs file instead of a mod.rs file,
|
||||||
// we need to look for submodules in
|
// we need to look for submodules in
|
||||||
// `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
|
// `./foo/<ident>.rs` and `./foo/<ident>/mod.rs` rather than
|
||||||
// `./<id>.rs` and `./<id>/mod.rs`.
|
// `./<ident>.rs` and `./<ident>/mod.rs`.
|
||||||
let relative_prefix_string;
|
let relative_prefix_string;
|
||||||
let relative_prefix = if let Some(ident) = relative {
|
let relative_prefix = if let Some(ident) = relative {
|
||||||
relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
|
relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR);
|
||||||
|
@ -259,7 +181,7 @@ pub fn default_submod_path<'a>(
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
let mod_name = id.name.to_string();
|
let mod_name = ident.name.to_string();
|
||||||
let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
|
let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
|
||||||
let secondary_path_str =
|
let secondary_path_str =
|
||||||
format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
|
format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR);
|
||||||
|
@ -268,44 +190,74 @@ pub fn default_submod_path<'a>(
|
||||||
let default_exists = sess.source_map().file_exists(&default_path);
|
let default_exists = sess.source_map().file_exists(&default_path);
|
||||||
let secondary_exists = sess.source_map().file_exists(&secondary_path);
|
let secondary_exists = sess.source_map().file_exists(&secondary_path);
|
||||||
|
|
||||||
let result = match (default_exists, secondary_exists) {
|
match (default_exists, secondary_exists) {
|
||||||
(true, false) => Ok(ModulePathSuccess {
|
(true, false) => Ok(ModulePathSuccess {
|
||||||
path: default_path,
|
file_path: default_path,
|
||||||
ownership: DirectoryOwnership::Owned { relative: Some(id) },
|
dir_ownership: DirOwnership::Owned { relative: Some(ident) },
|
||||||
}),
|
}),
|
||||||
(false, true) => Ok(ModulePathSuccess {
|
(false, true) => Ok(ModulePathSuccess {
|
||||||
path: secondary_path,
|
file_path: secondary_path,
|
||||||
ownership: DirectoryOwnership::Owned { relative: None },
|
dir_ownership: DirOwnership::Owned { relative: None },
|
||||||
}),
|
}),
|
||||||
(false, false) => {
|
(false, false) => Err(ModError::FileNotFound(ident, default_path)),
|
||||||
|
(true, true) => {
|
||||||
|
Err(ModError::MultipleCandidates(ident, default_path_str, secondary_path_str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModError<'_> {
|
||||||
|
fn report(self, sess: &Session, span: Span) {
|
||||||
|
let diag = &sess.parse_sess.span_diagnostic;
|
||||||
|
match self {
|
||||||
|
ModError::CircularInclusion(file_paths) => {
|
||||||
|
let mut msg = String::from("circular modules: ");
|
||||||
|
for file_path in &file_paths {
|
||||||
|
msg.push_str(&file_path.display().to_string());
|
||||||
|
msg.push_str(" -> ");
|
||||||
|
}
|
||||||
|
msg.push_str(&file_paths[0].display().to_string());
|
||||||
|
diag.struct_span_err(span, &msg)
|
||||||
|
}
|
||||||
|
ModError::ModInBlock(ident) => {
|
||||||
|
let msg = "cannot declare a non-inline module inside a block unless it has a path attribute";
|
||||||
|
let mut err = diag.struct_span_err(span, msg);
|
||||||
|
if let Some(ident) = ident {
|
||||||
|
let note =
|
||||||
|
format!("maybe `use` the module `{}` instead of redeclaring it", ident);
|
||||||
|
err.span_note(span, ¬e);
|
||||||
|
}
|
||||||
|
err
|
||||||
|
}
|
||||||
|
ModError::FileNotFound(ident, default_path) => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
sess.span_diagnostic,
|
diag,
|
||||||
span,
|
span,
|
||||||
E0583,
|
E0583,
|
||||||
"file not found for module `{}`",
|
"file not found for module `{}`",
|
||||||
mod_name,
|
ident,
|
||||||
);
|
);
|
||||||
err.help(&format!(
|
err.help(&format!(
|
||||||
"to create the module `{}`, create file \"{}\"",
|
"to create the module `{}`, create file \"{}\"",
|
||||||
mod_name,
|
ident,
|
||||||
default_path.display(),
|
default_path.display(),
|
||||||
));
|
));
|
||||||
Err(err)
|
err
|
||||||
}
|
}
|
||||||
(true, true) => {
|
ModError::MultipleCandidates(ident, default_path_short, secondary_path_short) => {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
sess.span_diagnostic,
|
diag,
|
||||||
span,
|
span,
|
||||||
E0761,
|
E0761,
|
||||||
"file for module `{}` found at both {} and {}",
|
"file for module `{}` found at both {} and {}",
|
||||||
mod_name,
|
ident,
|
||||||
default_path_str,
|
default_path_short,
|
||||||
secondary_path_str,
|
secondary_path_short,
|
||||||
);
|
);
|
||||||
err.help("delete or rename one of them to remove the ambiguity");
|
err.help("delete or rename one of them to remove the ambiguity");
|
||||||
Err(err)
|
err
|
||||||
|
}
|
||||||
|
ModError::ParserError(err) => err,
|
||||||
|
}.emit()
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,8 +302,10 @@ fn configure_and_expand_inner<'a>(
|
||||||
..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
|
..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
let extern_mod_loaded = |k: &ast::Crate, ident: Ident| {
|
let extern_mod_loaded = |ident: Ident, attrs, items, span| {
|
||||||
pre_expansion_lint(sess, lint_store, k, &*ident.name.as_str())
|
let krate = ast::Crate { attrs, items, span, proc_macros: vec![] };
|
||||||
|
pre_expansion_lint(sess, lint_store, &krate, &ident.name.as_str());
|
||||||
|
(krate.attrs, krate.items)
|
||||||
};
|
};
|
||||||
let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded));
|
let mut ecx = ExtCtxt::new(&sess, cfg, &mut resolver, Some(&extern_mod_loaded));
|
||||||
|
|
||||||
|
@ -988,7 +990,7 @@ fn encode_and_write_metadata(
|
||||||
.unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
.unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||||
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
|
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
|
||||||
let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
|
let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
|
||||||
if let Err(e) = fs::rename(&metadata_filename, &out_filename) {
|
if let Err(e) = util::non_durable_rename(&metadata_filename, &out_filename) {
|
||||||
tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
||||||
}
|
}
|
||||||
if tcx.sess.opts.json_artifact_notifications {
|
if tcx.sess.opts.json_artifact_notifications {
|
||||||
|
|
|
@ -694,6 +694,24 @@ pub fn build_output_filenames(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))]
|
||||||
|
pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||||
|
std::fs::rename(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function attempts to bypass the auto_da_alloc heuristic implemented by some filesystems
|
||||||
|
/// such as btrfs and ext4. When renaming over a file that already exists then they will "helpfully"
|
||||||
|
/// write back the source file before committing the rename in case a developer forgot some of
|
||||||
|
/// the fsyncs in the open/write/fsync(file)/rename/fsync(dir) dance for atomic file updates.
|
||||||
|
///
|
||||||
|
/// To avoid triggering this heuristic we delete the destination first, if it exists.
|
||||||
|
/// The cost of an extra syscall is much lower than getting descheduled for the sync IO.
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||||
|
let _ = std::fs::remove_file(dst);
|
||||||
|
std::fs::rename(src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
|
// Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere.
|
||||||
//
|
//
|
||||||
// FIXME: Currently the `everybody_loops` transformation is not applied to:
|
// FIXME: Currently the `everybody_loops` transformation is not applied to:
|
||||||
|
|
|
@ -127,6 +127,11 @@ pub struct DestinationPropagation;
|
||||||
|
|
||||||
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
impl<'tcx> MirPass<'tcx> for DestinationPropagation {
|
||||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||||
|
// FIXME(#79191, #82678)
|
||||||
|
if !tcx.sess.opts.debugging_opts.unsound_mir_opts {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Only run at mir-opt-level=3 or higher for now (we don't fix up debuginfo and remove
|
// Only run at mir-opt-level=3 or higher for now (we don't fix up debuginfo and remove
|
||||||
// storage statements at the moment).
|
// storage statements at the moment).
|
||||||
if tcx.sess.mir_opt_level() < 3 {
|
if tcx.sess.mir_opt_level() < 3 {
|
||||||
|
|
|
@ -72,6 +72,10 @@ impl<'a> Parser<'a> {
|
||||||
let cursor_snapshot = self.token_cursor.clone();
|
let cursor_snapshot = self.token_cursor.clone();
|
||||||
|
|
||||||
let (mut ret, trailing_token) = f(self, attrs.attrs)?;
|
let (mut ret, trailing_token) = f(self, attrs.attrs)?;
|
||||||
|
let tokens = match ret.tokens_mut() {
|
||||||
|
Some(tokens) if tokens.is_none() => tokens,
|
||||||
|
_ => return Ok(ret),
|
||||||
|
};
|
||||||
|
|
||||||
// Produces a `TokenStream` on-demand. Using `cursor_snapshot`
|
// Produces a `TokenStream` on-demand. Using `cursor_snapshot`
|
||||||
// and `num_calls`, we can reconstruct the `TokenStream` seen
|
// and `num_calls`, we can reconstruct the `TokenStream` seen
|
||||||
|
@ -128,14 +132,14 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lazy_impl = LazyTokenStreamImpl {
|
*tokens = Some(LazyTokenStream::new(LazyTokenStreamImpl {
|
||||||
start_token,
|
start_token,
|
||||||
num_calls,
|
num_calls,
|
||||||
cursor_snapshot,
|
cursor_snapshot,
|
||||||
desugar_doc_comments: self.desugar_doc_comments,
|
desugar_doc_comments: self.desugar_doc_comments,
|
||||||
append_unglued_token: self.token_cursor.append_unglued_token.clone(),
|
append_unglued_token: self.token_cursor.append_unglued_token.clone(),
|
||||||
};
|
}));
|
||||||
ret.finalize_tokens(LazyTokenStream::new(lazy_impl));
|
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ use rustc_span::hygiene::ExpnId;
|
||||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||||
use rustc_span::{MultiSpan, Span, Symbol};
|
use rustc_span::{MultiSpan, Span, Symbol};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
/// The set of keys (and, optionally, values) that define the compilation
|
/// The set of keys (and, optionally, values) that define the compilation
|
||||||
|
@ -122,8 +121,6 @@ pub struct ParseSess {
|
||||||
pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
|
pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
|
||||||
/// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
|
/// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
|
||||||
pub raw_identifier_spans: Lock<Vec<Span>>,
|
pub raw_identifier_spans: Lock<Vec<Span>>,
|
||||||
/// Used to determine and report recursive module inclusions.
|
|
||||||
pub included_mod_stack: Lock<Vec<PathBuf>>,
|
|
||||||
source_map: Lrc<SourceMap>,
|
source_map: Lrc<SourceMap>,
|
||||||
pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
|
pub buffered_lints: Lock<Vec<BufferedEarlyLint>>,
|
||||||
/// Contains the spans of block expressions that could have been incomplete based on the
|
/// Contains the spans of block expressions that could have been incomplete based on the
|
||||||
|
@ -157,7 +154,6 @@ impl ParseSess {
|
||||||
edition: ExpnId::root().expn_data().edition,
|
edition: ExpnId::root().expn_data().edition,
|
||||||
missing_fragment_specifiers: Default::default(),
|
missing_fragment_specifiers: Default::default(),
|
||||||
raw_identifier_spans: Lock::new(Vec::new()),
|
raw_identifier_spans: Lock::new(Vec::new()),
|
||||||
included_mod_stack: Lock::new(vec![]),
|
|
||||||
source_map,
|
source_map,
|
||||||
buffered_lints: Lock::new(vec![]),
|
buffered_lints: Lock::new(vec![]),
|
||||||
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
ambiguous_block_expr_parse: Lock::new(FxHashMap::default()),
|
||||||
|
|
|
@ -344,6 +344,7 @@ symbols! {
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
cfg_attr_multi,
|
cfg_attr_multi,
|
||||||
cfg_doctest,
|
cfg_doctest,
|
||||||
|
cfg_eval,
|
||||||
cfg_panic,
|
cfg_panic,
|
||||||
cfg_sanitize,
|
cfg_sanitize,
|
||||||
cfg_target_feature,
|
cfg_target_feature,
|
||||||
|
|
|
@ -77,11 +77,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let output = match result {
|
let output = match result {
|
||||||
None => {
|
None => {
|
||||||
// this will report an error since original_callee_ty is not a fn
|
// this will report an error since original_callee_ty is not a fn
|
||||||
self.confirm_builtin_call(call_expr, original_callee_ty, arg_exprs, expected)
|
self.confirm_builtin_call(
|
||||||
|
call_expr,
|
||||||
|
callee_expr,
|
||||||
|
original_callee_ty,
|
||||||
|
arg_exprs,
|
||||||
|
expected,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CallStep::Builtin(callee_ty)) => {
|
Some(CallStep::Builtin(callee_ty)) => {
|
||||||
self.confirm_builtin_call(call_expr, callee_ty, arg_exprs, expected)
|
self.confirm_builtin_call(call_expr, callee_expr, callee_ty, arg_exprs, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CallStep::DeferredClosure(fn_sig)) => {
|
Some(CallStep::DeferredClosure(fn_sig)) => {
|
||||||
|
@ -281,6 +287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
fn confirm_builtin_call(
|
fn confirm_builtin_call(
|
||||||
&self,
|
&self,
|
||||||
call_expr: &'tcx hir::Expr<'tcx>,
|
call_expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
callee_expr: &'tcx hir::Expr<'tcx>,
|
||||||
callee_ty: Ty<'tcx>,
|
callee_ty: Ty<'tcx>,
|
||||||
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
arg_exprs: &'tcx [hir::Expr<'tcx>],
|
||||||
expected: Expectation<'tcx>,
|
expected: Expectation<'tcx>,
|
||||||
|
@ -299,10 +306,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hir::ExprKind::Call(callee, _) = call_expr.kind {
|
|
||||||
let mut err = type_error_struct!(
|
let mut err = type_error_struct!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
callee.span,
|
callee_expr.span,
|
||||||
callee_ty,
|
callee_ty,
|
||||||
E0618,
|
E0618,
|
||||||
"expected function, found {}",
|
"expected function, found {}",
|
||||||
|
@ -315,8 +321,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.identify_bad_closure_def_and_call(
|
self.identify_bad_closure_def_and_call(
|
||||||
&mut err,
|
&mut err,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
&callee.kind,
|
&callee_expr.kind,
|
||||||
callee.span,
|
callee_expr.span,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(ref path) = unit_variant {
|
if let Some(ref path) = unit_variant {
|
||||||
|
@ -333,9 +339,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inner_callee_path = None;
|
let mut inner_callee_path = None;
|
||||||
let def = match callee.kind {
|
let def = match callee_expr.kind {
|
||||||
hir::ExprKind::Path(ref qpath) => {
|
hir::ExprKind::Path(ref qpath) => {
|
||||||
self.typeck_results.borrow().qpath_res(qpath, callee.hir_id)
|
self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
|
||||||
}
|
}
|
||||||
hir::ExprKind::Call(ref inner_callee, _) => {
|
hir::ExprKind::Call(ref inner_callee, _) => {
|
||||||
// If the call spans more than one line and the callee kind is
|
// If the call spans more than one line and the callee kind is
|
||||||
|
@ -345,7 +351,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.tcx.sess.source_map().is_multiline(call_expr.span);
|
self.tcx.sess.source_map().is_multiline(call_expr.span);
|
||||||
if call_is_multiline {
|
if call_is_multiline {
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
callee.span.shrink_to_hi(),
|
callee_expr.span.shrink_to_hi(),
|
||||||
"consider using a semicolon here",
|
"consider using a semicolon here",
|
||||||
";".to_owned(),
|
";".to_owned(),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
|
@ -353,9 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
|
if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
|
||||||
inner_callee_path = Some(inner_qpath);
|
inner_callee_path = Some(inner_qpath);
|
||||||
self.typeck_results
|
self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
|
||||||
.borrow()
|
|
||||||
.qpath_res(inner_qpath, inner_callee.hir_id)
|
|
||||||
} else {
|
} else {
|
||||||
Res::Err
|
Res::Err
|
||||||
}
|
}
|
||||||
|
@ -369,11 +373,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let callee_ty = callee_ty.to_string();
|
let callee_ty = callee_ty.to_string();
|
||||||
let label = match (unit_variant, inner_callee_path) {
|
let label = match (unit_variant, inner_callee_path) {
|
||||||
(Some(path), _) => Some(format!("`{}` defined here", path)),
|
(Some(path), _) => Some(format!("`{}` defined here", path)),
|
||||||
(_, Some(hir::QPath::Resolved(_, path))) => {
|
(_, Some(hir::QPath::Resolved(_, path))) => self
|
||||||
self.tcx.sess.source_map().span_to_snippet(path.span).ok().map(
|
.tcx
|
||||||
|p| format!("`{}` defined here returns `{}`", p, callee_ty),
|
.sess
|
||||||
)
|
.source_map()
|
||||||
}
|
.span_to_snippet(path.span)
|
||||||
|
.ok()
|
||||||
|
.map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)),
|
||||||
_ => {
|
_ => {
|
||||||
match def {
|
match def {
|
||||||
// Emit a different diagnostic for local variables, as they are not
|
// Emit a different diagnostic for local variables, as they are not
|
||||||
|
@ -383,9 +389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.tcx.hir().name(hir_id),
|
self.tcx.hir().name(hir_id),
|
||||||
callee_ty
|
callee_ty
|
||||||
)),
|
)),
|
||||||
Res::Def(kind, def_id)
|
Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
|
||||||
if kind.ns() == Some(Namespace::ValueNS) =>
|
|
||||||
{
|
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"`{}` defined here",
|
"`{}` defined here",
|
||||||
self.tcx.def_path_str(def_id),
|
self.tcx.def_path_str(def_id),
|
||||||
|
@ -400,9 +404,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
} else {
|
|
||||||
bug!("call_expr.kind should be an ExprKind::Call, got {:?}", call_expr.kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the "default" function signature, used in case of error.
|
// This is the "default" function signature, used in case of error.
|
||||||
// In that case, we check each argument against "error" in order to
|
// In that case, we check each argument against "error" in order to
|
||||||
|
|
|
@ -1452,6 +1452,18 @@ pub(crate) mod builtin {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expands all `#[cfg]` and `#[cfg_attr]` attributes in the code fragment it's applied to.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
pub macro cfg_eval($($tt:tt)*) {
|
||||||
|
/* compiler built-in */
|
||||||
|
}
|
||||||
|
|
||||||
/// Unstable implementation detail of the `rustc` compiler, do not use.
|
/// Unstable implementation detail of the `rustc` compiler, do not use.
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
|
@ -81,3 +81,12 @@ pub use crate::macros::builtin::derive;
|
||||||
)]
|
)]
|
||||||
#[doc(no_inline)]
|
#[doc(no_inline)]
|
||||||
pub use crate::macros::builtin::cfg_accessible;
|
pub use crate::macros::builtin::cfg_accessible;
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[doc(no_inline)]
|
||||||
|
pub use crate::macros::builtin::cfg_eval;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
use crate::alloc::Allocator;
|
||||||
use crate::cmp;
|
use crate::cmp;
|
||||||
use crate::fmt;
|
use crate::fmt;
|
||||||
use crate::io::{
|
use crate::io::{
|
||||||
|
@ -357,7 +358,7 @@ impl Write for &mut [u8] {
|
||||||
/// Write is implemented for `Vec<u8>` by appending to the vector.
|
/// Write is implemented for `Vec<u8>` by appending to the vector.
|
||||||
/// The vector will grow as needed.
|
/// The vector will grow as needed.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Write for Vec<u8> {
|
impl<A: Allocator> Write for Vec<u8, A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
self.extend_from_slice(buf);
|
self.extend_from_slice(buf);
|
||||||
|
|
|
@ -234,6 +234,7 @@
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
#![feature(cfg_accessible)]
|
#![feature(cfg_accessible)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(cfg_eval))]
|
||||||
#![feature(cfg_target_has_atomic)]
|
#![feature(cfg_target_has_atomic)]
|
||||||
#![feature(cfg_target_thread_local)]
|
#![feature(cfg_target_thread_local)]
|
||||||
#![feature(char_error_internals)]
|
#![feature(char_error_internals)]
|
||||||
|
|
|
@ -67,6 +67,15 @@ pub use core::prelude::v1::derive;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use core::prelude::v1::cfg_accessible;
|
pub use core::prelude::v1::cfg_accessible;
|
||||||
|
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
#[unstable(
|
||||||
|
feature = "cfg_eval",
|
||||||
|
issue = "82679",
|
||||||
|
reason = "`cfg_eval` is a recently implemented feature"
|
||||||
|
)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use core::prelude::v1::cfg_eval;
|
||||||
|
|
||||||
// The file so far is equivalent to src/libcore/prelude/v1.rs,
|
// The file so far is equivalent to src/libcore/prelude/v1.rs,
|
||||||
// and below to src/liballoc/prelude.rs.
|
// and below to src/liballoc/prelude.rs.
|
||||||
// Those files are duplicated rather than using glob imports
|
// Those files are duplicated rather than using glob imports
|
||||||
|
|
|
@ -397,6 +397,7 @@ impl<'a> Builder<'a> {
|
||||||
test::Crate,
|
test::Crate,
|
||||||
test::CrateLibrustc,
|
test::CrateLibrustc,
|
||||||
test::CrateRustdoc,
|
test::CrateRustdoc,
|
||||||
|
test::CrateRustdocJsonTypes,
|
||||||
test::Linkcheck,
|
test::Linkcheck,
|
||||||
test::TierCheck,
|
test::TierCheck,
|
||||||
test::Cargotest,
|
test::Cargotest,
|
||||||
|
|
|
@ -1922,6 +1922,77 @@ impl Step for CrateRustdoc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct CrateRustdocJsonTypes {
|
||||||
|
host: TargetSelection,
|
||||||
|
test_kind: TestKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Step for CrateRustdocJsonTypes {
|
||||||
|
type Output = ();
|
||||||
|
const DEFAULT: bool = true;
|
||||||
|
const ONLY_HOSTS: bool = true;
|
||||||
|
|
||||||
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
|
run.path("src/rustdoc-json-types")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_run(run: RunConfig<'_>) {
|
||||||
|
let builder = run.builder;
|
||||||
|
|
||||||
|
let test_kind = builder.kind.into();
|
||||||
|
|
||||||
|
builder.ensure(CrateRustdocJsonTypes { host: run.target, test_kind });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(self, builder: &Builder<'_>) {
|
||||||
|
let test_kind = self.test_kind;
|
||||||
|
let target = self.host;
|
||||||
|
|
||||||
|
// Use the previous stage compiler to reuse the artifacts that are
|
||||||
|
// created when running compiletest for src/test/rustdoc. If this used
|
||||||
|
// `compiler`, then it would cause rustdoc to be built *again*, which
|
||||||
|
// isn't really necessary.
|
||||||
|
let compiler = builder.compiler_for(builder.top_stage, target, target);
|
||||||
|
builder.ensure(compile::Rustc { compiler, target });
|
||||||
|
|
||||||
|
let mut cargo = tool::prepare_tool_cargo(
|
||||||
|
builder,
|
||||||
|
compiler,
|
||||||
|
Mode::ToolRustc,
|
||||||
|
target,
|
||||||
|
test_kind.subcommand(),
|
||||||
|
"src/rustdoc-json-types",
|
||||||
|
SourceType::InTree,
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
if test_kind.subcommand() == "test" && !builder.fail_fast {
|
||||||
|
cargo.arg("--no-fail-fast");
|
||||||
|
}
|
||||||
|
|
||||||
|
cargo.arg("-p").arg("rustdoc-json-types");
|
||||||
|
|
||||||
|
cargo.arg("--");
|
||||||
|
cargo.args(&builder.config.cmd.test_args());
|
||||||
|
|
||||||
|
if self.host.contains("musl") {
|
||||||
|
cargo.arg("'-Ctarget-feature=-crt-static'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if !builder.config.verbose_tests {
|
||||||
|
cargo.arg("--quiet");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.info(&format!(
|
||||||
|
"{} rustdoc-json-types stage{} ({} -> {})",
|
||||||
|
test_kind, compiler.stage, &compiler.host, target
|
||||||
|
));
|
||||||
|
let _time = util::timeit(&builder);
|
||||||
|
|
||||||
|
try_run(builder, &mut cargo.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Some test suites are run inside emulators or on remote devices, and most
|
/// Some test suites are run inside emulators or on remote devices, and most
|
||||||
/// of our test binaries are linked dynamically which means we need to ship
|
/// of our test binaries are linked dynamically which means we need to ship
|
||||||
/// the standard library and such to the emulator ahead of time. This step
|
/// the standard library and such to the emulator ahead of time. This step
|
||||||
|
|
|
@ -75,4 +75,11 @@
|
||||||
<ExpandedItem>ptr.pointer->data</ExpandedItem>
|
<ExpandedItem>ptr.pointer->data</ExpandedItem>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
<Type Name="alloc::borrow::Cow<*>">
|
||||||
|
<DisplayString Condition="RUST$ENUM$DISR == 0x0">Borrowed({__0})</DisplayString>
|
||||||
|
<DisplayString Condition="RUST$ENUM$DISR == 0x1">Owned({__0})</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Name="[value]" ExcludeView="simple">__0</Item>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
||||||
|
|
|
@ -30,4 +30,19 @@
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="core::result::Result<*>">
|
||||||
|
<DisplayString Condition="RUST$ENUM$DISR == 0x0">Ok({__0})</DisplayString>
|
||||||
|
<DisplayString Condition="RUST$ENUM$DISR == 0x1">Err({(*($T2*) &__0)})</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Name="[value]" Condition="RUST$ENUM$DISR == 0x0">__0</Item>
|
||||||
|
<Item Name="[value]" Condition="RUST$ENUM$DISR == 0x1">(*($T2*) &__0)</Item>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="core::ptr::non_null::NonNull<*>">
|
||||||
|
<DisplayString>{(void*) pointer}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Name="[value]">*pointer</Item>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
|
@ -72,4 +72,33 @@
|
||||||
</CustomListItems>
|
</CustomListItems>
|
||||||
</Expand>
|
</Expand>
|
||||||
</Type>
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="std::ffi::c_str::CString">
|
||||||
|
<DisplayString>{inner.data_ptr,s}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Synthetic Name="[chars]">
|
||||||
|
<Expand>
|
||||||
|
<ArrayItems>
|
||||||
|
<Size>inner.length</Size>
|
||||||
|
<ValuePointer>(char*)inner.data_ptr</ValuePointer>
|
||||||
|
</ArrayItems>
|
||||||
|
</Expand>
|
||||||
|
</Synthetic>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="std::ffi::c_str::CStr">
|
||||||
|
<DisplayString>{(char*) inner}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Synthetic Name="[chars]">
|
||||||
|
<DisplayString>{(char*) inner}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<ArrayItems>
|
||||||
|
<Size>strlen((char *) inner) + 1</Size>
|
||||||
|
<ValuePointer>(char*)inner</ValuePointer>
|
||||||
|
</ArrayItems>
|
||||||
|
</Expand>
|
||||||
|
</Synthetic>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
</AutoVisualizer>
|
</AutoVisualizer>
|
||||||
|
|
|
@ -23,7 +23,6 @@ use std::collections::HashSet;
|
||||||
|
|
||||||
impl JsonRenderer<'_> {
|
impl JsonRenderer<'_> {
|
||||||
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
|
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
|
||||||
let item_type = ItemType::from(&item);
|
|
||||||
let deprecation = item.deprecation(self.tcx);
|
let deprecation = item.deprecation(self.tcx);
|
||||||
let clean::Item { source, name, attrs, kind, visibility, def_id } = item;
|
let clean::Item { source, name, attrs, kind, visibility, def_id } = item;
|
||||||
let inner = match *kind {
|
let inner = match *kind {
|
||||||
|
@ -50,7 +49,6 @@ impl JsonRenderer<'_> {
|
||||||
.map(rustc_ast_pretty::pprust::attribute_to_string)
|
.map(rustc_ast_pretty::pprust::attribute_to_string)
|
||||||
.collect(),
|
.collect(),
|
||||||
deprecation: deprecation.map(from_deprecation),
|
deprecation: deprecation.map(from_deprecation),
|
||||||
kind: item_type.into(),
|
|
||||||
inner,
|
inner,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -154,30 +152,30 @@ crate fn from_def_id(did: DefId) -> Id {
|
||||||
fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum {
|
fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Symbol>) -> ItemEnum {
|
||||||
use clean::ItemKind::*;
|
use clean::ItemKind::*;
|
||||||
match item {
|
match item {
|
||||||
ModuleItem(m) => ItemEnum::ModuleItem(m.into()),
|
ModuleItem(m) => ItemEnum::Module(m.into()),
|
||||||
ImportItem(i) => ItemEnum::ImportItem(i.into()),
|
ImportItem(i) => ItemEnum::Import(i.into()),
|
||||||
StructItem(s) => ItemEnum::StructItem(s.into()),
|
StructItem(s) => ItemEnum::Struct(s.into()),
|
||||||
UnionItem(u) => ItemEnum::UnionItem(u.into()),
|
UnionItem(u) => ItemEnum::Union(u.into()),
|
||||||
StructFieldItem(f) => ItemEnum::StructFieldItem(f.into()),
|
StructFieldItem(f) => ItemEnum::StructField(f.into()),
|
||||||
EnumItem(e) => ItemEnum::EnumItem(e.into()),
|
EnumItem(e) => ItemEnum::Enum(e.into()),
|
||||||
VariantItem(v) => ItemEnum::VariantItem(v.into()),
|
VariantItem(v) => ItemEnum::Variant(v.into()),
|
||||||
FunctionItem(f) => ItemEnum::FunctionItem(f.into()),
|
FunctionItem(f) => ItemEnum::Function(f.into()),
|
||||||
ForeignFunctionItem(f) => ItemEnum::FunctionItem(f.into()),
|
ForeignFunctionItem(f) => ItemEnum::Function(f.into()),
|
||||||
TraitItem(t) => ItemEnum::TraitItem(t.into()),
|
TraitItem(t) => ItemEnum::Trait(t.into()),
|
||||||
TraitAliasItem(t) => ItemEnum::TraitAliasItem(t.into()),
|
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into()),
|
||||||
MethodItem(m, _) => ItemEnum::MethodItem(from_function_method(m, true)),
|
MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true)),
|
||||||
TyMethodItem(m) => ItemEnum::MethodItem(from_function_method(m, false)),
|
TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false)),
|
||||||
ImplItem(i) => ItemEnum::ImplItem(i.into()),
|
ImplItem(i) => ItemEnum::Impl(i.into()),
|
||||||
StaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)),
|
StaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
|
||||||
ForeignStaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)),
|
ForeignStaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)),
|
||||||
ForeignTypeItem => ItemEnum::ForeignTypeItem,
|
ForeignTypeItem => ItemEnum::ForeignType,
|
||||||
TypedefItem(t, _) => ItemEnum::TypedefItem(t.into()),
|
TypedefItem(t, _) => ItemEnum::Typedef(t.into()),
|
||||||
OpaqueTyItem(t) => ItemEnum::OpaqueTyItem(t.into()),
|
OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into()),
|
||||||
ConstantItem(c) => ItemEnum::ConstantItem(c.into()),
|
ConstantItem(c) => ItemEnum::Constant(c.into()),
|
||||||
MacroItem(m) => ItemEnum::MacroItem(m.source),
|
MacroItem(m) => ItemEnum::Macro(m.source),
|
||||||
ProcMacroItem(m) => ItemEnum::ProcMacroItem(m.into()),
|
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into()),
|
||||||
AssocConstItem(t, s) => ItemEnum::AssocConstItem { type_: t.into(), default: s },
|
AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into(), default: s },
|
||||||
AssocTypeItem(g, t) => ItemEnum::AssocTypeItem {
|
AssocTypeItem(g, t) => ItemEnum::AssocType {
|
||||||
bounds: g.into_iter().map(Into::into).collect(),
|
bounds: g.into_iter().map(Into::into).collect(),
|
||||||
default: t.map(Into::into),
|
default: t.map(Into::into),
|
||||||
},
|
},
|
||||||
|
@ -185,7 +183,7 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option<Sy
|
||||||
PrimitiveItem(_) | KeywordItem(_) => {
|
PrimitiveItem(_) | KeywordItem(_) => {
|
||||||
panic!("{:?} is not supported for JSON output", item)
|
panic!("{:?} is not supported for JSON output", item)
|
||||||
}
|
}
|
||||||
ExternCrateItem { ref src } => ItemEnum::ExternCrateItem {
|
ExternCrateItem { ref src } => ItemEnum::ExternCrate {
|
||||||
name: name.as_ref().unwrap().to_string(),
|
name: name.as_ref().unwrap().to_string(),
|
||||||
rename: src.map(|x| x.to_string()),
|
rename: src.map(|x| x.to_string()),
|
||||||
},
|
},
|
||||||
|
|
|
@ -108,8 +108,7 @@ impl JsonRenderer<'tcx> {
|
||||||
.last()
|
.last()
|
||||||
.map(Clone::clone),
|
.map(Clone::clone),
|
||||||
visibility: types::Visibility::Public,
|
visibility: types::Visibility::Public,
|
||||||
kind: types::ItemKind::Trait,
|
inner: types::ItemEnum::Trait(trait_item.clone().into()),
|
||||||
inner: types::ItemEnum::TraitItem(trait_item.clone().into()),
|
|
||||||
source: None,
|
source: None,
|
||||||
docs: Default::default(),
|
docs: Default::default(),
|
||||||
links: Default::default(),
|
links: Default::default(),
|
||||||
|
@ -158,11 +157,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||||
|
|
||||||
let id = item.def_id;
|
let id = item.def_id;
|
||||||
if let Some(mut new_item) = self.convert_item(item) {
|
if let Some(mut new_item) = self.convert_item(item) {
|
||||||
if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner {
|
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
|
||||||
t.implementors = self.get_trait_implementors(id)
|
t.implementors = self.get_trait_implementors(id)
|
||||||
} else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner {
|
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
|
||||||
s.impls = self.get_impls(id)
|
s.impls = self.get_impls(id)
|
||||||
} else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
|
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
|
||||||
e.impls = self.get_impls(id)
|
e.impls = self.get_impls(id)
|
||||||
}
|
}
|
||||||
let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
|
let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
|
||||||
|
|
|
@ -9,3 +9,6 @@ path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub struct Item {
|
||||||
/// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
|
/// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
|
||||||
pub attrs: Vec<String>,
|
pub attrs: Vec<String>,
|
||||||
pub deprecation: Option<Deprecation>,
|
pub deprecation: Option<Deprecation>,
|
||||||
pub kind: ItemKind,
|
#[serde(flatten)]
|
||||||
pub inner: ItemEnum,
|
pub inner: ItemEnum,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,48 +185,48 @@ pub enum ItemKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
|
||||||
#[serde(untagged)]
|
#[serde(tag = "kind", content = "inner", rename_all = "snake_case")]
|
||||||
pub enum ItemEnum {
|
pub enum ItemEnum {
|
||||||
ModuleItem(Module),
|
Module(Module),
|
||||||
ExternCrateItem {
|
ExternCrate {
|
||||||
name: String,
|
name: String,
|
||||||
rename: Option<String>,
|
rename: Option<String>,
|
||||||
},
|
},
|
||||||
ImportItem(Import),
|
Import(Import),
|
||||||
|
|
||||||
UnionItem(Union),
|
Union(Union),
|
||||||
StructItem(Struct),
|
Struct(Struct),
|
||||||
StructFieldItem(Type),
|
StructField(Type),
|
||||||
EnumItem(Enum),
|
Enum(Enum),
|
||||||
VariantItem(Variant),
|
Variant(Variant),
|
||||||
|
|
||||||
FunctionItem(Function),
|
Function(Function),
|
||||||
|
|
||||||
TraitItem(Trait),
|
Trait(Trait),
|
||||||
TraitAliasItem(TraitAlias),
|
TraitAlias(TraitAlias),
|
||||||
MethodItem(Method),
|
Method(Method),
|
||||||
ImplItem(Impl),
|
Impl(Impl),
|
||||||
|
|
||||||
TypedefItem(Typedef),
|
Typedef(Typedef),
|
||||||
OpaqueTyItem(OpaqueTy),
|
OpaqueTy(OpaqueTy),
|
||||||
ConstantItem(Constant),
|
Constant(Constant),
|
||||||
|
|
||||||
StaticItem(Static),
|
Static(Static),
|
||||||
|
|
||||||
/// `type`s from an extern block
|
/// `type`s from an extern block
|
||||||
ForeignTypeItem,
|
ForeignType,
|
||||||
|
|
||||||
/// Declarative macro_rules! macro
|
/// Declarative macro_rules! macro
|
||||||
MacroItem(String),
|
Macro(String),
|
||||||
ProcMacroItem(ProcMacro),
|
ProcMacro(ProcMacro),
|
||||||
|
|
||||||
AssocConstItem {
|
AssocConst {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
type_: Type,
|
type_: Type,
|
||||||
/// e.g. `const X: usize = 5;`
|
/// e.g. `const X: usize = 5;`
|
||||||
default: Option<String>,
|
default: Option<String>,
|
||||||
},
|
},
|
||||||
AssocTypeItem {
|
AssocType {
|
||||||
bounds: Vec<GenericBound>,
|
bounds: Vec<GenericBound>,
|
||||||
/// e.g. `type X = usize;`
|
/// e.g. `type X = usize;`
|
||||||
default: Option<Type>,
|
default: Option<Type>,
|
||||||
|
@ -508,3 +508,6 @@ pub struct Static {
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
pub expr: String,
|
pub expr: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
34
src/rustdoc-json-types/tests.rs
Normal file
34
src/rustdoc-json-types/tests.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_struct_info_roundtrip() {
|
||||||
|
let s = ItemEnum::Struct(Struct {
|
||||||
|
struct_type: StructType::Plain,
|
||||||
|
generics: Generics { params: vec![], where_predicates: vec![] },
|
||||||
|
fields_stripped: false,
|
||||||
|
fields: vec![],
|
||||||
|
impls: vec![],
|
||||||
|
});
|
||||||
|
|
||||||
|
let struct_json = serde_json::to_string(&s).unwrap();
|
||||||
|
|
||||||
|
let de_s = serde_json::from_str(&struct_json).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(s, de_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_union_info_roundtrip() {
|
||||||
|
let u = ItemEnum::Union(Union {
|
||||||
|
generics: Generics { params: vec![], where_predicates: vec![] },
|
||||||
|
fields_stripped: false,
|
||||||
|
fields: vec![],
|
||||||
|
impls: vec![],
|
||||||
|
});
|
||||||
|
|
||||||
|
let union_json = serde_json::to_string(&u).unwrap();
|
||||||
|
|
||||||
|
let de_u = serde_json::from_str(&union_json).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(u, de_u);
|
||||||
|
}
|
|
@ -5,22 +5,26 @@
|
||||||
debug s => _1; // in scope 0 at $DIR/deduplicate_blocks.rs:2:36: 2:37
|
debug s => _1; // in scope 0 at $DIR/deduplicate_blocks.rs:2:36: 2:37
|
||||||
let mut _0: bool; // return place in scope 0 at $DIR/deduplicate_blocks.rs:2:48: 2:52
|
let mut _0: bool; // return place in scope 0 at $DIR/deduplicate_blocks.rs:2:48: 2:52
|
||||||
let mut _2: &[u8]; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
let mut _2: &[u8]; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
let mut _3: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
let mut _3: &str; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12
|
||||||
let mut _4: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
let mut _4: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
||||||
let mut _5: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
let mut _5: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
||||||
let mut _6: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
let mut _6: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
||||||
|
let mut _7: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
||||||
scope 1 (inlined core::str::<impl str>::as_bytes) { // at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
scope 1 (inlined core::str::<impl str>::as_bytes) { // at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
debug self => _7; // in scope 1 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
debug self => _3; // in scope 1 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
let mut _7: &str; // in scope 1 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
let mut _8: &str; // in scope 1 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
scope 2 {
|
scope 2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_2); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
StorageLive(_2); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
_7 = _1; // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12
|
StorageLive(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12
|
||||||
- _2 = transmute::<&str, &[u8]>(move _7) -> bb14; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
_3 = _1; // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12
|
||||||
+ _2 = transmute::<&str, &[u8]>(move _7) -> bb12; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
StorageLive(_8); // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
|
_8 = _3; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
|
- _2 = transmute::<&str, &[u8]>(move _8) -> bb14; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
|
+ _2 = transmute::<&str, &[u8]>(move _8) -> bb12; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/deduplicate_blocks.rs:3:11: 3:23
|
// + span: $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {std::intrinsics::transmute::<&str, &[u8]>}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {std::intrinsics::transmute::<&str, &[u8]>}, val: Value(Scalar(<ZST>)) }
|
||||||
|
@ -44,9 +48,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
_3 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
_4 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
||||||
_4 = Ge(move _3, const 3_usize); // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
_5 = Ge(move _4, const 3_usize); // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
||||||
switchInt(move _4) -> [false: bb9, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
switchInt(move _5) -> [false: bb9, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
@ -93,9 +97,11 @@
|
||||||
|
|
||||||
- bb14: {
|
- bb14: {
|
||||||
+ bb12: {
|
+ bb12: {
|
||||||
_5 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
StorageDead(_8); // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23
|
||||||
_6 = Ge(move _5, const 4_usize); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
StorageDead(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:22: 3:23
|
||||||
switchInt(move _6) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
_6 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
||||||
|
_7 = Ge(move _6, const 4_usize); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
||||||
|
switchInt(move _7) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Tests that assignment in both branches of an `if` are eliminated.
|
//! Tests that assignment in both branches of an `if` are eliminated.
|
||||||
|
// compile-flags: -Zunsound-mir-opts
|
||||||
fn val() -> i32 {
|
fn val() -> i32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Check that DestinationPropagation does not propagate an assignment to a function argument
|
// Check that DestinationPropagation does not propagate an assignment to a function argument
|
||||||
// (doing so can break usages of the original argument value)
|
// (doing so can break usages of the original argument value)
|
||||||
|
// compile-flags: -Zunsound-mir-opts
|
||||||
fn dummy(x: u8) -> u8 {
|
fn dummy(x: u8) -> u8 {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
|
//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
|
||||||
|
// compile-flags: -Zunsound-mir-opts
|
||||||
fn val() -> i32 {
|
fn val() -> i32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
|
//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
|
||||||
|
// compile-flags: -Zunsound-mir-opts
|
||||||
// EMIT_MIR simple.nrvo.DestinationPropagation.diff
|
// EMIT_MIR simple.nrvo.DestinationPropagation.diff
|
||||||
fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
|
fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! Tests that projections through unions cancel `DestinationPropagation`.
|
//! Tests that projections through unions cancel `DestinationPropagation`.
|
||||||
|
// compile-flags: -Zunsound-mir-opts
|
||||||
fn val() -> u32 {
|
fn val() -> u32 {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
|
||||||
debug _q => _9; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
debug _q => _9; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
let mut _10: T; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
let mut _10: i32; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
|
let mut _11: T; // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +40,13 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
|
||||||
(_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
(_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
StorageLive(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
StorageLive(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
_9 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
_9 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
(_0.0: i32) = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
|
||||||
StorageLive(_10); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
StorageLive(_10); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
_10 = (*((*_6).1: &T)); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
_10 = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
(_0.1: T) = move _10; // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
StorageLive(_11); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
|
_11 = (*((*_6).1: &T)); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
|
(_0.0: i32) = move _10; // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
|
(_0.1: T) = move _11; // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
|
StorageDead(_11); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
StorageDead(_10); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
StorageDead(_10); // scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
StorageDead(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
StorageDead(_9); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||||
StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
|
StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
|
||||||
|
|
|
@ -5,18 +5,20 @@
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
|
let mut _0: (); // return place in scope 0 at $DIR/inline-diverging.rs:21:12: 21:12
|
||||||
let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
let _1: (!, !); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _7: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _9: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _8: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _10: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ debug f => _2; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let _3: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _5: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _6: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ let mut _6: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ let mut _7: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
|
+ let mut _8: !; // in scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ scope 2 {
|
+ scope 2 {
|
||||||
+ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ debug a => _3; // in scope 2 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
|
+ let _5: !; // in scope 2 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ scope 3 {
|
+ scope 3 {
|
||||||
+ debug b => _6; // in scope 3 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ debug b => _5; // in scope 3 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ }
|
+ }
|
||||||
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
+ scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ scope 7 (inlined sleep) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
+ scope 7 (inlined sleep) { // at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
|
@ -40,12 +42,11 @@
|
||||||
- // mir::Constant
|
- // mir::Constant
|
||||||
// + span: $DIR/inline-diverging.rs:22:16: 22:21
|
// + span: $DIR/inline-diverging.rs:22:16: 22:21
|
||||||
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar(<ZST>)) }
|
||||||
+ StorageLive(_6); // scope 0 at $DIR/inline-diverging.rs:22:5: 22:22
|
|
||||||
+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ StorageLive(_3); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ StorageLive(_4); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ _4 = &_2; // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ StorageLive(_7); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ StorageLive(_9); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ _7 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ _9 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22
|
+ goto -> bb1; // scope 4 at $DIR/inline-diverging.rs:22:5: 22:22
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,12 @@
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline-generator.rs:9:14: 9:46
|
+ scope 6 (inlined g::{closure#0}) { // at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ debug a => _8; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ debug a => _11; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ let mut _8: bool; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ let mut _8: i32; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ let mut _9: u32; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ let mut _9: bool; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ let mut _10: bool; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ let _11: bool; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ let mut _12: u32; // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
|
@ -65,16 +68,18 @@
|
||||||
- // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator<bool>>, bool) -> std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return> {<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) }
|
- // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator<bool>>, bool) -> std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return> {<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) }
|
||||||
+ StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ StorageLive(_8); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ StorageLive(_9); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ _9 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_12); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ _12 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
}
|
}
|
||||||
|
|
||||||
- bb3: {
|
- bb3: {
|
||||||
+ bb1: {
|
+ bb1: {
|
||||||
+ StorageDead(_9); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageDead(_12); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ StorageDead(_8); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageDead(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ StorageDead(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ StorageDead(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageDead(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
StorageDead(_2); // scope 0 at $DIR/inline-generator.rs:9:45: 9:46
|
StorageDead(_2); // scope 0 at $DIR/inline-generator.rs:9:45: 9:46
|
||||||
StorageDead(_4); // scope 0 at $DIR/inline-generator.rs:9:46: 9:47
|
StorageDead(_4); // scope 0 at $DIR/inline-generator.rs:9:46: 9:47
|
||||||
|
@ -89,28 +94,36 @@
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb3: {
|
+ bb3: {
|
||||||
+ _8 = move _7; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ _11 = move _7; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ StorageLive(_9); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ _9 = _11; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb4: {
|
+ bb4: {
|
||||||
+ ((_1 as Yielded).0: i32) = const 7_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ _8 = const 7_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb5: {
|
+ bb5: {
|
||||||
+ ((_1 as Yielded).0: i32) = const 13_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ _8 = const 13_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ goto -> bb6; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb6: {
|
+ bb6: {
|
||||||
|
+ StorageDead(_9); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ discriminant(_1) = 0; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39
|
+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:11: 15:39
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ bb7: {
|
+ bb7: {
|
||||||
+ ((_1 as Complete).0: bool) = move _7; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ StorageLive(_8); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ _10 = move _7; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ StorageDead(_8); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
|
+ ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ discriminant(_1) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
+ discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
|
||||||
+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41
|
+ goto -> bb1; // scope 0 at $DIR/inline-generator.rs:15:41: 15:41
|
||||||
|
|
|
@ -6,25 +6,32 @@
|
||||||
let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
|
let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
|
||||||
let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
|
let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
|
||||||
let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
|
let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
|
||||||
let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _5: i32; // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _6: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _7: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _8: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _9: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _12: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _13: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
|
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
|
||||||
let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
scope 3 {
|
scope 3 {
|
||||||
debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
|
debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
|
let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 4 {
|
scope 4 {
|
||||||
debug left_val => _11; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
debug right_val => _12; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let _10: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let _14: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug kind => _10; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug kind => _14; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,36 +50,57 @@
|
||||||
_1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21
|
_1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21
|
||||||
StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21
|
StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21
|
||||||
StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
|
StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
|
||||||
((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
|
StorageLive(_5); // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
|
_5 = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
|
((_4 as Some).0: i32) = move _5; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
||||||
discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
||||||
(_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_5); // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
|
||||||
_6 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// ty::Const
|
// ty::Const
|
||||||
// + ty: &i32
|
// + ty: &i32
|
||||||
// + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
|
// + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
||||||
(_5.1: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_11 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_12 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_9 = (*_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_9 = (_6.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_8 = Eq(move _9, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageDead(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_10 = (_6.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_7 = Not(move _8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageDead(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
switchInt(move _7) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_13 = (*_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_11 = Not(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
discriminant(_10) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
discriminant(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
discriminant(_13) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _11, move _12, move _13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_16 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_18 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
|
||||||
|
@ -85,8 +113,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
|
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
|
||||||
|
StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
|
||||||
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
|
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
|
||||||
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
|
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,25 +6,32 @@
|
||||||
let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
|
let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
|
||||||
let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
|
let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
|
||||||
let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
|
let _3: i32; // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
|
||||||
let mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _5: i32; // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
let mut _6: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _6: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _7: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _8: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _8: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _9: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _12: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let mut _13: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let mut _15: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _16: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _17: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _19: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
|
debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
|
||||||
let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
let _4: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
scope 3 {
|
scope 3 {
|
||||||
debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
|
debug _prev => _4; // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
|
let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
let mut _20: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 4 {
|
scope 4 {
|
||||||
debug left_val => _11; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
debug right_val => _12; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
let _10: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
let _14: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
scope 5 {
|
scope 5 {
|
||||||
debug kind => _10; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
debug kind => _14; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,36 +50,57 @@
|
||||||
_1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21
|
_1 = _3; // scope 2 at $DIR/issue-73223.rs:3:20: 3:21
|
||||||
StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21
|
StorageDead(_3); // scope 0 at $DIR/issue-73223.rs:3:20: 3:21
|
||||||
StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
|
StorageDead(_2); // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
|
||||||
((_4 as Some).0: i32) = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
StorageLive(_4); // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
|
||||||
|
StorageLive(_5); // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
|
_5 = _1; // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
|
||||||
|
((_4 as Some).0: i32) = move _5; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
||||||
discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
discriminant(_4) = 1; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
|
||||||
(_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_5); // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
|
||||||
_6 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// ty::Const
|
// ty::Const
|
||||||
// + ty: &i32
|
// + ty: &i32
|
||||||
// + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
|
// + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0]))
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
// + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) }
|
||||||
(_5.1: &i32) = move _6; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_11 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_12 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_9 = (*_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_9 = (_6.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_8 = Eq(move _9, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageDead(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_10 = (_6.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_7 = Not(move _8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageDead(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
switchInt(move _7) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_13 = (*_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_11 = Not(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
switchInt(move _11) -> [false: bb2, otherwise: bb1]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
discriminant(_10) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
discriminant(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
StorageLive(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_15); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
discriminant(_13) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _11, move _12, move _13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
_16 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_15 = _16; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_18 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
_17 = _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
discriminant(_19) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option<std::fmt::Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(Scalar(<ZST>)) }
|
||||||
|
@ -85,8 +113,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
|
StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
|
||||||
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
|
_0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
|
||||||
|
StorageDead(_4); // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
|
||||||
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
|
StorageDead(_1); // scope 0 at $DIR/issue-73223.rs:9:1: 9:2
|
||||||
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
|
return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,60 +3,67 @@
|
||||||
fn num_to_digit(_1: char) -> u32 {
|
fn num_to_digit(_1: char) -> u32 {
|
||||||
debug num => _1; // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
|
debug num => _1; // in scope 0 at $DIR/issue-59352.rs:12:21: 12:24
|
||||||
let mut _0: u32; // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
|
let mut _0: u32; // return place in scope 0 at $DIR/issue-59352.rs:12:35: 12:38
|
||||||
let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
let mut _2: char; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:11
|
||||||
let mut _3: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
let mut _3: std::option::Option<u32>; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
||||||
let mut _4: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
let mut _4: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
||||||
let mut _9: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
let mut _5: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
let mut _11: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
|
scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
debug self => _7; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
debug self => _2; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
debug radix => _4; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
debug radix => _5; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
let mut _5: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
let mut _6: &std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
let _6: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
let _7: std::option::Option<u32>; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
let mut _7: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
let mut _8: char; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
|
scope 2 (inlined Option::<u32>::is_some) { // at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
debug self => _5; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
debug self => _6; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
let mut _9: isize; // in scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
|
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
debug self => _2; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
debug self => _3; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
let mut _8: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
let mut _10: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
scope 4 {
|
scope 4 {
|
||||||
debug val => _0; // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
|
debug val => _0; // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
_7 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
|
StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
|
||||||
StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
_2 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11
|
||||||
_4 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageLive(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
StorageLive(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
_5 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
StorageLive(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageLive(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
_6 = char::methods::<impl char>::to_digit(move _7, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageLive(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
StorageLive(_8); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
_8 = _2; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
_7 = char::methods::<impl char>::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/issue-59352.rs:14:8: 14:23
|
// + span: $DIR/issue-59352.rs:14:8: 14:23
|
||||||
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
StorageDead(_11); // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
||||||
StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
||||||
_3 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
||||||
_2 = char::methods::<impl char>::to_digit(move _3, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
_4 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29
|
||||||
|
_3 = char::methods::<impl char>::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/issue-59352.rs:14:30: 14:38
|
// + span: $DIR/issue-59352.rs:14:30: 14:38
|
||||||
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: fn(char, u32) -> std::option::Option<u32> {std::char::methods::<impl char>::to_digit}, val: Value(Scalar(<ZST>)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
|
StorageDead(_11); // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
||||||
_0 = const 0_u32; // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
|
_0 = const 0_u32; // scope 0 at $DIR/issue-59352.rs:14:60: 14:61
|
||||||
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
bb3: {
|
||||||
StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
|
StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41
|
||||||
StorageLive(_8); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
|
StorageLive(_10); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
_8 = discriminant(_2); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
_10 = discriminant(_3); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
switchInt(move _8) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
switchInt(move _10) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
@ -64,12 +71,18 @@ fn num_to_digit(_1: char) -> u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb5: {
|
bb5: {
|
||||||
_5 = &_6; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
_6 = &_7; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
_9 = discriminant((*_5)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageDead(_8); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
StorageDead(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageLive(_9); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
_9 = discriminant((*_6)); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
StorageLive(_11); // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
_11 = move _9; // scope 2 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
StorageDead(_9); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
StorageDead(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageDead(_6); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
StorageDead(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
switchInt(move _9) -> [1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
StorageDead(_5); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23
|
||||||
|
StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:14:22: 14:23
|
||||||
|
switchInt(move _11) -> [1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
||||||
}
|
}
|
||||||
|
|
||||||
bb6: {
|
bb6: {
|
||||||
|
@ -90,9 +103,9 @@ fn num_to_digit(_1: char) -> u32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb8: {
|
bb8: {
|
||||||
_0 = move ((_2 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
_0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
StorageDead(_8); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
|
StorageDead(_10); // scope 0 at $DIR/issue-59352.rs:14:26: 14:50
|
||||||
StorageDead(_2); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
|
StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50
|
||||||
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
fn f_u64() -> () {
|
fn f_u64() -> () {
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
|
let mut _0: (); // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
|
||||||
|
let mut _1: u64; // in scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
|
scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
debug t => _1; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
let mut _1: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
|
||||||
let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
let _2: (); // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
let mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
|
scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
|
@ -12,6 +12,7 @@ fn f_u64() -> () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
|
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
_1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
_1 = const 0_u64; // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
StorageLive(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
|
@ -25,6 +26,7 @@ fn f_u64() -> () {
|
||||||
bb1: {
|
bb1: {
|
||||||
StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
StorageDead(_3); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
StorageDead(_2); // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
|
StorageDead(_1); // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
|
||||||
_0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:34:16: 36:2
|
_0 = const (); // scope 0 at $DIR/lower_intrinsics.rs:34:16: 36:2
|
||||||
return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
|
return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,13 @@
|
||||||
StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:14:9: 14:14
|
StorageLive(_1); // scope 0 at $DIR/simplify-locals.rs:14:9: 14:14
|
||||||
_1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify-locals.rs:14:17: 14:26
|
_1 = [const 0_u8; 10]; // scope 0 at $DIR/simplify-locals.rs:14:17: 14:26
|
||||||
- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
- StorageLive(_2); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
- _3 = &_1; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
- StorageLive(_3); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
|
- StorageLive(_4); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
|
- _4 = &_1; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
|
- _3 = _4; // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
- _2 = move _3 as &[u8] (Pointer(Unsize)); // scope 1 at $DIR/simplify-locals.rs:16:20: 16:26
|
||||||
|
- StorageDead(_3); // scope 1 at $DIR/simplify-locals.rs:16:25: 16:26
|
||||||
|
- StorageDead(_4); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27
|
||||||
- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27
|
- StorageDead(_2); // scope 1 at $DIR/simplify-locals.rs:16:26: 16:27
|
||||||
_0 = const (); // scope 0 at $DIR/simplify-locals.rs:13:8: 17:2
|
_0 = const (); // scope 0 at $DIR/simplify-locals.rs:13:8: 17:2
|
||||||
StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:17:1: 17:2
|
StorageDead(_1); // scope 0 at $DIR/simplify-locals.rs:17:1: 17:2
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
macro_rules! mod_decl {
|
macro_rules! mod_decl {
|
||||||
($i:ident) => {
|
($i:ident) => {
|
||||||
mod $i; //~ ERROR Cannot declare a non-inline module inside a block
|
mod $i; //~ ERROR cannot declare a non-inline module inside a block
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Cannot declare a non-inline module inside a block unless it has a path attribute
|
error: cannot declare a non-inline module inside a block unless it has a path attribute
|
||||||
--> $DIR/macro-expanded-mod.rs:5:9
|
--> $DIR/macro-expanded-mod.rs:5:9
|
||||||
|
|
|
|
||||||
LL | mod $i;
|
LL | mod $i;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Test that non-inline modules are not allowed inside blocks.
|
// Test that non-inline modules are not allowed inside blocks.
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
mod foo; //~ ERROR Cannot declare a non-inline module inside a block
|
mod foo; //~ ERROR cannot declare a non-inline module inside a block
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
error: Cannot declare a non-inline module inside a block unless it has a path attribute
|
error: cannot declare a non-inline module inside a block unless it has a path attribute
|
||||||
--> $DIR/non-inline-mod-restriction.rs:4:5
|
--> $DIR/non-inline-mod-restriction.rs:4:5
|
||||||
|
|
|
|
||||||
LL | mod foo;
|
LL | mod foo;
|
||||||
|
|
7
src/test/ui/modules/path-no-file-name.rs
Normal file
7
src/test/ui/modules/path-no-file-name.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// normalize-stderr-test: "\.:.*\(" -> ".: $$ACCESS_DENIED_MSG ("
|
||||||
|
// normalize-stderr-test: "os error \d+" -> "os error $$ACCESS_DENIED_CODE"
|
||||||
|
|
||||||
|
#[path = "."]
|
||||||
|
mod m; //~ ERROR couldn't read
|
||||||
|
|
||||||
|
fn main() {}
|
8
src/test/ui/modules/path-no-file-name.stderr
Normal file
8
src/test/ui/modules/path-no-file-name.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error: couldn't read $DIR/.: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE)
|
||||||
|
--> $DIR/path-no-file-name.rs:5:1
|
||||||
|
|
|
||||||
|
LL | mod m;
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
// error-pattern: circular modules
|
||||||
|
|
||||||
#[path = "circular_modules_hello.rs"]
|
#[path = "circular_modules_hello.rs"]
|
||||||
mod circular_modules_hello; //~ ERROR: circular modules
|
mod circular_modules_hello;
|
||||||
|
|
||||||
pub fn hi_str() -> String {
|
pub fn hi_str() -> String {
|
||||||
"Hi!".to_string()
|
"Hi!".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module
|
circular_modules_hello::say_hello();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs
|
error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs
|
||||||
--> $DIR/circular_modules_main.rs:2:1
|
--> $DIR/circular_modules_hello.rs:4:1
|
||||||
|
|
|
|
||||||
LL | mod circular_modules_hello;
|
LL | mod circular_modules_main;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0425]: cannot find function `say_hello` in module `circular_modules_hello`
|
error[E0425]: cannot find function `hi_str` in module `circular_modules_main`
|
||||||
--> $DIR/circular_modules_main.rs:9:29
|
--> $DIR/circular_modules_hello.rs:7:43
|
||||||
|
|
|
|
||||||
LL | circular_modules_hello::say_hello();
|
LL | println!("{}", circular_modules_main::hi_str());
|
||||||
| ^^^^^^^^^ not found in `circular_modules_hello`
|
| ^^^^^^ not found in `circular_modules_main`
|
||||||
|
|
|
|
||||||
help: consider importing this function
|
help: consider importing this function
|
||||||
|
|
|
|
||||||
LL | use circular_modules_hello::say_hello;
|
LL | use hi_str;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
9
src/test/ui/proc-macro/cfg-eval-fail.rs
Normal file
9
src/test/ui/proc-macro/cfg-eval-fail.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#![feature(cfg_eval)]
|
||||||
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
//~^ ERROR removing an expression is not supported in this position
|
||||||
|
//~| ERROR removing an expression is not supported in this position
|
||||||
|
//~| ERROR removing an expression is not supported in this position
|
||||||
|
}
|
20
src/test/ui/proc-macro/cfg-eval-fail.stderr
Normal file
20
src/test/ui/proc-macro/cfg-eval-fail.stderr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: removing an expression is not supported in this position
|
||||||
|
--> $DIR/cfg-eval-fail.rs:5:25
|
||||||
|
|
|
||||||
|
LL | let _ = #[cfg_eval] #[cfg(FALSE)] 0;
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
32
src/test/ui/proc-macro/cfg-eval.rs
Normal file
32
src/test/ui/proc-macro/cfg-eval.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: -Z span-debug
|
||||||
|
// aux-build:test-macros.rs
|
||||||
|
|
||||||
|
#![feature(cfg_eval)]
|
||||||
|
#![feature(proc_macro_hygiene)]
|
||||||
|
#![feature(stmt_expr_attributes)]
|
||||||
|
|
||||||
|
#![no_std] // Don't load unnecessary hygiene information from std
|
||||||
|
extern crate std;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate test_macros;
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[print_attr]
|
||||||
|
struct S1 {
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
field_false: u8,
|
||||||
|
#[cfg(all(/*true*/))]
|
||||||
|
#[cfg_attr(FALSE, unknown_attr)]
|
||||||
|
#[cfg_attr(all(/*true*/), allow())]
|
||||||
|
field_true: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_eval]
|
||||||
|
#[cfg(FALSE)]
|
||||||
|
struct S2 {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = #[cfg_eval] #[print_attr](#[cfg(FALSE)] 0, #[cfg(all(/*true*/))] 1);
|
||||||
|
}
|
135
src/test/ui/proc-macro/cfg-eval.stdout
Normal file
135
src/test/ui/proc-macro/cfg-eval.stdout
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, }
|
||||||
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "struct",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "S1",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Brace,
|
||||||
|
stream: TokenStream [
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "cfg",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "all",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "allow",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "field_true",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ':',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Ident {
|
||||||
|
ident: "u8",
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:17:1: 24:2 (#0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
PRINT-ATTR INPUT (DISPLAY): (#[cfg(all())] 1,)
|
||||||
|
PRINT-ATTR INPUT (DEBUG): TokenStream [
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Punct {
|
||||||
|
ch: '#',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Bracket,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "cfg",
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [
|
||||||
|
Ident {
|
||||||
|
ident: "all",
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Group {
|
||||||
|
delimiter: Parenthesis,
|
||||||
|
stream: TokenStream [],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Literal {
|
||||||
|
kind: Integer,
|
||||||
|
symbol: "1",
|
||||||
|
suffix: None,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
Punct {
|
||||||
|
ch: ',',
|
||||||
|
spacing: Alone,
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
span: $DIR/cfg-eval.rs:31:38: 31:80 (#0),
|
||||||
|
},
|
||||||
|
]
|
Loading…
Add table
Add a link
Reference in a new issue