From 6a679ffc8125419123e416fbeb14a4e118e9f366 Mon Sep 17 00:00:00 2001 From: The8472 Date: Sat, 13 Feb 2021 00:54:17 +0100 Subject: [PATCH 01/27] bypass auto_da_alloc for metadata files --- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_interface/src/util.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 56aa3939b22dc..c1ae450483e67 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -983,7 +983,7 @@ fn encode_and_write_metadata( .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_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)); } if tcx.sess.opts.json_artifact_notifications { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index b7dc539c6d606..dc2c90472c0ee 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -670,6 +670,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. // // FIXME: Currently the `everybody_loops` transformation is not applied to: From 6e52b23fa94ed967daed38cb3796d0874ec705a7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 28 Feb 2021 14:50:03 -0500 Subject: [PATCH 02/27] Fix jemalloc usage on OSX Closes #82423 --- compiler/rustc/src/main.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 6bc5aa6382c4c..3f03d1b68695e 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -24,6 +24,20 @@ fn main() { static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc; #[used] 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(); From 920e2d82484909a85fabc636fd216ad2fa0a168f Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Fri, 26 Feb 2021 17:52:31 +0100 Subject: [PATCH 03/27] Add natvis for Result, NonNull, CString, CStr, and Cow --- src/etc/natvis/liballoc.natvis | 7 +++++++ src/etc/natvis/libcore.natvis | 15 +++++++++++++++ src/etc/natvis/libstd.natvis | 29 +++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index cfaafc5734bce..9cc60fc7b47e5 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -75,4 +75,11 @@ ptr.pointer->data + + Borrowed({__0}) + Owned({__0}) + + __0 + + diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis index 984a8bfb13c7c..9c3c26f597838 100644 --- a/src/etc/natvis/libcore.natvis +++ b/src/etc/natvis/libcore.natvis @@ -30,4 +30,19 @@ + + Ok({__0}) + Err({(*($T2*) &__0)}) + + __0 + (*($T2*) &__0) + + + + + {(void*) pointer} + + *pointer + + \ No newline at end of file diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 7e5ee7b13daf1..b0542b0c63303 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -72,4 +72,33 @@ + + + {inner.data_ptr,s} + + + + + inner.length + (char*)inner.data_ptr + + + + + + + + {(char*) inner} + + + {(char*) inner} + + + strlen((char *) inner) + 1 + (char*)inner + + + + + From c8a0e8d61b57b59e0dbcd4d90fb046b1a43abb4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 4 Mar 2021 13:36:48 +0300 Subject: [PATCH 04/27] Refactor confirm_builtin_call, remove partial if Pass callee expr to `confirm_builtin_call`. This removes a partial pattern match in `confirm_builtin_call` and the `panic` in the `else` branch. The diff is large because of indentation changes caused by removing the if-let. --- compiler/rustc_typeck/src/check/callee.rs | 191 +++++++++++----------- 1 file changed, 96 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index ca1e79fac73e9..66f6ac510d592 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -77,11 +77,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let output = match result { None => { // 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)) => { - 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)) => { @@ -281,6 +287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn confirm_builtin_call( &self, call_expr: &'tcx hir::Expr<'tcx>, + callee_expr: &'tcx hir::Expr<'tcx>, callee_ty: Ty<'tcx>, arg_exprs: &'tcx [hir::Expr<'tcx>], expected: Expectation<'tcx>, @@ -299,110 +306,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let hir::ExprKind::Call(callee, _) = call_expr.kind { - let mut err = type_error_struct!( - self.tcx.sess, - callee.span, - callee_ty, - E0618, - "expected function, found {}", - match unit_variant { - Some(ref path) => format!("enum variant `{}`", path), - None => format!("`{}`", callee_ty), - } - ); + let mut err = type_error_struct!( + self.tcx.sess, + callee_expr.span, + callee_ty, + E0618, + "expected function, found {}", + match unit_variant { + Some(ref path) => format!("enum variant `{}`", path), + None => format!("`{}`", callee_ty), + } + ); - self.identify_bad_closure_def_and_call( - &mut err, - call_expr.hir_id, - &callee.kind, - callee.span, - ); + self.identify_bad_closure_def_and_call( + &mut err, + call_expr.hir_id, + &callee_expr.kind, + callee_expr.span, + ); - if let Some(ref path) = unit_variant { - err.span_suggestion( - call_expr.span, - &format!( - "`{}` is a unit variant, you need to write it \ + if let Some(ref path) = unit_variant { + err.span_suggestion( + call_expr.span, + &format!( + "`{}` is a unit variant, you need to write it \ without the parenthesis", - path - ), - path.to_string(), - Applicability::MachineApplicable, - ); - } + path + ), + path.to_string(), + Applicability::MachineApplicable, + ); + } - let mut inner_callee_path = None; - let def = match callee.kind { - hir::ExprKind::Path(ref qpath) => { - self.typeck_results.borrow().qpath_res(qpath, callee.hir_id) + let mut inner_callee_path = None; + let def = match callee_expr.kind { + hir::ExprKind::Path(ref qpath) => { + self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id) + } + hir::ExprKind::Call(ref inner_callee, _) => { + // If the call spans more than one line and the callee kind is + // itself another `ExprCall`, that's a clue that we might just be + // missing a semicolon (Issue #51055) + let call_is_multiline = + self.tcx.sess.source_map().is_multiline(call_expr.span); + if call_is_multiline { + err.span_suggestion( + callee_expr.span.shrink_to_hi(), + "consider using a semicolon here", + ";".to_owned(), + Applicability::MaybeIncorrect, + ); } - hir::ExprKind::Call(ref inner_callee, _) => { - // If the call spans more than one line and the callee kind is - // itself another `ExprCall`, that's a clue that we might just be - // missing a semicolon (Issue #51055) - let call_is_multiline = - self.tcx.sess.source_map().is_multiline(call_expr.span); - if call_is_multiline { - err.span_suggestion( - callee.span.shrink_to_hi(), - "consider using a semicolon here", - ";".to_owned(), - Applicability::MaybeIncorrect, - ); - } - if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind { - inner_callee_path = Some(inner_qpath); - self.typeck_results - .borrow() - .qpath_res(inner_qpath, inner_callee.hir_id) - } else { - Res::Err - } + if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind { + inner_callee_path = Some(inner_qpath); + self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id) + } else { + Res::Err } - _ => Res::Err, - }; - - err.span_label(call_expr.span, "call expression requires function"); - - if let Some(span) = self.tcx.hir().res_span(def) { - let callee_ty = callee_ty.to_string(); - let label = match (unit_variant, inner_callee_path) { - (Some(path), _) => Some(format!("`{}` defined here", path)), - (_, Some(hir::QPath::Resolved(_, path))) => { - self.tcx.sess.source_map().span_to_snippet(path.span).ok().map( - |p| format!("`{}` defined here returns `{}`", p, callee_ty), - ) - } - _ => { - match def { - // Emit a different diagnostic for local variables, as they are not - // type definitions themselves, but rather variables *of* that type. - Res::Local(hir_id) => Some(format!( - "`{}` has type `{}`", - self.tcx.hir().name(hir_id), - callee_ty - )), - Res::Def(kind, def_id) - if kind.ns() == Some(Namespace::ValueNS) => - { - Some(format!( - "`{}` defined here", - self.tcx.def_path_str(def_id), - )) - } - _ => Some(format!("`{}` defined here", callee_ty)), + } + _ => Res::Err, + }; + + err.span_label(call_expr.span, "call expression requires function"); + + if let Some(span) = self.tcx.hir().res_span(def) { + let callee_ty = callee_ty.to_string(); + let label = match (unit_variant, inner_callee_path) { + (Some(path), _) => Some(format!("`{}` defined here", path)), + (_, Some(hir::QPath::Resolved(_, path))) => self + .tcx + .sess + .source_map() + .span_to_snippet(path.span) + .ok() + .map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)), + _ => { + match def { + // Emit a different diagnostic for local variables, as they are not + // type definitions themselves, but rather variables *of* that type. + Res::Local(hir_id) => Some(format!( + "`{}` has type `{}`", + self.tcx.hir().name(hir_id), + callee_ty + )), + Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => { + Some(format!( + "`{}` defined here", + self.tcx.def_path_str(def_id), + )) } + _ => Some(format!("`{}` defined here", callee_ty)), } - }; - if let Some(label) = label { - err.span_label(span, label); } + }; + if let Some(label) = label { + err.span_label(span, label); } - err.emit(); - } else { - bug!("call_expr.kind should be an ExprKind::Call, got {:?}", call_expr.kind); } + err.emit(); // This is the "default" function signature, used in case of error. // In that case, we check each argument against "error" in order to From bc18eb471772403de20cd9bc0a836ce1f5e09e98 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 16:12:11 +0300 Subject: [PATCH 05/27] expand: Remove obsolete `DirectoryOwnership::UnownedViaMod` This ownership kind is only constructed in the case of path attributes like `#[path = ".."]` without a file name segment, which always represent some kind of directories and will produce and error on attempt to parse them as a module file. --- compiler/rustc_expand/src/module.rs | 61 +++----------------- src/test/ui/modules/path-no-file-name.rs | 7 +++ src/test/ui/modules/path-no-file-name.stderr | 8 +++ 3 files changed, 24 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/modules/path-no-file-name.rs create mode 100644 src/test/ui/modules/path-no-file-name.stderr diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 076d3b02be93f..99c1591d40a81 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -22,7 +22,6 @@ pub enum DirectoryOwnership { relative: Option, }, UnownedViaBlock, - UnownedViaMod, } /// Information about the path to a module. @@ -134,23 +133,20 @@ fn submod_path<'a>( dir_path: &Path, ) -> PResult<'a, ModulePathSuccess> { if let Some(path) = submod_path_from_attr(sess, attrs, dir_path) { - let ownership = match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }; + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + let ownership = DirectoryOwnership::Owned { relative: None }; return Ok(ModulePathSuccess { ownership, path }); } let relative = match ownership { DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + DirectoryOwnership::UnownedViaBlock => None, }; let ModulePath { path_exists, name, result } = default_submod_path(&sess.parse_sess, id, span, relative, dir_path); @@ -160,10 +156,6 @@ fn submod_path<'a>( 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) - } } } @@ -182,41 +174,6 @@ fn error_decl_mod_in_block<'a, T>( 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"]`. /// The provided `dir_path` is joined with the `path_string`. pub(super) fn submod_path_from_attr( diff --git a/src/test/ui/modules/path-no-file-name.rs b/src/test/ui/modules/path-no-file-name.rs new file mode 100644 index 0000000000000..f62cd2a9eb4e4 --- /dev/null +++ b/src/test/ui/modules/path-no-file-name.rs @@ -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() {} diff --git a/src/test/ui/modules/path-no-file-name.stderr b/src/test/ui/modules/path-no-file-name.stderr new file mode 100644 index 0000000000000..32a213c68f654 --- /dev/null +++ b/src/test/ui/modules/path-no-file-name.stderr @@ -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 + From 39052c55bb0259930dd9e6b0fc27a715793b07c8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 21 Feb 2021 19:15:43 +0300 Subject: [PATCH 06/27] expand: Move module file path stack from global session to expansion data Also don't push the paths on the stack directly in `fn parse_external_mod`, return them instead. --- .../rustc_builtin_macros/src/source_util.rs | 7 +- compiler/rustc_expand/src/base.rs | 22 +++++- compiler/rustc_expand/src/expand.rs | 71 ++++++++++--------- compiler/rustc_expand/src/module.rs | 22 +++--- compiler/rustc_session/src/parse.rs | 4 -- src/test/ui/parser/circular_modules_main.rs | 6 +- .../ui/parser/circular_modules_main.stderr | 18 ++--- 7 files changed, 80 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 28efd483c8670..98659f15a7e2f 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -101,7 +101,7 @@ pub fn expand_include<'cx>( None => return DummyResult::any(sp), }; // 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, Err(mut err) => { 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`. // 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. - file.pop(); + let dir_path = file.parent().unwrap_or(&file).to_owned(); + cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; - let mod_path = cx.current_expansion.module.mod_path.clone(); - cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file }); struct ExpandResult<'a> { p: Parser<'a>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index ce8103c0f850d..a0632522ca0e5 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -894,10 +894,26 @@ pub trait ResolverExpand { fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct ModuleData { + /// Path to the module starting from the crate name, like `my_crate::foo::bar`. pub mod_path: Vec, - 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, + /// 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)] @@ -946,7 +962,7 @@ impl<'a> ExtCtxt<'a> { current_expansion: ExpansionData { id: ExpnId::root(), depth: 0, - module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }), + module: Default::default(), directory_ownership: DirectoryOwnership::Owned { relative: None }, prior_type_ascription: None, }, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index b474cad1242e8..8d633afacf478 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -355,16 +355,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // FIXME: Avoid visiting the crate as a `Mod` item, // make crate a first class expansion target instead. pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate { - let mut module = ModuleData { - 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(), - other => PathBuf::from(other.to_string()), - }, + let file_path = match self.cx.source_map().span_to_unmapped_path(krate.span) { + FileName::Real(name) => name.into_local_path(), + other => PathBuf::from(other.to_string()), }; - module.directory.pop(); - self.cx.root_path = module.directory.clone(); - self.cx.current_expansion.module = Rc::new(module); + let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); + self.cx.root_path = dir_path.clone(); + 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 { attrs: krate.attrs, @@ -1276,25 +1277,30 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }) } ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { - let sess = &self.cx.sess.parse_sess; - let orig_ownership = self.cx.current_expansion.directory_ownership; - 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 { + let dir = Directory { + ownership: self.cx.current_expansion.directory_ownership, + path: self.cx.current_expansion.module.dir_path.clone(), + }; + let (file_path, Directory { ownership, path }) = match mod_kind { ModKind::Loaded(_, Inline::Yes, _) => { // Inline `mod foo { ... }`, but we still need to push directories. + let dir_path = push_directory(&self.cx.sess, ident, &attrs, dir); item.attrs = attrs; - push_directory(&self.cx.sess, ident, &item.attrs, dir) + (None, dir_path) } ModKind::Loaded(_, Inline::No, _) => { panic!("`mod` item is loaded from a file for the second time") } ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. - let (items, inner_span, dir) = - parse_external_mod(&self.cx.sess, ident, span, dir, &mut attrs, pushed); + let (items, inner_span, file_path, dir_path) = parse_external_mod( + &self.cx.sess, + ident, + span, + &self.cx.current_expansion.module.file_path_stack, + dir, + &mut attrs, + ); let krate = ast::Crate { attrs, items, span: inner_span, proc_macros: vec![] }; @@ -1305,34 +1311,29 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { *mod_kind = ModKind::Loaded(krate.items, Inline::No, inner_span); item.attrs = krate.attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. - item = match self.configure(item) { - Some(node) => node, - None => { - if *pushed { - sess.included_mod_stack.borrow_mut().pop(); - } - return Default::default(); - } - }; - dir + item = configure!(self, item); + (Some(file_path), dir_path) } }; // Set the module info before we flat map. - self.cx.current_expansion.directory_ownership = ownership; - module.directory = path; + let mut module = self.cx.current_expansion.module.with_dir_path(path); module.mod_path.push(ident); + if let Some(file_path) = file_path { + module.file_path_stack.push(file_path); + } + let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); + let orig_dir_ownership = + mem::replace(&mut self.cx.current_expansion.directory_ownership, ownership); let result = noop_flat_map_item(item, self); // Restore the module info. + self.cx.current_expansion.directory_ownership = orig_dir_ownership; 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 } _ => { diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 99c1591d40a81..55b48e4f6b254 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -42,10 +42,10 @@ crate fn parse_external_mod( sess: &Session, id: Ident, span: Span, // The span to blame on errors. + file_path_stack: &[PathBuf], Directory { mut ownership, path }: Directory, attrs: &mut Vec, - pop_mod_stack: &mut bool, -) -> (Vec>, Span, Directory) { +) -> (Vec>, Span, PathBuf, Directory) { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. @@ -53,20 +53,16 @@ crate fn parse_external_mod( ownership = mp.ownership; // Ensure file paths are acyclic. - let mut included_mod_stack = sess.parse_sess.included_mod_stack.borrow_mut(); - error_on_circular_module(&sess.parse_sess, span, &mp.path, &included_mod_stack)?; - included_mod_stack.push(mp.path.clone()); - *pop_mod_stack = true; // We have pushed, so notify caller. - drop(included_mod_stack); + error_on_circular_module(&sess.parse_sess, span, &mp.path, file_path_stack)?; // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); let (mut inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof)?; attrs.append(&mut inner_attrs); - (items, inner_span) + (items, inner_span, mp.path) }; // (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(|mut err| err.emit()).unwrap_or_default(); // Extract the directory path for submodules of the module. let path = sess.source_map().span_to_unmapped_path(inner_span); @@ -76,18 +72,18 @@ crate fn parse_external_mod( }; path.pop(); - (items, inner_span, Directory { ownership, path }) + (items, inner_span, file_path, Directory { ownership, path }) } fn error_on_circular_module<'a>( sess: &'a ParseSess, span: Span, path: &Path, - included_mod_stack: &[PathBuf], + file_path_stack: &[PathBuf], ) -> PResult<'a, ()> { - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + if let Some(i) = file_path_stack.iter().position(|p| *p == path) { let mut err = String::from("circular modules: "); - for p in &included_mod_stack[i..] { + for p in &file_path_stack[i..] { err.push_str(&p.to_string_lossy()); err.push_str(" -> "); } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 81b38347414e8..592773bfe1b44 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -13,7 +13,6 @@ use rustc_span::hygiene::ExpnId; use rustc_span::source_map::{FilePathMapping, SourceMap}; use rustc_span::{MultiSpan, Span, Symbol}; -use std::path::PathBuf; use std::str; /// The set of keys (and, optionally, values) that define the compilation @@ -122,8 +121,6 @@ pub struct ParseSess { pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock>, - /// Used to determine and report recursive module inclusions. - pub included_mod_stack: Lock>, source_map: Lrc, pub buffered_lints: Lock>, /// 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, missing_fragment_specifiers: Default::default(), raw_identifier_spans: Lock::new(Vec::new()), - included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs index 1ae36a1f7605e..d4b47efe68158 100644 --- a/src/test/ui/parser/circular_modules_main.rs +++ b/src/test/ui/parser/circular_modules_main.rs @@ -1,10 +1,12 @@ +// error-pattern: circular modules + #[path = "circular_modules_hello.rs"] -mod circular_modules_hello; //~ ERROR: circular modules +mod circular_modules_hello; pub fn hi_str() -> String { "Hi!".to_string() } fn main() { - circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module + circular_modules_hello::say_hello(); } diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index 5d4db8c31a2c3..ee45f65a3bd5a 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -1,18 +1,18 @@ -error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs - --> $DIR/circular_modules_main.rs:2:1 +error: circular modules: $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs + --> $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` - --> $DIR/circular_modules_main.rs:9:29 +error[E0425]: cannot find function `hi_str` in module `circular_modules_main` + --> $DIR/circular_modules_hello.rs:7:43 | -LL | circular_modules_hello::say_hello(); - | ^^^^^^^^^ not found in `circular_modules_hello` +LL | println!("{}", circular_modules_main::hi_str()); + | ^^^^^^ not found in `circular_modules_main` | help: consider importing this function | -LL | use circular_modules_hello::say_hello; +LL | use hi_str; | error: aborting due to 2 previous errors From 5bdf81d5fa7ada2274617ebfa97e6bd157ae5a52 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 18:42:57 +0300 Subject: [PATCH 07/27] expand: Determine module directory path directly instead of relying on span --- compiler/rustc_expand/src/module.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 55b48e4f6b254..e744ab27e8f56 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -4,8 +4,8 @@ use rustc_errors::{struct_span_err, PResult}; use rustc_parse::new_parser_from_file; use rustc_session::parse::ParseSess; use rustc_session::Session; -use rustc_span::source_map::{FileName, Span}; use rustc_span::symbol::{sym, Ident}; +use rustc_span::Span; use std::path::{self, Path, PathBuf}; @@ -64,13 +64,8 @@ crate fn parse_external_mod( // (1) ...instead, we return a dummy module. let (items, inner_span, file_path) = result.map_err(|mut err| err.emit()).unwrap_or_default(); - // Extract the directory path for submodules of the module. - let path = sess.source_map().span_to_unmapped_path(inner_span); - let mut path = match path { - FileName::Real(name) => name.into_local_path(), - other => PathBuf::from(other.to_string()), - }; - path.pop(); + // Extract the directory path for submodules of the module. + let path = file_path.parent().unwrap_or(&file_path).to_owned(); (items, inner_span, file_path, Directory { ownership, path }) } From 3d0b622ab7ae3f803d757f73f2a9a7c857d771bb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 18:58:45 +0300 Subject: [PATCH 08/27] expand: Less path cloning during module loading --- compiler/rustc_expand/src/expand.rs | 36 ++++++++++++-------- compiler/rustc_expand/src/module.rs | 52 ++++++++++++++++------------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 8d633afacf478..a81bc381c508a 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -3,7 +3,7 @@ use crate::config::StripUnconfigured; use crate::configure; use crate::hygiene::SyntaxContext; use crate::mbe::macro_rules::annotate_err_with_kind; -use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; +use crate::module::{parse_external_mod, push_directory, DirectoryOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; use rustc_ast as ast; @@ -1277,28 +1277,36 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }) } ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { - let dir = Directory { - ownership: self.cx.current_expansion.directory_ownership, - path: self.cx.current_expansion.module.dir_path.clone(), - }; - let (file_path, Directory { ownership, path }) = match mod_kind { + let (file_path, dir_path, dir_ownership) = match mod_kind { ModKind::Loaded(_, Inline::Yes, _) => { // Inline `mod foo { ... }`, but we still need to push directories. - let dir_path = push_directory(&self.cx.sess, ident, &attrs, dir); + let (dir_path, dir_ownership) = push_directory( + &self.cx.sess, + ident, + &attrs, + &self.cx.current_expansion.module, + self.cx.current_expansion.directory_ownership, + ); item.attrs = attrs; - (None, dir_path) + (None, dir_path, dir_ownership) } ModKind::Loaded(_, Inline::No, _) => { panic!("`mod` item is loaded from a file for the second time") } ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. - let (items, inner_span, file_path, dir_path) = parse_external_mod( + let ParsedExternalMod { + items, + inner_span, + file_path, + dir_path, + dir_ownership, + } = parse_external_mod( &self.cx.sess, ident, span, - &self.cx.current_expansion.module.file_path_stack, - dir, + &self.cx.current_expansion.module, + self.cx.current_expansion.directory_ownership, &mut attrs, ); @@ -1312,12 +1320,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { item.attrs = krate.attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. item = configure!(self, item); - (Some(file_path), dir_path) + (Some(file_path), dir_path, dir_ownership) } }; // Set the module info before we flat map. - let mut module = self.cx.current_expansion.module.with_dir_path(path); + let mut module = self.cx.current_expansion.module.with_dir_path(dir_path); module.mod_path.push(ident); if let Some(file_path) = file_path { module.file_path_stack.push(file_path); @@ -1326,7 +1334,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); let orig_dir_ownership = - mem::replace(&mut self.cx.current_expansion.directory_ownership, ownership); + mem::replace(&mut self.cx.current_expansion.directory_ownership, dir_ownership); let result = noop_flat_map_item(item, self); diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index e744ab27e8f56..4ba24ace8eb8c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,3 +1,4 @@ +use crate::base::ModuleData; use rustc_ast::ptr::P; use rustc_ast::{token, Attribute, Item}; use rustc_errors::{struct_span_err, PResult}; @@ -9,12 +10,6 @@ use rustc_span::Span; use std::path::{self, Path, PathBuf}; -#[derive(Clone)] -pub struct Directory { - pub path: PathBuf, - pub ownership: DirectoryOwnership, -} - #[derive(Copy, Clone)] pub enum DirectoryOwnership { Owned { @@ -38,22 +33,30 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } +crate struct ParsedExternalMod { + pub items: Vec>, + pub inner_span: Span, + pub file_path: PathBuf, + pub dir_path: PathBuf, + pub dir_ownership: DirectoryOwnership, +} + crate fn parse_external_mod( sess: &Session, id: Ident, span: Span, // The span to blame on errors. - file_path_stack: &[PathBuf], - Directory { mut ownership, path }: Directory, + module: &ModuleData, + mut dir_ownership: DirectoryOwnership, attrs: &mut Vec, -) -> (Vec>, Span, PathBuf, Directory) { +) -> ParsedExternalMod { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. - let mp = submod_path(sess, id, span, &attrs, ownership, &path)?; - ownership = mp.ownership; + let mp = submod_path(sess, id, span, &attrs, dir_ownership, &module.dir_path)?; + dir_ownership = mp.ownership; // Ensure file paths are acyclic. - error_on_circular_module(&sess.parse_sess, span, &mp.path, file_path_stack)?; + error_on_circular_module(&sess.parse_sess, span, &mp.path, &module.file_path_stack)?; // Actually parse the external file as a module. let mut parser = new_parser_from_file(&sess.parse_sess, &mp.path, Some(span)); @@ -65,9 +68,9 @@ crate fn parse_external_mod( let (items, inner_span, file_path) = result.map_err(|mut err| err.emit()).unwrap_or_default(); // Extract the directory path for submodules of the module. - let path = file_path.parent().unwrap_or(&file_path).to_owned(); + let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); - (items, inner_span, file_path, Directory { ownership, path }) + ParsedExternalMod { items, inner_span, file_path, dir_path, dir_ownership } } fn error_on_circular_module<'a>( @@ -92,11 +95,13 @@ crate fn push_directory( sess: &Session, id: Ident, attrs: &[Attribute], - Directory { mut ownership, mut path }: Directory, -) -> Directory { - if let Some(filename) = sess.first_attr_value_str_by_name(attrs, sym::path) { - path.push(&*filename.as_str()); - ownership = DirectoryOwnership::Owned { relative: None }; + module: &ModuleData, + mut dir_ownership: DirectoryOwnership, +) -> (PathBuf, DirectoryOwnership) { + let mut dir_path = module.dir_path.clone(); + if let Some(file_path) = sess.first_attr_value_str_by_name(attrs, sym::path) { + dir_path.push(&*file_path.as_str()); + dir_ownership = DirectoryOwnership::Owned { relative: None }; } else { // 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 @@ -104,15 +109,16 @@ crate fn push_directory( // // 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`. - if let DirectoryOwnership::Owned { relative } = &mut ownership { + if let DirectoryOwnership::Owned { relative } = &mut dir_ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - path.push(&*ident.as_str()); + dir_path.push(&*ident.as_str()); } } - path.push(&*id.as_str()); + dir_path.push(&*id.as_str()); } - Directory { ownership, path } + + (dir_path, dir_ownership) } fn submod_path<'a>( From 46b67aa74d8ee7d9c41983e15f8cd0f17ee27ae7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 19:06:36 +0300 Subject: [PATCH 09/27] expand: Some more consistent naming in module loading --- .../rustc_builtin_macros/src/source_util.rs | 4 +- compiler/rustc_expand/src/base.rs | 6 +- compiler/rustc_expand/src/expand.rs | 20 +++-- compiler/rustc_expand/src/module.rs | 86 +++++++++---------- 4 files changed, 59 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 98659f15a7e2f..4aafcb2fb6dfe 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -4,7 +4,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; -use rustc_expand::module::DirectoryOwnership; +use rustc_expand::module::DirOwnership; use rustc_parse::parser::{ForceCollect, Parser}; use rustc_parse::{self, new_parser_from_file}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; @@ -116,7 +116,7 @@ pub fn expand_include<'cx>( // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. let dir_path = file.parent().unwrap_or(&file).to_owned(); cx.current_expansion.module = Rc::new(cx.current_expansion.module.with_dir_path(dir_path)); - cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; + cx.current_expansion.dir_ownership = DirOwnership::Owned { relative: None }; struct ExpandResult<'a> { p: Parser<'a>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index a0632522ca0e5..f88110cf106a7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,5 @@ use crate::expand::{self, AstFragment, Invocation}; -use crate::module::DirectoryOwnership; +use crate::module::DirOwnership; use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; @@ -921,7 +921,7 @@ pub struct ExpansionData { pub id: ExpnId, pub depth: usize, pub module: Rc, - pub directory_ownership: DirectoryOwnership, + pub dir_ownership: DirOwnership, pub prior_type_ascription: Option<(Span, bool)>, } @@ -963,7 +963,7 @@ impl<'a> ExtCtxt<'a> { id: ExpnId::root(), depth: 0, module: Default::default(), - directory_ownership: DirectoryOwnership::Owned { relative: None }, + dir_ownership: DirOwnership::Owned { relative: None }, prior_type_ascription: None, }, force_mode: false, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index a81bc381c508a..eee2c6ff80869 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -3,7 +3,7 @@ use crate::config::StripUnconfigured; use crate::configure; use crate::hygiene::SyntaxContext; use crate::mbe::macro_rules::annotate_err_with_kind; -use crate::module::{parse_external_mod, push_directory, DirectoryOwnership, ParsedExternalMod}; +use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; use crate::placeholders::{placeholder, PlaceholderExpander}; use rustc_ast as ast; @@ -1246,10 +1246,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } fn visit_block(&mut self, block: &mut P) { - let old_directory_ownership = self.cx.current_expansion.directory_ownership; - self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock; + let orig_dir_ownership = mem::replace( + &mut self.cx.current_expansion.dir_ownership, + DirOwnership::UnownedViaBlock, + ); 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) -> SmallVec<[P; 1]> { @@ -1280,12 +1282,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let (file_path, dir_path, dir_ownership) = match mod_kind { ModKind::Loaded(_, Inline::Yes, _) => { // Inline `mod foo { ... }`, but we still need to push directories. - let (dir_path, dir_ownership) = push_directory( + let (dir_path, dir_ownership) = mod_dir_path( &self.cx.sess, ident, &attrs, &self.cx.current_expansion.module, - self.cx.current_expansion.directory_ownership, + self.cx.current_expansion.dir_ownership, ); item.attrs = attrs; (None, dir_path, dir_ownership) @@ -1306,7 +1308,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ident, span, &self.cx.current_expansion.module, - self.cx.current_expansion.directory_ownership, + self.cx.current_expansion.dir_ownership, &mut attrs, ); @@ -1334,12 +1336,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); let orig_dir_ownership = - mem::replace(&mut self.cx.current_expansion.directory_ownership, dir_ownership); + mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership); let result = noop_flat_map_item(item, self); // Restore the module info. - self.cx.current_expansion.directory_ownership = orig_dir_ownership; + self.cx.current_expansion.dir_ownership = orig_dir_ownership; self.cx.current_expansion.module = orig_module; result diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 4ba24ace8eb8c..607c68f82dfa9 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -11,7 +11,7 @@ use rustc_span::Span; use std::path::{self, Path, PathBuf}; #[derive(Copy, Clone)] -pub enum DirectoryOwnership { +pub enum DirOwnership { Owned { // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. relative: Option, @@ -29,8 +29,8 @@ pub struct ModulePath<'a> { // Public for rustfmt usage. pub struct ModulePathSuccess { - pub path: PathBuf, - pub ownership: DirectoryOwnership, + pub file_path: PathBuf, + pub dir_ownership: DirOwnership, } crate struct ParsedExternalMod { @@ -38,31 +38,31 @@ crate struct ParsedExternalMod { pub inner_span: Span, pub file_path: PathBuf, pub dir_path: PathBuf, - pub dir_ownership: DirectoryOwnership, + pub dir_ownership: DirOwnership, } crate fn parse_external_mod( sess: &Session, - id: Ident, + ident: Ident, span: Span, // The span to blame on errors. module: &ModuleData, - mut dir_ownership: DirectoryOwnership, + mut dir_ownership: DirOwnership, attrs: &mut Vec, ) -> ParsedExternalMod { // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. - let mp = submod_path(sess, id, span, &attrs, dir_ownership, &module.dir_path)?; - dir_ownership = mp.ownership; + let mp = mod_file_path(sess, ident, span, &attrs, &module.dir_path, dir_ownership)?; + dir_ownership = mp.dir_ownership; // Ensure file paths are acyclic. - error_on_circular_module(&sess.parse_sess, span, &mp.path, &module.file_path_stack)?; + error_on_circular_module(&sess.parse_sess, span, &mp.file_path, &module.file_path_stack)?; // 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)?; attrs.append(&mut inner_attrs); - (items, inner_span, mp.path) + (items, inner_span, mp.file_path) }; // (1) ...instead, we return a dummy module. let (items, inner_span, file_path) = result.map_err(|mut err| err.emit()).unwrap_or_default(); @@ -76,32 +76,32 @@ crate fn parse_external_mod( fn error_on_circular_module<'a>( sess: &'a ParseSess, span: Span, - path: &Path, + file_path: &Path, file_path_stack: &[PathBuf], ) -> PResult<'a, ()> { - if let Some(i) = file_path_stack.iter().position(|p| *p == path) { + if let Some(i) = file_path_stack.iter().position(|p| *p == file_path) { let mut err = String::from("circular modules: "); for p in &file_path_stack[i..] { err.push_str(&p.to_string_lossy()); err.push_str(" -> "); } - err.push_str(&path.to_string_lossy()); + err.push_str(&file_path.to_string_lossy()); return Err(sess.span_diagnostic.struct_span_err(span, &err[..])); } Ok(()) } -crate fn push_directory( +crate fn mod_dir_path( sess: &Session, - id: Ident, + ident: Ident, attrs: &[Attribute], module: &ModuleData, - mut dir_ownership: DirectoryOwnership, -) -> (PathBuf, DirectoryOwnership) { + mut dir_ownership: DirOwnership, +) -> (PathBuf, DirOwnership) { let mut dir_path = module.dir_path.clone(); if let Some(file_path) = sess.first_attr_value_str_by_name(attrs, sym::path) { dir_path.push(&*file_path.as_str()); - dir_ownership = DirectoryOwnership::Owned { relative: None }; + dir_ownership = DirOwnership::Owned { relative: None }; } else { // 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 @@ -109,27 +109,27 @@ crate fn push_directory( // // 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`. - if let DirectoryOwnership::Owned { relative } = &mut dir_ownership { + if let DirOwnership::Owned { relative } = &mut dir_ownership { if let Some(ident) = relative.take() { // Remove the relative offset. dir_path.push(&*ident.as_str()); } } - dir_path.push(&*id.as_str()); + dir_path.push(&*ident.as_str()); } (dir_path, dir_ownership) } -fn submod_path<'a>( +fn mod_file_path<'a>( sess: &'a Session, - id: Ident, + ident: Ident, span: Span, attrs: &[Attribute], - ownership: DirectoryOwnership, dir_path: &Path, + dir_ownership: DirOwnership, ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = submod_path_from_attr(sess, attrs, dir_path) { + 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. // This means that `mod foo;` declarations inside `#[path]`-included // files are siblings, @@ -137,19 +137,19 @@ fn submod_path<'a>( // Note that this will produce weirdness when a file named `foo.rs` is // `#[path]` included and contains a `mod foo;` declaration. // If you encounter this, it's your own darn fault :P - let ownership = DirectoryOwnership::Owned { relative: None }; - return Ok(ModulePathSuccess { ownership, path }); + let dir_ownership = DirOwnership::Owned { relative: None }; + return Ok(ModulePathSuccess { file_path, dir_ownership }); } - let relative = match ownership { - DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock => None, + let relative = match dir_ownership { + DirOwnership::Owned { relative } => relative, + DirOwnership::UnownedViaBlock => 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 => { + default_submod_path(&sess.parse_sess, ident, span, relative, dir_path); + match dir_ownership { + DirOwnership::Owned { .. } => Ok(result?), + DirOwnership::UnownedViaBlock => { let _ = result.map_err(|mut err| err.cancel()); error_decl_mod_in_block(&sess.parse_sess, span, path_exists, &name) } @@ -173,7 +173,7 @@ fn error_decl_mod_in_block<'a, T>( /// Derive a submodule path from the first found `#[path = "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, attrs: &[Attribute], dir_path: &Path, @@ -196,15 +196,15 @@ pub(super) fn submod_path_from_attr( // Public for rustfmt usage. pub fn default_submod_path<'a>( sess: &'a ParseSess, - id: Ident, + ident: Ident, span: Span, relative: Option, dir_path: &Path, ) -> ModulePath<'a> { // If we're in a foo.rs file instead of a mod.rs file, // we need to look for submodules in - // `./foo/.rs` and `./foo//mod.rs` rather than - // `./.rs` and `.//mod.rs`. + // `./foo/.rs` and `./foo//mod.rs` rather than + // `./.rs` and `.//mod.rs`. let relative_prefix_string; let relative_prefix = if let Some(ident) = relative { relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); @@ -213,7 +213,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 secondary_path_str = format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); @@ -224,12 +224,12 @@ pub fn default_submod_path<'a>( let result = match (default_exists, secondary_exists) { (true, false) => Ok(ModulePathSuccess { - path: default_path, - ownership: DirectoryOwnership::Owned { relative: Some(id) }, + file_path: default_path, + dir_ownership: DirOwnership::Owned { relative: Some(ident) }, }), (false, true) => Ok(ModulePathSuccess { - path: secondary_path, - ownership: DirectoryOwnership::Owned { relative: None }, + file_path: secondary_path, + dir_ownership: DirOwnership::Owned { relative: None }, }), (false, false) => { let mut err = struct_span_err!( From da3419e18c68f4eb8beb3765fc9fde4c2e689d43 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 19:49:09 +0300 Subject: [PATCH 10/27] rustc_interface: Hide some hacky details of early linting from expand --- compiler/rustc_expand/src/base.rs | 9 ++++++--- compiler/rustc_expand/src/expand.rs | 10 ++++------ compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_interface/src/passes.rs | 6 ++++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index f88110cf106a7..05c01deef5e1e 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -5,7 +5,7 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::{CanSynthesizeMissingTokens, LazyTokenStream, TokenStream}; 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_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; @@ -925,6 +925,9 @@ pub struct ExpansionData { pub prior_type_ascription: Option<(Span, bool)>, } +type OnExternModLoaded<'a> = + Option<&'a dyn Fn(Ident, Vec, Vec>, Span) -> (Vec, Vec>)>; + /// One of these is made during expansion and incrementally updated as we go; /// when a macro expansion occurs, the resulting nodes have the `backtrace() /// -> expn_data` of their expansion context stored into their span. @@ -942,7 +945,7 @@ pub struct ExtCtxt<'a> { /// Called directly after having parsed an external `mod foo;` in expansion. /// /// `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> { @@ -950,7 +953,7 @@ impl<'a> ExtCtxt<'a> { sess: &'a Session, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn ResolverExpand, - extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate, Ident)>, + extern_mod_loaded: OnExternModLoaded<'a>, ) -> ExtCtxt<'a> { ExtCtxt { sess, diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index eee2c6ff80869..a42a60fe9a52b 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1298,7 +1298,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. let ParsedExternalMod { - items, + mut items, inner_span, file_path, dir_path, @@ -1312,14 +1312,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { &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 { - 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); - item.attrs = krate.attrs; + *mod_kind = ModKind::Loaded(items, Inline::No, inner_span); + item.attrs = attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. item = configure!(self, item); (Some(file_path), dir_path, dir_ownership) diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index c5d8ff25ea94b..bcccb04c9efd3 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,5 +1,6 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] +#![feature(destructuring_assignment)] #![feature(or_patterns)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5217066bbefde..8328c07fbb730 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -302,8 +302,10 @@ fn configure_and_expand_inner<'a>( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let extern_mod_loaded = |k: &ast::Crate, ident: Ident| { - pre_expansion_lint(sess, lint_store, k, &*ident.name.as_str()) + let extern_mod_loaded = |ident: Ident, attrs, items, span| { + 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)); From 29a9ef28188e2ebdd3c56177672cd437dd11e25d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 20:11:30 +0300 Subject: [PATCH 11/27] expand: Align some code with the PR fixing inner attributes on out-of-line modules --- compiler/rustc_expand/src/expand.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index a42a60fe9a52b..dd2eaa0f3d53c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1280,8 +1280,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } ast::ItemKind::Mod(_, ref mut mod_kind) if ident != Ident::invalid() => { let (file_path, dir_path, dir_ownership) = match mod_kind { - ModKind::Loaded(_, Inline::Yes, _) => { + ModKind::Loaded(_, inline, _) => { // 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, @@ -1292,11 +1296,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { item.attrs = attrs; (None, dir_path, dir_ownership) } - ModKind::Loaded(_, Inline::No, _) => { - panic!("`mod` item is loaded from a file for the second time") - } ModKind::Unloaded => { // We have an outline `mod foo;` so we need to parse the file. + let old_attrs_len = attrs.len(); let ParsedExternalMod { mut items, inner_span, @@ -1318,8 +1320,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { *mod_kind = ModKind::Loaded(items, Inline::No, inner_span); item.attrs = attrs; - // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. - item = configure!(self, item); + if item.attrs.len() > old_attrs_len { + // If we loaded an out-of-line module and added some inner attributes, + // then we need to re-configure it. + // FIXME: Attributes also need to be recollected + // for resolution and expansion. + item = configure!(self, item); + } (Some(file_path), dir_path, dir_ownership) } }; From 1e1d574aeac3fae44dac430ecfe8086abcdf9a5f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 20:56:49 +0300 Subject: [PATCH 12/27] expand: Share some code between inline and out-of-line module treatment --- compiler/rustc_expand/src/module.rs | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 607c68f82dfa9..8f5200804e0dc 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -98,25 +98,26 @@ crate fn mod_dir_path( module: &ModuleData, mut dir_ownership: DirOwnership, ) -> (PathBuf, DirOwnership) { + if let Some(file_path) = mod_file_path_from_attr(sess, attrs, &module.dir_path) { + // For inline modules file path from `#[path]` is actually the directory path + // 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 + // paths in order to ensure that any additional module paths from inline + // `mod x { ... }` come after the relative extension. + // + // 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`. let mut dir_path = module.dir_path.clone(); - if let Some(file_path) = sess.first_attr_value_str_by_name(attrs, sym::path) { - dir_path.push(&*file_path.as_str()); - dir_ownership = DirOwnership::Owned { relative: None }; - } else { - // 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 - // `mod x { ... }` come after the relative extension. - // - // 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`. - if let DirOwnership::Owned { relative } = &mut dir_ownership { - if let Some(ident) = relative.take() { - // Remove the relative offset. - dir_path.push(&*ident.as_str()); - } + if let DirOwnership::Owned { relative } = &mut dir_ownership { + if let Some(ident) = relative.take() { + // Remove the relative offset. + dir_path.push(&*ident.as_str()); } - dir_path.push(&*ident.as_str()); } + dir_path.push(&*ident.as_str()); (dir_path, dir_ownership) } @@ -179,8 +180,7 @@ fn mod_file_path_from_attr( dir_path: &Path, ) -> Option { // 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 = path_string.as_str(); + let path_string = sess.first_attr_value_str_by_name(attrs, sym::path)?.as_str(); // On windows, the base path might have the form // `\\?\foo\bar` in which case it does not tolerate From 1fe2eb83ecfed43874b4cdf39d0be8910995dd1d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 22 Feb 2021 21:22:40 +0300 Subject: [PATCH 13/27] expand: Introduce enum for module loading errors and make module loading speculative --- compiler/rustc_expand/src/lib.rs | 1 + compiler/rustc_expand/src/module.rs | 172 +++++++++--------- .../directory_ownership/macro-expanded-mod.rs | 2 +- .../macro-expanded-mod.stderr | 2 +- .../non-inline-mod-restriction.rs | 2 +- .../non-inline-mod-restriction.stderr | 2 +- 6 files changed, 90 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index bcccb04c9efd3..1a93975533de0 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] #![feature(destructuring_assignment)] diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 8f5200804e0dc..2ec656d4895e7 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -1,7 +1,7 @@ use crate::base::ModuleData; use rustc_ast::ptr::P; 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_session::parse::ParseSess; use rustc_session::Session; @@ -19,14 +19,6 @@ pub enum DirOwnership { UnownedViaBlock, } -/// 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. pub struct ModulePathSuccess { pub file_path: PathBuf, @@ -41,6 +33,14 @@ crate struct ParsedExternalMod { pub dir_ownership: DirOwnership, } +pub enum ModError<'a> { + CircularInclusion(Vec), + ModInBlock(Option), + FileNotFound(Ident, PathBuf), + MultipleCandidates(Ident, String, String), + ParserError(DiagnosticBuilder<'a>), +} + crate fn parse_external_mod( sess: &Session, ident: Ident, @@ -50,22 +50,26 @@ crate fn parse_external_mod( attrs: &mut Vec, ) -> ParsedExternalMod { // 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. - let mp = mod_file_path(sess, ident, span, &attrs, &module.dir_path, dir_ownership)?; + let mp = mod_file_path(sess, ident, &attrs, &module.dir_path, dir_ownership)?; dir_ownership = mp.dir_ownership; // Ensure file paths are acyclic. - error_on_circular_module(&sess.parse_sess, span, &mp.file_path, &module.file_path_stack)?; + if let Some(pos) = module.file_path_stack.iter().position(|p| p == &mp.file_path) { + Err(ModError::CircularInclusion(module.file_path_stack[pos..].to_vec()))?; + } // Actually parse the external file as a module. 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); (items, inner_span, mp.file_path) }; // (1) ...instead, we return a dummy module. - let (items, inner_span, file_path) = 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. let dir_path = file_path.parent().unwrap_or(&file_path).to_owned(); @@ -73,24 +77,6 @@ crate fn parse_external_mod( ParsedExternalMod { items, inner_span, file_path, dir_path, dir_ownership } } -fn error_on_circular_module<'a>( - sess: &'a ParseSess, - span: Span, - file_path: &Path, - file_path_stack: &[PathBuf], -) -> PResult<'a, ()> { - if let Some(i) = file_path_stack.iter().position(|p| *p == file_path) { - let mut err = String::from("circular modules: "); - for p in &file_path_stack[i..] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&file_path.to_string_lossy()); - return Err(sess.span_diagnostic.struct_span_err(span, &err[..])); - } - Ok(()) -} - crate fn mod_dir_path( sess: &Session, ident: Ident, @@ -125,11 +111,10 @@ crate fn mod_dir_path( fn mod_file_path<'a>( sess: &'a Session, ident: Ident, - span: Span, attrs: &[Attribute], dir_path: &Path, dir_ownership: DirOwnership, -) -> PResult<'a, ModulePathSuccess> { +) -> Result> { 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. // This means that `mod foo;` declarations inside `#[path]`-included @@ -146,30 +131,14 @@ fn mod_file_path<'a>( DirOwnership::Owned { relative } => relative, DirOwnership::UnownedViaBlock => None, }; - let ModulePath { path_exists, name, result } = - default_submod_path(&sess.parse_sess, ident, span, relative, dir_path); + let result = default_submod_path(&sess.parse_sess, ident, relative, dir_path); match dir_ownership { - DirOwnership::Owned { .. } => Ok(result?), - DirOwnership::UnownedViaBlock => { - let _ = result.map_err(|mut err| err.cancel()); - error_decl_mod_in_block(&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); + DirOwnership::Owned { .. } => result, + DirOwnership::UnownedViaBlock => Err(ModError::ModInBlock(match result { + Ok(_) | Err(ModError::MultipleCandidates(..)) => Some(ident), + _ => None, + })), } - Err(err) } /// Derive a submodule path from the first found `#[path = "path_string"]`. @@ -197,10 +166,9 @@ fn mod_file_path_from_attr( pub fn default_submod_path<'a>( sess: &'a ParseSess, ident: Ident, - span: Span, relative: Option, dir_path: &Path, -) -> ModulePath<'a> { +) -> Result> { // If we're in a foo.rs file instead of a mod.rs file, // we need to look for submodules in // `./foo/.rs` and `./foo//mod.rs` rather than @@ -222,7 +190,7 @@ pub fn default_submod_path<'a>( let default_exists = sess.source_map().file_exists(&default_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 { file_path: default_path, dir_ownership: DirOwnership::Owned { relative: Some(ident) }, @@ -231,35 +199,65 @@ pub fn default_submod_path<'a>( file_path: secondary_path, dir_ownership: DirOwnership::Owned { relative: None }, }), - (false, false) => { - let mut err = struct_span_err!( - sess.span_diagnostic, - span, - E0583, - "file not found for module `{}`", - mod_name, - ); - err.help(&format!( - "to create the module `{}`, create file \"{}\"", - mod_name, - default_path.display(), - )); - Err(err) - } + (false, false) => Err(ModError::FileNotFound(ident, default_path)), (true, true) => { - let mut err = struct_span_err!( - sess.span_diagnostic, - span, - E0761, - "file for module `{}` found at both {} and {}", - mod_name, - default_path_str, - secondary_path_str, - ); - err.help("delete or rename one of them to remove the ambiguity"); - Err(err) + Err(ModError::MultipleCandidates(ident, default_path_str, secondary_path_str)) } - }; + } +} - ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } +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!( + diag, + span, + E0583, + "file not found for module `{}`", + ident, + ); + err.help(&format!( + "to create the module `{}`, create file \"{}\"", + ident, + default_path.display(), + )); + err + } + ModError::MultipleCandidates(ident, default_path_short, secondary_path_short) => { + let mut err = struct_span_err!( + diag, + span, + E0761, + "file for module `{}` found at both {} and {}", + ident, + default_path_short, + secondary_path_short, + ); + err.help("delete or rename one of them to remove the ambiguity"); + err + } + ModError::ParserError(err) => err, + }.emit() + } } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 9cb159603a8c5..fa81769e5a800 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -2,7 +2,7 @@ macro_rules! mod_decl { ($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 }; } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index f90419247c92b..4039728e18ac3 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -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 | LL | mod $i; diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.rs b/src/test/ui/directory_ownership/non-inline-mod-restriction.rs index af31b8a49281f..de4f816656cc4 100644 --- a/src/test/ui/directory_ownership/non-inline-mod-restriction.rs +++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.rs @@ -1,5 +1,5 @@ // Test that non-inline modules are not allowed inside blocks. 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 } diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr index d034942ca5d4c..64189bee43f6e 100644 --- a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr +++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -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 | LL | mod foo; From 1b4860ab2a70c4bc76661aa3f87d0ad09655a2f6 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Fri, 5 Mar 2021 07:12:02 -0500 Subject: [PATCH 14/27] Update compiler/rustc/src/main.rs --- compiler/rustc/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 3f03d1b68695e..8c5447a91cdca 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -36,7 +36,7 @@ fn main() { } #[used] - static _F7: unsafe extern "C" fn() = _rjem_je_zone_register(); + static _F7: unsafe extern "C" fn() = _rjem_je_zone_register; } } From 6f49aadabbd2d487f290fe393c7a69f77ebda9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 6 Mar 2021 00:00:00 +0000 Subject: [PATCH 15/27] Disable destination propagation on all mir-opt-levels --- compiler/rustc_mir/src/transform/dest_prop.rs | 5 + ..._line_doc_comment_2.DeduplicateBlocks.diff | 36 ++++--- src/test/mir-opt/dest-prop/branch.rs | 2 +- .../mir-opt/dest-prop/copy_propagation_arg.rs | 2 +- src/test/mir-opt/dest-prop/cycle.rs | 2 +- src/test/mir-opt/dest-prop/simple.rs | 2 +- src/test/mir-opt/dest-prop/union.rs | 2 +- ...line_closure_captures.foo.Inline.after.mir | 12 ++- .../inline/inline_diverging.h.Inline.diff | 17 ++-- .../inline/inline_generator.main.Inline.diff | 41 +++++--- .../issue_73223.main.PreCodegen.32bit.diff | 98 ++++++++++++------- .../issue_73223.main.PreCodegen.64bit.diff | 98 ++++++++++++------- ...ue_59352.num_to_digit.PreCodegen.after.mir | 79 ++++++++------- ...wer_intrinsics.f_u64.PreCodegen.before.mir | 4 +- .../simplify_locals.c.SimplifyLocals.diff | 7 +- 15 files changed, 260 insertions(+), 147 deletions(-) diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 0822ab73c4c67..f7568e1d929dd 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -127,6 +127,11 @@ pub struct DestinationPropagation; impl<'tcx> MirPass<'tcx> for DestinationPropagation { 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 // storage statements at the moment). if tcx.sess.mir_opt_level() < 3 { diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index b6e4469e87069..b0c97f4237818 100644 --- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -5,22 +5,26 @@ 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 _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 _4: bool; // 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 _6: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37 + let mut _3: &str; // in scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 + let mut _4: usize; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31 + let mut _5: bool; // in scope 0 at $DIR/deduplicate_blocks.rs:5:9: 5:31 + 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::::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 - let mut _7: &str; // 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 _8: &str; // in scope 1 at $DIR/deduplicate_blocks.rs:3:11: 3:23 scope 2 { } } bb0: { 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 -- _2 = transmute::<&str, &[u8]>(move _7) -> bb14; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 -+ _2 = transmute::<&str, &[u8]>(move _7) -> bb12; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 + StorageLive(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 + _3 = _1; // scope 0 at $DIR/deduplicate_blocks.rs:3:11: 3:12 + 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 // + 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()) } @@ -44,9 +48,9 @@ } bb5: { - _3 = 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 - switchInt(move _4) -> [false: bb9, otherwise: bb6]; // 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 + _5 = Ge(move _4, const 3_usize); // 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: { @@ -93,9 +97,11 @@ - bb14: { + bb12: { - _5 = Len((*_2)); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37 - _6 = Ge(move _5, const 4_usize); // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37 - switchInt(move _6) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/deduplicate_blocks.rs:4:9: 4:37 + StorageDead(_8); // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 + StorageDead(_3); // scope 0 at $DIR/deduplicate_blocks.rs:3:22: 3:23 + _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 } } diff --git a/src/test/mir-opt/dest-prop/branch.rs b/src/test/mir-opt/dest-prop/branch.rs index 7e0e40671ddb2..fffcf82b3f1d8 100644 --- a/src/test/mir-opt/dest-prop/branch.rs +++ b/src/test/mir-opt/dest-prop/branch.rs @@ -1,5 +1,5 @@ //! Tests that assignment in both branches of an `if` are eliminated. - +// compile-flags: -Zunsound-mir-opts fn val() -> i32 { 1 } diff --git a/src/test/mir-opt/dest-prop/copy_propagation_arg.rs b/src/test/mir-opt/dest-prop/copy_propagation_arg.rs index b5188a8b4b260..41796247789aa 100644 --- a/src/test/mir-opt/dest-prop/copy_propagation_arg.rs +++ b/src/test/mir-opt/dest-prop/copy_propagation_arg.rs @@ -1,6 +1,6 @@ // Check that DestinationPropagation does not propagate an assignment to a function argument // (doing so can break usages of the original argument value) - +// compile-flags: -Zunsound-mir-opts fn dummy(x: u8) -> u8 { x } diff --git a/src/test/mir-opt/dest-prop/cycle.rs b/src/test/mir-opt/dest-prop/cycle.rs index 7fbffb1335946..c9187d408675c 100644 --- a/src/test/mir-opt/dest-prop/cycle.rs +++ b/src/test/mir-opt/dest-prop/cycle.rs @@ -1,5 +1,5 @@ //! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code. - +// compile-flags: -Zunsound-mir-opts fn val() -> i32 { 1 } diff --git a/src/test/mir-opt/dest-prop/simple.rs b/src/test/mir-opt/dest-prop/simple.rs index 4655f96699874..3627d479a9aa3 100644 --- a/src/test/mir-opt/dest-prop/simple.rs +++ b/src/test/mir-opt/dest-prop/simple.rs @@ -1,5 +1,5 @@ //! 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 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] { let mut buf = [0; 1024]; diff --git a/src/test/mir-opt/dest-prop/union.rs b/src/test/mir-opt/dest-prop/union.rs index b9d831389e8b3..0ac9661a66a31 100644 --- a/src/test/mir-opt/dest-prop/union.rs +++ b/src/test/mir-opt/dest-prop/union.rs @@ -1,5 +1,5 @@ //! Tests that projections through unions cancel `DestinationPropagation`. - +// compile-flags: -Zunsound-mir-opts fn val() -> u32 { 1 } diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index a861eab39d337..a7c2c93aad23a 100644 --- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -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 => (*((*_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 - 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 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 - (_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 - _10 = (*((*_6).1: &T)); // 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 + _10 = (*((*_6).0: &i32)); // 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(_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 diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff index e945629b6138b..e2fad5b60ebfa 100644 --- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff @@ -5,18 +5,20 @@ 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 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 _8: (); // 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 _10: (); // in scope 0 at $DIR/inline-diverging.rs:22:5: 22:22 + scope 1 (inlined call_twice:: ! {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 + 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 _5: &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 _6: &fn() -> ! {sleep}; // 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 { + 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 { -+ 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 ! {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 @@ -40,12 +42,11 @@ - // mir::Constant // + span: $DIR/inline-diverging.rs:22:16: 22:21 // + literal: Const { ty: fn() -> ! {sleep}, val: Value(Scalar()) } -+ 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(_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 -+ StorageLive(_7); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 -+ _7 = const (); // scope 1 at $DIR/inline-diverging.rs:22:5: 22:22 ++ StorageLive(_9); // 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 } diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 066ac8d82d36b..fba88c83eb4f3 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -24,9 +24,12 @@ + } + } + 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 -+ let mut _8: bool; // 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 ++ debug a => _11; // 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: 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: { @@ -65,16 +68,18 @@ - // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator>, bool) -> std::ops::GeneratorState< as std::ops::Generator>::Yield, as std::ops::Generator>::Return> { as std::ops::Generator>::resume}, val: Value(Scalar()) } + 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 -+ StorageLive(_8); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 -+ StorageLive(_9); // 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 -+ 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 ++ StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 ++ StorageLive(_11); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 ++ StorageLive(_12); // scope 0 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: { + bb1: { -+ StorageDead(_9); // 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(_12); // 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(_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 @@ -89,28 +94,36 @@ + } + + bb3: { -+ _8 = 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 ++ _11 = 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 ++ 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: { -+ ((_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 + } + + 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 + } + + 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((*(_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 + } + + 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((*(_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 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index c630ab70de13b..e2ec0e82ebf09 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -6,25 +6,32 @@ let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 let mut _2: std::option::Option; // 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 mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &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 _8: bool; // 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: &i32; // 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: std::option::Option; // 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, &i32); // 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: &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 _12: bool; // 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 _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; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 scope 3 { 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 { - debug left_val => _11; // 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 - let _10: core::panicking::AssertKind; // 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 => _10; // 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 { - 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 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 - ((_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 - (_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = const main::promoted[0]; // 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 + 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: &i32 // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) // mir::Constant // + 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])) } - (_5.1: &i32) = move _6; // 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 - _12 = (_5.1: &i32); // 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 - StorageLive(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (*_11); // scope 4 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 - StorageDead(_9); // scope 4 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 - StorageDead(_8); // 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 + _8 = _20; // 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 + (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_8); // scope 3 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 3 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 + StorageLive(_10); // scope 3 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 + StorageLive(_11); // 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 + 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: { - StorageLive(_10); // 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 - StorageLive(_13); // 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 - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _11, move _12, move _13); // scope 5 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(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // 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 + _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::(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 // + 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>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } @@ -85,8 +113,12 @@ } 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 + 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 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 } diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index c630ab70de13b..e2ec0e82ebf09 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -6,25 +6,32 @@ let _1: i32; // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14 let mut _2: std::option::Option; // 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 mut _5: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _6: &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 _8: bool; // 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: &i32; // 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: std::option::Option; // 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, &i32); // 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: &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 _12: bool; // 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 _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; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _4: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 scope 3 { 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 { - debug left_val => _11; // 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 - let _10: core::panicking::AssertKind; // 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 => _10; // 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 { - 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 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 - ((_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 - (_5.0: &i32) = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _6 = const main::promoted[0]; // 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 + 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: &i32 // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, [], Some(promoted[0])) // mir::Constant // + 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])) } - (_5.1: &i32) = move _6; // 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 - _12 = (_5.1: &i32); // 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 - StorageLive(_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _9 = (*_11); // scope 4 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 - StorageDead(_9); // scope 4 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 - StorageDead(_8); // 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 + _8 = _20; // 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 + (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_8); // scope 3 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 3 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 + StorageLive(_10); // scope 3 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 + StorageLive(_11); // 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 + 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: { - StorageLive(_10); // 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 - StorageLive(_13); // 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 - core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _11, move _12, move _13); // scope 5 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(_14) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // 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 + _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::(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 // + 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>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } @@ -85,8 +113,12 @@ } 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 + 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 return; // scope 0 at $DIR/issue-73223.rs:9:2: 9:2 } diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index 0f718a720f4cc..19d161ac2b103 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -3,60 +3,67 @@ fn num_to_digit(_1: char) -> u32 { 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 _2: std::option::Option; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41 - let mut _3: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29 - let mut _4: u32; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23 - let mut _9: isize; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:23 + let mut _2: char; // in scope 0 at $DIR/issue-59352.rs:14:8: 14:11 + let mut _3: std::option::Option; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:41 + let mut _4: char; // in scope 0 at $DIR/issue-59352.rs:14:26: 14:29 + 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::::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 radix => _4; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23 - let mut _5: &std::option::Option; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23 - let _6: std::option::Option; // 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 + debug self => _2; // 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 _6: &std::option::Option; // in scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + let _7: std::option::Option; // 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::::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::::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 - let mut _8: isize; // 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 _10: isize; // in scope 3 at $DIR/issue-59352.rs:14:26: 14:50 scope 4 { debug val => _0; // in scope 4 at $DIR/issue-59352.rs:14:26: 14:50 } } bb0: { - _7 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11 - StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:8: 14:23 - _4 = const 8_u32; // scope 0 at $DIR/issue-59352.rs:14:8: 14:23 - StorageLive(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:8: 14:11 + _2 = _1; // scope 0 at $DIR/issue-59352.rs:14:8: 14:11 + StorageLive(_5); // scope 0 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 - _6 = char::methods::::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::::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 // mir::Constant // + span: $DIR/issue-59352.rs:14:8: 14:23 // + literal: Const { ty: fn(char, u32) -> std::option::Option {std::char::methods::::to_digit}, val: Value(Scalar()) } } bb1: { - StorageLive(_2); // scope 0 at $DIR/issue-59352.rs:14:26: 14:41 - StorageLive(_3); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29 - _3 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29 - _2 = char::methods::::to_digit(move _3, const 8_u32) -> bb3; // 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:41 + StorageLive(_4); // scope 0 at $DIR/issue-59352.rs:14:26: 14:29 + _4 = _1; // scope 0 at $DIR/issue-59352.rs:14:26: 14:29 + _3 = char::methods::::to_digit(move _4, const 8_u32) -> bb3; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41 // mir::Constant // + span: $DIR/issue-59352.rs:14:30: 14:38 // + literal: Const { ty: fn(char, u32) -> std::option::Option {std::char::methods::::to_digit}, val: Value(Scalar()) } } 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 goto -> bb4; // scope 0 at $DIR/issue-59352.rs:14:5: 14:63 } bb3: { - StorageDead(_3); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41 - StorageLive(_8); // 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 - switchInt(move _8) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50 + StorageDead(_4); // scope 0 at $DIR/issue-59352.rs:14:40: 14:41 + StorageLive(_10); // scope 0 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 _10) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $DIR/issue-59352.rs:14:26: 14:50 } bb4: { @@ -64,12 +71,18 @@ fn num_to_digit(_1: char) -> u32 { } bb5: { - _5 = &_6; // 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(_5); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + _6 = &_7; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + StorageDead(_8); // 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(_4); // scope 0 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(_7); // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 + 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: { @@ -90,9 +103,9 @@ fn num_to_digit(_1: char) -> u32 { } bb8: { - _0 = move ((_2 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(_2); // scope 0 at $DIR/issue-59352.rs:14:49: 14:50 + _0 = move ((_3 as Some).0: u32); // scope 3 at $DIR/issue-59352.rs:14:26: 14:50 + StorageDead(_10); // scope 0 at $DIR/issue-59352.rs:14:26: 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 } } diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir index 740a6e0edb0c4..a87d5e1f0ff8b 100644 --- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir +++ b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir @@ -2,9 +2,9 @@ fn f_u64() -> () { 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::) { // 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 mut _3: u64; // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21 scope 2 (inlined std::mem::size_of::) { // at $DIR/lower_intrinsics.rs:35:5: 35:21 @@ -12,6 +12,7 @@ fn f_u64() -> () { } 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 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 @@ -25,6 +26,7 @@ fn f_u64() -> () { bb1: { 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(_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 return; // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2 } diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff index dbac7dff9e2bb..f1718c5752c1c 100644 --- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff @@ -17,8 +17,13 @@ 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 - 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 +- 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 _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 From 069e612e73f3fabb1184d9df009ea064118fffd8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 6 Mar 2021 21:06:01 +0300 Subject: [PATCH 16/27] rustc_ast: Replace `AstLike::finalize_tokens` with a getter `tokens_mut` --- compiler/rustc_ast/src/ast.rs | 10 --- compiler/rustc_ast/src/ast_like.rs | 88 +++++++------------ compiler/rustc_builtin_macros/src/derive.rs | 12 +-- compiler/rustc_expand/src/base.rs | 18 +++- .../rustc_parse/src/parser/attr_wrapper.rs | 10 ++- 5 files changed, 60 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index de44a2031ab82..99196210e004b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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 { match &self.kind { StmtKind::Semi(_) => true, diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs index 6649cda69a0b0..a71f2ac981501 100644 --- a/compiler/rustc_ast/src/ast_like.rs +++ b/compiler/rustc_ast/src/ast_like.rs @@ -11,13 +11,7 @@ use super::{AttrVec, Attribute, Stmt, StmtKind}; pub trait AstLike: Sized { fn attrs(&self) -> &[Attribute]; fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)); - /// Called by `Parser::collect_tokens` to store the collected - /// 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!") - } + fn tokens_mut(&mut self) -> Option<&mut Option>; } impl AstLike for P { @@ -27,8 +21,8 @@ impl AstLike for P { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { (**self).visit_attrs(f); } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - (**self).finalize_tokens(tokens) + fn tokens_mut(&mut self) -> Option<&mut Option> { + (**self).tokens_mut() } } @@ -42,12 +36,12 @@ fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec)) { impl AstLike for StmtKind { fn attrs(&self) -> &[Attribute] { - match *self { - StmtKind::Local(ref local) => local.attrs(), - StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), - StmtKind::Item(ref item) => item.attrs(), + match self { + StmtKind::Local(local) => local.attrs(), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), + StmtKind::Item(item) => item.attrs(), 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), } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - let stmt_tokens = match self { - StmtKind::Local(ref mut local) => &mut local.tokens, - StmtKind::Item(ref mut item) => &mut item.tokens, - StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => &mut expr.tokens, - StmtKind::Empty => return, - StmtKind::MacCall(ref mut mac) => &mut mac.tokens, - }; - if stmt_tokens.is_none() { - *stmt_tokens = Some(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option> { + Some(match self { + StmtKind::Local(local) => &mut local.tokens, + StmtKind::Item(item) => &mut item.tokens, + StmtKind::Expr(expr) | StmtKind::Semi(expr) => &mut expr.tokens, + StmtKind::Empty => return None, + StmtKind::MacCall(mac) => &mut mac.tokens, + }) } } @@ -82,8 +73,8 @@ impl AstLike for Stmt { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { self.kind.visit_attrs(f); } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - self.kind.finalize_tokens(tokens) + fn tokens_mut(&mut self) -> Option<&mut Option> { + self.kind.tokens_mut() } } @@ -92,17 +83,13 @@ impl AstLike for Attribute { &[] } fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) {} - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - match &mut self.kind { - AttrKind::Normal(_, attr_tokens) => { - if attr_tokens.is_none() { - *attr_tokens = Some(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option> { + Some(match &mut self.kind { + AttrKind::Normal(_, tokens) => tokens, + kind @ AttrKind::DocComment(..) => { + 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 AstLike for Option { inner.visit_attrs(f); } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if let Some(inner) = self { - inner.finalize_tokens(tokens); - } + fn tokens_mut(&mut self) -> Option<&mut Option> { + self.as_mut().and_then(|inner| inner.tokens_mut()) } } @@ -152,11 +137,8 @@ macro_rules! derive_has_tokens_and_attrs { VecOrAttrVec::visit(&mut self.attrs, f) } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if self.tokens.is_none() { - self.tokens = Some(tokens); - } - + fn tokens_mut(&mut self) -> Option<&mut Option> { + Some(&mut self.tokens) } } )* } @@ -173,7 +155,9 @@ macro_rules! derive_has_attrs_no_tokens { VecOrAttrVec::visit(&mut self.attrs, f) } - fn finalize_tokens(&mut self, _tokens: LazyTokenStream) {} + fn tokens_mut(&mut self) -> Option<&mut Option> { + None + } } )* } } @@ -185,14 +169,10 @@ macro_rules! derive_has_tokens_no_attrs { &[] } - fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) { - } - - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - if self.tokens.is_none() { - self.tokens = Some(tokens); - } + fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec)) {} + fn tokens_mut(&mut self) -> Option<&mut Option> { + Some(&mut self.tokens) } } )* } diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index fad64858ce3ff..c307d8b2f5306 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,4 +1,4 @@ -use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{self as ast, token, AstLike, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; use rustc_expand::config::StripUnconfigured; @@ -59,15 +59,9 @@ impl MultiItemModifier for Expander { // 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!(), + if let Some(tokens) = item.tokens_mut() { + *tokens = None; } - .tokens = None; } ExpandResult::Ready(vec![item]) } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 929cc56294d3d..ffdb30819b193 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -81,8 +81,22 @@ impl AstLike for Annotatable { } } - fn finalize_tokens(&mut self, tokens: LazyTokenStream) { - panic!("Called finalize_tokens on an Annotatable: {:?}", tokens); + fn tokens_mut(&mut self) -> Option<&mut Option> { + 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(), + } } } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index f45d8d6c7a00e..7512f46988c91 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -72,6 +72,10 @@ impl<'a> Parser<'a> { let cursor_snapshot = self.token_cursor.clone(); 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` // 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, num_calls, cursor_snapshot, desugar_doc_comments: self.desugar_doc_comments, append_unglued_token: self.token_cursor.append_unglued_token.clone(), - }; - ret.finalize_tokens(LazyTokenStream::new(lazy_impl)); + })); + Ok(ret) } } From 5dad6c25751f577c53bd36d09f033e1c245d0806 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 6 Mar 2021 21:33:02 +0300 Subject: [PATCH 17/27] Implement built-in attribute macro `#[cfg_eval]` --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 29 ++++ compiler/rustc_builtin_macros/src/lib.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/macros/mod.rs | 12 ++ library/core/src/prelude/v1.rs | 9 ++ library/std/src/lib.rs | 1 + library/std/src/prelude/v1.rs | 9 ++ src/test/ui/proc-macro/cfg-eval-fail.rs | 9 ++ src/test/ui/proc-macro/cfg-eval-fail.stderr | 20 +++ src/test/ui/proc-macro/cfg-eval.rs | 32 +++++ src/test/ui/proc-macro/cfg-eval.stdout | 135 ++++++++++++++++++ 11 files changed, 259 insertions(+) create mode 100644 compiler/rustc_builtin_macros/src/cfg_eval.rs create mode 100644 src/test/ui/proc-macro/cfg-eval-fail.rs create mode 100644 src/test/ui/proc-macro/cfg-eval-fail.stderr create mode 100644 src/test/ui/proc-macro/cfg-eval.rs create mode 100644 src/test/ui/proc-macro/cfg-eval.stdout diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs new file mode 100644 index 0000000000000..805f9d0634c04 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -0,0 +1,29 @@ +use crate::util::check_builtin_macro_attribute; + +use rustc_ast::{self as ast, AstLike}; +use rustc_expand::base::{Annotatable, ExtCtxt}; +use rustc_expand::config::StripUnconfigured; +use rustc_span::symbol::sym; +use rustc_span::Span; + +pub fn expand( + ecx: &mut ExtCtxt<'_>, + _span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, +) -> Vec { + check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + + let mut visitor = + StripUnconfigured { sess: ecx.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. + if let Some(tokens) = item.tokens_mut() { + *tokens = None; + } + } + vec![item] +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 9a3c914337ca2..1017b23e5675a 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -24,6 +24,7 @@ mod asm; mod assert; mod cfg; mod cfg_accessible; +mod cfg_eval; mod compile_error; mod concat; mod concat_idents; @@ -89,6 +90,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { register_attr! { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, + cfg_eval: cfg_eval::expand, derive: derive::Expander, global_allocator: global_allocator::expand, test: test::expand_test, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 9663760cba189..507eb1e1cbe89 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -344,6 +344,7 @@ symbols! { cfg_attr, cfg_attr_multi, cfg_doctest, + cfg_eval, cfg_panic, cfg_sanitize, cfg_target_feature, diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 3e70ba81d4997..28fed9b8a14cd 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1452,6 +1452,18 @@ pub(crate) mod builtin { /* 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. #[rustc_builtin_macro] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index a1fbd8dec7505..5e8a8d252a238 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -81,3 +81,12 @@ pub use crate::macros::builtin::derive; )] #[doc(no_inline)] 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; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 72b86338d2c97..acdf7550fe71d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -234,6 +234,7 @@ #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_accessible)] +#![cfg_attr(not(bootstrap), feature(cfg_eval))] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index ef9aec54a4ca2..7181dc6e710e4 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -67,6 +67,15 @@ pub use core::prelude::v1::derive; #[doc(hidden)] 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, // and below to src/liballoc/prelude.rs. // Those files are duplicated rather than using glob imports diff --git a/src/test/ui/proc-macro/cfg-eval-fail.rs b/src/test/ui/proc-macro/cfg-eval-fail.rs new file mode 100644 index 0000000000000..379491f3126b0 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-fail.rs @@ -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 +} diff --git a/src/test/ui/proc-macro/cfg-eval-fail.stderr b/src/test/ui/proc-macro/cfg-eval-fail.stderr new file mode 100644 index 0000000000000..010ac006b0bee --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval-fail.stderr @@ -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 + diff --git a/src/test/ui/proc-macro/cfg-eval.rs b/src/test/ui/proc-macro/cfg-eval.rs new file mode 100644 index 0000000000000..ea397df545265 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval.rs @@ -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); +} diff --git a/src/test/ui/proc-macro/cfg-eval.stdout b/src/test/ui/proc-macro/cfg-eval.stdout new file mode 100644 index 0000000000000..b98e8961bfea7 --- /dev/null +++ b/src/test/ui/proc-macro/cfg-eval.stdout @@ -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), + }, +] From cf5246915b838b49778bc25cc68e8b1863a05362 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 27 Feb 2021 19:44:17 -0500 Subject: [PATCH 18/27] Remove Item::kind, use tagged enum. Rename variants to match --- src/librustdoc/json/conversions.rs | 52 ++++++++++++++---------------- src/librustdoc/json/mod.rs | 9 +++--- src/rustdoc-json-types/lib.rs | 48 +++++++++++++-------------- 3 files changed, 53 insertions(+), 56 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 47e4f3f0aa320..063d8aab1ec3e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -23,7 +23,6 @@ use std::collections::HashSet; impl JsonRenderer<'_> { pub(super) fn convert_item(&self, item: clean::Item) -> Option { - let item_type = ItemType::from(&item); let deprecation = item.deprecation(self.tcx); let clean::Item { source, name, attrs, kind, visibility, def_id } = item; let inner = match *kind { @@ -50,7 +49,6 @@ impl JsonRenderer<'_> { .map(rustc_ast_pretty::pprust::attribute_to_string) .collect(), deprecation: deprecation.map(from_deprecation), - kind: item_type.into(), 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) -> ItemEnum { use clean::ItemKind::*; match item { - ModuleItem(m) => ItemEnum::ModuleItem(m.into()), - ImportItem(i) => ItemEnum::ImportItem(i.into()), - StructItem(s) => ItemEnum::StructItem(s.into()), - UnionItem(u) => ItemEnum::UnionItem(u.into()), - StructFieldItem(f) => ItemEnum::StructFieldItem(f.into()), - EnumItem(e) => ItemEnum::EnumItem(e.into()), - VariantItem(v) => ItemEnum::VariantItem(v.into()), - FunctionItem(f) => ItemEnum::FunctionItem(f.into()), - ForeignFunctionItem(f) => ItemEnum::FunctionItem(f.into()), - TraitItem(t) => ItemEnum::TraitItem(t.into()), - TraitAliasItem(t) => ItemEnum::TraitAliasItem(t.into()), - MethodItem(m, _) => ItemEnum::MethodItem(from_function_method(m, true)), - TyMethodItem(m) => ItemEnum::MethodItem(from_function_method(m, false)), - ImplItem(i) => ItemEnum::ImplItem(i.into()), - StaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)), - ForeignStaticItem(s) => ItemEnum::StaticItem(from_clean_static(s, tcx)), - ForeignTypeItem => ItemEnum::ForeignTypeItem, - TypedefItem(t, _) => ItemEnum::TypedefItem(t.into()), - OpaqueTyItem(t) => ItemEnum::OpaqueTyItem(t.into()), - ConstantItem(c) => ItemEnum::ConstantItem(c.into()), - MacroItem(m) => ItemEnum::MacroItem(m.source), - ProcMacroItem(m) => ItemEnum::ProcMacroItem(m.into()), - AssocConstItem(t, s) => ItemEnum::AssocConstItem { type_: t.into(), default: s }, - AssocTypeItem(g, t) => ItemEnum::AssocTypeItem { + ModuleItem(m) => ItemEnum::Module(m.into()), + ImportItem(i) => ItemEnum::Import(i.into()), + StructItem(s) => ItemEnum::Struct(s.into()), + UnionItem(u) => ItemEnum::Union(u.into()), + StructFieldItem(f) => ItemEnum::StructField(f.into()), + EnumItem(e) => ItemEnum::Enum(e.into()), + VariantItem(v) => ItemEnum::Variant(v.into()), + FunctionItem(f) => ItemEnum::Function(f.into()), + ForeignFunctionItem(f) => ItemEnum::Function(f.into()), + TraitItem(t) => ItemEnum::Trait(t.into()), + TraitAliasItem(t) => ItemEnum::TraitAlias(t.into()), + MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true)), + TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false)), + ImplItem(i) => ItemEnum::Impl(i.into()), + StaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)), + ForeignStaticItem(s) => ItemEnum::Static(from_clean_static(s, tcx)), + ForeignTypeItem => ItemEnum::ForeignType, + TypedefItem(t, _) => ItemEnum::Typedef(t.into()), + OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into()), + ConstantItem(c) => ItemEnum::Constant(c.into()), + MacroItem(m) => ItemEnum::Macro(m.source), + ProcMacroItem(m) => ItemEnum::ProcMacro(m.into()), + AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into(), default: s }, + AssocTypeItem(g, t) => ItemEnum::AssocType { bounds: g.into_iter().map(Into::into).collect(), default: t.map(Into::into), }, @@ -185,7 +183,7 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>, name: &Option { 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(), rename: src.map(|x| x.to_string()), }, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 863610baed484..8b0c049c05bc7 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -108,8 +108,7 @@ impl JsonRenderer<'tcx> { .last() .map(Clone::clone), visibility: types::Visibility::Public, - kind: types::ItemKind::Trait, - inner: types::ItemEnum::TraitItem(trait_item.clone().into()), + inner: types::ItemEnum::Trait(trait_item.clone().into()), source: None, docs: Default::default(), links: Default::default(), @@ -158,11 +157,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let id = item.def_id; 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) - } 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) - } 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) } let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone()); diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 6188b87d2c617..01f929c5d08ad 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -76,7 +76,7 @@ pub struct Item { /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`) pub attrs: Vec, pub deprecation: Option, - pub kind: ItemKind, + #[serde(flatten)] pub inner: ItemEnum, } @@ -185,48 +185,48 @@ pub enum ItemKind { } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] -#[serde(untagged)] +#[serde(tag = "kind", content = "inner", rename_all = "snake_case")] pub enum ItemEnum { - ModuleItem(Module), - ExternCrateItem { + Module(Module), + ExternCrate { name: String, rename: Option, }, - ImportItem(Import), + Import(Import), - UnionItem(Union), - StructItem(Struct), - StructFieldItem(Type), - EnumItem(Enum), - VariantItem(Variant), + Union(Union), + Struct(Struct), + StructField(Type), + Enum(Enum), + Variant(Variant), - FunctionItem(Function), + Function(Function), - TraitItem(Trait), - TraitAliasItem(TraitAlias), - MethodItem(Method), - ImplItem(Impl), + Trait(Trait), + TraitAlias(TraitAlias), + Method(Method), + Impl(Impl), - TypedefItem(Typedef), - OpaqueTyItem(OpaqueTy), - ConstantItem(Constant), + Typedef(Typedef), + OpaqueTy(OpaqueTy), + Constant(Constant), - StaticItem(Static), + Static(Static), /// `type`s from an extern block - ForeignTypeItem, + ForeignType, /// Declarative macro_rules! macro - MacroItem(String), - ProcMacroItem(ProcMacro), + Macro(String), + ProcMacro(ProcMacro), - AssocConstItem { + AssocConst { #[serde(rename = "type")] type_: Type, /// e.g. `const X: usize = 5;` default: Option, }, - AssocTypeItem { + AssocType { bounds: Vec, /// e.g. `type X = usize;` default: Option, From ca48d1566ed54b7dd1718dfe877ef24711078538 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 4 Mar 2021 18:45:57 -0500 Subject: [PATCH 19/27] Add roundtrip testing and bump format version --- Cargo.lock | 3 +++ src/librustdoc/json/mod.rs | 2 +- src/rustdoc-json-types/Cargo.toml | 3 +++ src/rustdoc-json-types/lib.rs | 44 +++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 9e773c572cc41..955f96d690308 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "addr2line" version = "0.14.0" @@ -4568,6 +4570,7 @@ name = "rustdoc-json-types" version = "0.1.0" dependencies = [ "serde", + "serde_json", ] [[package]] diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 8b0c049c05bc7..2302dfdc80a84 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -242,7 +242,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - format_version: 4, + format_version: 5, }; let mut p = self.out_path.clone(); p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml index 7bba16a68b96c..9c02d5e645bfe 100644 --- a/src/rustdoc-json-types/Cargo.toml +++ b/src/rustdoc-json-types/Cargo.toml @@ -9,3 +9,6 @@ path = "lib.rs" [dependencies] serde = { version = "1.0", features = ["derive"] } + +[dev-dependencies] +serde_json = "1.0" diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 01f929c5d08ad..e898a01dfaf85 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -508,3 +508,47 @@ pub struct Static { pub mutable: bool, pub expr: String, } + +#[cfg(test)] +mod tests { + 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); + } +} From 83cece468e8e5b785fce0dad25807841b91f3321 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 4 Mar 2021 19:08:06 -0500 Subject: [PATCH 20/27] Move tests to own file --- src/rustdoc-json-types/lib.rs | 43 +-------------------------------- src/rustdoc-json-types/tests.rs | 40 ++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 42 deletions(-) create mode 100644 src/rustdoc-json-types/tests.rs diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index e898a01dfaf85..4e7794fe61064 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -510,45 +510,4 @@ pub struct Static { } #[cfg(test)] -mod tests { - 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); - } -} +mod tests; diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs new file mode 100644 index 0000000000000..4a5994f4c087c --- /dev/null +++ b/src/rustdoc-json-types/tests.rs @@ -0,0 +1,40 @@ +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); +} \ No newline at end of file From 70c9b370e822424de5c35b97bf49dffb5b8b9167 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Thu, 4 Mar 2021 19:44:09 -0500 Subject: [PATCH 21/27] x.py fmt --- src/rustdoc-json-types/tests.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs index 4a5994f4c087c..e7f6447ed8753 100644 --- a/src/rustdoc-json-types/tests.rs +++ b/src/rustdoc-json-types/tests.rs @@ -4,10 +4,7 @@ use super::*; fn test_struct_info_roundtrip() { let s = ItemEnum::Struct(Struct { struct_type: StructType::Plain, - generics: Generics { - params: vec![], - where_predicates: vec![] - }, + generics: Generics { params: vec![], where_predicates: vec![] }, fields_stripped: false, fields: vec![], impls: vec![], @@ -23,10 +20,7 @@ fn test_struct_info_roundtrip() { #[test] fn test_union_info_roundtrip() { let u = ItemEnum::Union(Union { - generics: Generics { - params: vec![], - where_predicates: vec![] - }, + generics: Generics { params: vec![], where_predicates: vec![] }, fields_stripped: false, fields: vec![], impls: vec![], @@ -37,4 +31,4 @@ fn test_union_info_roundtrip() { let de_u = serde_json::from_str(&union_json).unwrap(); assert_eq!(u, de_u); -} \ No newline at end of file +} From 18841ec342def87006b0535bbaa658d5fa43ba28 Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Sat, 6 Mar 2021 15:37:07 -0500 Subject: [PATCH 22/27] Revert fmt version, add rustdoc-json-types to bootstrap tests --- Cargo.lock | 2 -- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 71 ++++++++++++++++++++++++++++++++++++++ src/librustdoc/json/mod.rs | 2 +- 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 955f96d690308..328a220430601 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - [[package]] name = "addr2line" version = "0.14.0" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9317c89625d06..22a1eb6370235 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -397,6 +397,7 @@ impl<'a> Builder<'a> { test::Crate, test::CrateLibrustc, test::CrateRustdoc, + test::CrateRustdocJsonTypes, test::Linkcheck, test::TierCheck, test::Cargotest, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c0cd24dd81f01..03ae684e23fed 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -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 /// 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 diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 2302dfdc80a84..8b0c049c05bc7 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -242,7 +242,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - format_version: 5, + format_version: 4, }; let mut p = self.out_path.clone(); p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); From f9019b70865089e09507274075188f50b189a79d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 6 Mar 2021 23:37:59 +0300 Subject: [PATCH 23/27] Move full configuration logic from `rustc_expand` to `rustc_builtin_macros` This logic is applicable to two specific macros and not to the expansion infrastructure in general. --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 176 +++++++++++++++++- compiler/rustc_builtin_macros/src/derive.rs | 9 +- compiler/rustc_expand/src/config.rs | 175 +---------------- 3 files changed, 184 insertions(+), 176 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 805f9d0634c04..8cf3be33e2046 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -1,12 +1,17 @@ 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_data_structures::map_in_place::MapInPlace; 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; -pub fn expand( +crate fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, @@ -14,10 +19,11 @@ pub fn expand( ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); - let mut visitor = - StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }; + let mut visitor = CfgEval { + cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }, + }; let mut item = visitor.fully_configure(item); - if visitor.modified { + 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. @@ -27,3 +33,165 @@ pub fn expand( } vec![item] } + +crate struct CfgEval<'a> { + pub cfg: StripUnconfigured<'a>, +} + +impl CfgEval<'_> { + fn configure(&mut self, node: T) -> Option { + self.cfg.configure(node) + } + + 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(_) => {} + } + } + + 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); + } + } + _ => {} + } + } + + 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)); + } + _ => {} + } + } + + fn configure_pat(&mut self, pat: &mut P) { + if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind { + fields.flat_map_in_place(|field| self.configure(field)); + } + } + + fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { + fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); + } + + crate 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 MutVisitor for CfgEval<'_> { + fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { + self.configure_foreign_mod(foreign_mod); + mut_visit::noop_visit_foreign_mod(foreign_mod, self); + } + + fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { + self.configure_item_kind(item); + mut_visit::noop_visit_item_kind(item, self); + } + + fn visit_expr(&mut self, expr: &mut P) { + self.cfg.configure_expr(expr); + self.configure_expr_kind(&mut expr.kind); + mut_visit::noop_visit_expr(expr, self); + } + + fn filter_map_expr(&mut self, expr: P) -> Option> { + let mut expr = configure!(self, expr); + self.configure_expr_kind(&mut expr.kind); + 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) -> SmallVec<[P; 1]> { + mut_visit::noop_flat_map_item(configure!(self, item), self) + } + + fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { + mut_visit::noop_flat_map_assoc_item(configure!(self, item), self) + } + + fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { + mut_visit::noop_flat_map_assoc_item(configure!(self, item), self) + } + + fn visit_pat(&mut self, pat: &mut P) { + self.configure_pat(pat); + mut_visit::noop_visit_pat(pat, self) + } + + fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { + self.configure_fn_decl(&mut fn_decl); + mut_visit::noop_visit_fn_decl(fn_decl, self); + } +} diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index c307d8b2f5306..48b1dddfdd1e8 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,3 +1,5 @@ +use crate::cfg_eval::CfgEval; + use rustc_ast::{self as ast, token, AstLike, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; @@ -52,10 +54,11 @@ impl MultiItemModifier for Expander { // 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) { Ok(()) => { - let mut visitor = - StripUnconfigured { sess, features: ecx.ecfg.features, modified: false }; + let mut visitor = CfgEval { + cfg: StripUnconfigured { sess, features: ecx.ecfg.features, modified: false }, + }; let mut item = visitor.fully_configure(item); - if visitor.modified { + 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. diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 7d0becf1f5d85..a23731cf309a4 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -1,8 +1,5 @@ //! Conditional compilation stripping. -use crate::base::Annotatable; - -use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token::{DelimToken, Token, TokenKind}; 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::{Span, DUMMY_SP}; -use smallvec::SmallVec; - /// A folder that strips out items that do not belong in the current configuration. pub struct StripUnconfigured<'a> { pub sess: &'a Session, @@ -272,7 +267,7 @@ impl<'a> StripUnconfigured<'a> { /// Gives compiler warnings if any `cfg_attr` does not contain any /// attributes and is in the original source code. Gives compiler errors if /// the syntax of any `cfg_attr` is incorrect. - pub fn process_cfg_attrs(&mut self, node: &mut T) { + fn process_cfg_attrs(&mut self, node: &mut T) { node.visit_attrs(|attrs| { 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. - pub fn in_cfg(&self, attrs: &[Attribute]) -> bool { + fn in_cfg(&self, attrs: &[Attribute]) -> bool { attrs.iter().all(|attr| { if !is_cfg(self.sess, attr) { 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` - 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) { let mut err = feature_err( &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) { - 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 // outer stmt or expression folder before descending in here. @@ -511,117 +459,6 @@ impl<'a> StripUnconfigured<'a> { self.process_cfg_attrs(expr) } - - pub fn configure_pat(&mut self, pat: &mut P) { - 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) { - self.configure_expr(expr); - self.configure_expr_kind(&mut expr.kind); - noop_visit_expr(expr, self); - } - - fn filter_map_expr(&mut self, expr: P) -> Option> { - 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) -> SmallVec<[P; 1]> { - noop_flat_map_item(configure!(self, item), self) - } - - fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { - noop_flat_map_assoc_item(configure!(self, item), self) - } - - fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { - noop_flat_map_assoc_item(configure!(self, item), self) - } - - fn visit_pat(&mut self, pat: &mut P) { - self.configure_pat(pat); - noop_visit_pat(pat, self) - } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } } fn is_cfg(sess: &Session, attr: &Attribute) -> bool { From 10ed08f5b644e1bd521eaf7d64474a837b17a7ae Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 7 Mar 2021 00:18:51 +0300 Subject: [PATCH 24/27] cfg_eval: Configure everything through mutable visitor methods This is simpler and mirrors what invocation collector does --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 97 ++++++------------- 1 file changed, 27 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 8cf3be33e2046..efc5f5af87708 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -3,7 +3,6 @@ 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_data_structures::map_in_place::MapInPlace; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::config::StripUnconfigured; use rustc_expand::configure; @@ -43,57 +42,6 @@ impl CfgEval<'_> { self.cfg.configure(node) } - 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(_) => {} - } - } - - 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); - } - } - _ => {} - } - } - - 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)); - } - _ => {} - } - } - - fn configure_pat(&mut self, pat: &mut P) { - if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind { - fields.flat_map_in_place(|field| self.configure(field)); - } - } - - fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { - fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); - } - crate 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 @@ -139,25 +87,13 @@ impl CfgEval<'_> { } impl MutVisitor for CfgEval<'_> { - fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - self.configure_foreign_mod(foreign_mod); - mut_visit::noop_visit_foreign_mod(foreign_mod, self); - } - - fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { - self.configure_item_kind(item); - mut_visit::noop_visit_item_kind(item, self); - } - fn visit_expr(&mut self, expr: &mut P) { self.cfg.configure_expr(expr); - self.configure_expr_kind(&mut expr.kind); mut_visit::noop_visit_expr(expr, self); } fn filter_map_expr(&mut self, expr: P) -> Option> { let mut expr = configure!(self, expr); - self.configure_expr_kind(&mut expr.kind); mut_visit::noop_visit_expr(&mut expr, self); Some(expr) } @@ -185,13 +121,34 @@ impl MutVisitor for CfgEval<'_> { mut_visit::noop_flat_map_assoc_item(configure!(self, item), self) } - fn visit_pat(&mut self, pat: &mut P) { - self.configure_pat(pat); - mut_visit::noop_visit_pat(pat, self) + fn flat_map_foreign_item( + &mut self, + foreign_item: P, + ) -> SmallVec<[P; 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 visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.configure_fn_decl(&mut fn_decl); - mut_visit::noop_visit_fn_decl(fn_decl, self); + fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { + mut_visit::noop_flat_map_variant(configure!(self, variant), self) } } From 5d27728141beed69bf64212de1eb504b6b2ac0f0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 7 Mar 2021 01:11:21 +0300 Subject: [PATCH 25/27] rustc_builtin_macros: Share some more logic between `derive` and `cfg_eval` --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 19 ++++++++++------- compiler/rustc_builtin_macros/src/derive.rs | 21 +++---------------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index efc5f5af87708..eea4d785dee06 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -14,27 +14,30 @@ crate fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, - item: Annotatable, + annotatable: Annotatable, ) -> Vec { check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval); + cfg_eval(ecx, annotatable) +} +crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec { let mut visitor = CfgEval { cfg: StripUnconfigured { sess: ecx.sess, features: ecx.ecfg.features, modified: false }, }; - let mut item = visitor.fully_configure(item); + 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) = item.tokens_mut() { + if let Some(tokens) = annotatable.tokens_mut() { *tokens = None; } } - vec![item] + vec![annotatable] } -crate struct CfgEval<'a> { - pub cfg: StripUnconfigured<'a>, +struct CfgEval<'a> { + cfg: StripUnconfigured<'a>, } impl CfgEval<'_> { @@ -42,10 +45,10 @@ impl CfgEval<'_> { self.cfg.configure(node) } - crate fn fully_configure(&mut self, item: Annotatable) -> Annotatable { + 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 item { + 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()) diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 48b1dddfdd1e8..0da2c1c1021f3 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -1,9 +1,8 @@ -use crate::cfg_eval::CfgEval; +use crate::cfg_eval::cfg_eval; -use rustc_ast::{self as ast, token, AstLike, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; +use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; -use rustc_expand::config::StripUnconfigured; use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; @@ -53,21 +52,7 @@ impl MultiItemModifier for Expander { // 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) { - Ok(()) => { - let mut visitor = CfgEval { - cfg: StripUnconfigured { sess, features: ecx.ecfg.features, modified: false }, - }; - let mut item = visitor.fully_configure(item); - 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) = item.tokens_mut() { - *tokens = None; - } - } - ExpandResult::Ready(vec![item]) - } + Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)), Err(Indeterminate) => ExpandResult::Retry(item), } } From 6b2eb0e6c67407aac50577eea443a9539d9c8f9a Mon Sep 17 00:00:00 2001 From: pierwill Date: Sat, 6 Mar 2021 22:07:38 -0800 Subject: [PATCH 26/27] Edit ructc_ast_lowering docs Fixes some punctuation and formatting; also makes some small wording changes. --- compiler/rustc_ast_lowering/src/lib.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c564ada0395e9..756caf18ec5eb 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -12,7 +12,7 @@ //! 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 //! 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 //! 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 //! 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. -//! 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 //! 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. nt_to_tokenstream: NtToTokenstream, - /// Used to allocate HIR nodes + /// Used to allocate HIR nodes. arena: &'hir Arena<'hir>, /// The items being lowered are collected here. @@ -128,7 +128,7 @@ struct LoweringContext<'a, 'hir: 'a> { is_in_trait_impl: 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 /// `'_` lifetimes as well as fully elided cases where nothing is /// written at all (e.g., `&T` or `std::cell::Ref`). @@ -238,11 +238,13 @@ enum ImplTraitContext<'b, 'a> { OtherOpaqueTy { /// Set of lifetimes that this opaque type can capture, if it uses /// 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>; + /// ``` /// - /// 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 /// parameter from `A`. // 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)) } - /// Transforms `-> T` into `Future` + /// Transforms `-> T` into `Future`. fn lower_async_fn_output_type_to_future_bound( &mut self, output: &FnRetTy, From ab8995bbca73be761402585ead491111163c44d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Ho=CC=88ner?= Date: Sun, 7 Mar 2021 16:22:53 +0100 Subject: [PATCH 27/27] Generalize Write impl for Vec to Vec As discussed in the issue tracker for the wg-allocators working group[1], updating this implementation for allocator support was most likely just forgotten in the original PR. [1]: https://github.com/rust-lang/wg-allocators/issues/86 --- library/std/src/io/impls.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 00bf8b9af7384..9870cfc4c95c3 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -1,6 +1,7 @@ #[cfg(test)] mod tests; +use crate::alloc::Allocator; use crate::cmp; use crate::fmt; use crate::io::{ @@ -357,7 +358,7 @@ impl Write for &mut [u8] { /// Write is implemented for `Vec` by appending to the vector. /// The vector will grow as needed. #[stable(feature = "rust1", since = "1.0.0")] -impl Write for Vec { +impl Write for Vec { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.extend_from_slice(buf);