From 6fc18a99646ca9228b29903428e2791fd529631d Mon Sep 17 00:00:00 2001 From: Chris Gregory Date: Mon, 3 Jun 2019 22:25:20 -0700 Subject: [PATCH 01/18] Centralize panic macro documentation --- src/libcore/{macros.rs => macros/mod.rs} | 4 +- src/libcore/macros/panic.md | 47 +++++++++++++++++++++++ src/libstd/macros.rs | 48 +----------------------- 3 files changed, 49 insertions(+), 50 deletions(-) rename src/libcore/{macros.rs => macros/mod.rs} (99%) create mode 100644 src/libcore/macros/panic.md diff --git a/src/libcore/macros.rs b/src/libcore/macros/mod.rs similarity index 99% rename from src/libcore/macros.rs rename to src/libcore/macros/mod.rs index d6b6e26436f31..7f27e62fb1598 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros/mod.rs @@ -1,6 +1,4 @@ -/// Panics the current thread. -/// -/// For details, see `std::macros`. +#[doc(include = "panic.md")] #[macro_export] #[allow_internal_unstable(core_panic, // FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling diff --git a/src/libcore/macros/panic.md b/src/libcore/macros/panic.md new file mode 100644 index 0000000000000..3ecfc43be049b --- /dev/null +++ b/src/libcore/macros/panic.md @@ -0,0 +1,47 @@ +Panics the current thread. + +This allows a program to terminate immediately and provide feedback +to the caller of the program. `panic!` should be used when a program reaches +an unrecoverable state. + +This macro is the perfect way to assert conditions in example code and in +tests. `panic!` is closely tied with the `unwrap` method of both [`Option`] +and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set +to None or Err variants. + +This macro is used to inject panic into a Rust thread, causing the thread to +panic entirely. Each thread's panic can be reaped as the `Box` type, +and the single-argument form of the `panic!` macro will be the value which +is transmitted. + +[`Result`] enum is often a better solution for recovering from errors than +using the `panic!` macro. This macro should be used to avoid proceeding using +incorrect values, such as from external sources. Detailed information about +error handling is found in the [book]. + +The multi-argument form of this macro panics with a string and has the +[`format!`] syntax for building a string. + +See also the macro [`compile_error!`], for raising errors during compilation. + +[runwrap]: ../std/result/enum.Result.html#method.unwrap +[`Option`]: ../std/option/enum.Option.html#method.unwrap +[`Result`]: ../std/result/enum.Result.html +[`format!`]: ../std/macro.format.html +[`compile_error!`]: ../std/macro.compile_error.html +[book]: ../book/ch09-00-error-handling.html + +# Current implementation + +If the main thread panics it will terminate all your threads and end your +program with code `101`. + +# Examples + +```should_panic +# #![allow(unreachable_code)] +panic!(); +panic!("this is a terrible mistake!"); +panic!(4); // panic with the value of 4 to be collected elsewhere +panic!("this is a {} {message}", "fancy", message = "message"); +``` diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index cbeaf20b13adc..2df79ee97fbac 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -4,53 +4,7 @@ //! library. Each macro is available for use when linking against the standard //! library. -/// Panics the current thread. -/// -/// This allows a program to terminate immediately and provide feedback -/// to the caller of the program. `panic!` should be used when a program reaches -/// an unrecoverable state. -/// -/// This macro is the perfect way to assert conditions in example code and in -/// tests. `panic!` is closely tied with the `unwrap` method of both [`Option`] -/// and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set -/// to None or Err variants. -/// -/// This macro is used to inject panic into a Rust thread, causing the thread to -/// panic entirely. Each thread's panic can be reaped as the `Box` type, -/// and the single-argument form of the `panic!` macro will be the value which -/// is transmitted. -/// -/// [`Result`] enum is often a better solution for recovering from errors than -/// using the `panic!` macro. This macro should be used to avoid proceeding using -/// incorrect values, such as from external sources. Detailed information about -/// error handling is found in the [book]. -/// -/// The multi-argument form of this macro panics with a string and has the -/// [`format!`] syntax for building a string. -/// -/// See also the macro [`compile_error!`], for raising errors during compilation. -/// -/// [runwrap]: ../std/result/enum.Result.html#method.unwrap -/// [`Option`]: ../std/option/enum.Option.html#method.unwrap -/// [`Result`]: ../std/result/enum.Result.html -/// [`format!`]: ../std/macro.format.html -/// [`compile_error!`]: ../std/macro.compile_error.html -/// [book]: ../book/ch09-00-error-handling.html -/// -/// # Current implementation -/// -/// If the main thread panics it will terminate all your threads and end your -/// program with code `101`. -/// -/// # Examples -/// -/// ```should_panic -/// # #![allow(unreachable_code)] -/// panic!(); -/// panic!("this is a terrible mistake!"); -/// panic!(4); // panic with the value of 4 to be collected elsewhere -/// panic!("this is a {} {message}", "fancy", message = "message"); -/// ``` +#[doc(include = "../libcore/macros/panic.md")] #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] #[allow_internal_unstable(libstd_sys_internals)] From 91aadf030548214da5a8f39a1b1dbd21db125625 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Nov 2019 19:32:12 +0100 Subject: [PATCH 02/18] find_deprecation: deprecation attr may be ill-formed meta. --- src/libsyntax/attr/builtin.rs | 5 ++++- .../issue-66340-deprecated-attr-non-meta-grammar.rs | 11 +++++++++++ ...ssue-66340-deprecated-attr-non-meta-grammar.stderr | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs create mode 100644 src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 2b759c205f54e..75e0c14115955 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -665,7 +665,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, break } - let meta = attr.meta().unwrap(); + let meta = match attr.meta() { + Some(meta) => meta, + None => continue, + }; depr = match &meta.kind { MetaItemKind::Word => Some(Deprecation { since: None, note: None }), MetaItemKind::NameValue(..) => { diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs new file mode 100644 index 0000000000000..c0cde75d4caeb --- /dev/null +++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs @@ -0,0 +1,11 @@ +// The original problem in #66340 was that `find_deprecation_generic` +// called `attr.meta().unwrap()` under the assumption that the attribute +// was a well-formed `MetaItem`. + +fn main() { + foo() +} + +#[deprecated(note = test)] +//~^ ERROR expected unsuffixed literal or identifier, found `test` +fn foo() {} diff --git a/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr new file mode 100644 index 0000000000000..24178faf8de78 --- /dev/null +++ b/src/test/ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.stderr @@ -0,0 +1,8 @@ +error: expected unsuffixed literal or identifier, found `test` + --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21 + | +LL | #[deprecated(note = test)] + | ^^^^ + +error: aborting due to previous error + From 8444e1628cd5e2d7229b3176cb5b248271defe22 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 15 Nov 2019 19:41:50 +0100 Subject: [PATCH 03/18] move DIAGNOSTICS usage to rustc_driver --- Cargo.lock | 2 +- src/librustc/session/mod.rs | 9 +++--- src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/lib.rs | 16 +++++++---- src/librustc_error_codes/error_codes.rs | 3 +- src/librustc_error_codes/lib.rs | 11 ++------ src/librustc_interface/Cargo.toml | 1 - src/librustc_interface/interface.rs | 28 +++++++++---------- src/librustc_interface/util.rs | 13 +-------- src/librustdoc/core.rs | 2 +- src/librustdoc/lib.rs | 3 +- src/librustdoc/test.rs | 1 + src/test/run-make-fulldeps/issue-19371/foo.rs | 3 +- 13 files changed, 40 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb2bd3c314caa..9094461067bc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3519,6 +3519,7 @@ dependencies = [ "rustc", "rustc_codegen_utils", "rustc_data_structures", + "rustc_error_codes", "rustc_errors", "rustc_interface", "rustc_lint", @@ -3592,7 +3593,6 @@ dependencies = [ "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", - "rustc_error_codes", "rustc_errors", "rustc_incremental", "rustc_lint", diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a69584cb90ad1..63ff92b5ecb63 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1039,12 +1039,11 @@ pub fn build_session_with_source_map( let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace; - let emitter = match diagnostics_output { - DiagnosticOutput::Default => default_emitter(&sopts, registry, &source_map, None), - DiagnosticOutput::Raw(write) => { - default_emitter(&sopts, registry, &source_map, Some(write)) - } + let write_dest = match diagnostics_output { + DiagnosticOutput::Default => None, + DiagnosticOutput::Raw(write) => Some(write), }; + let emitter = default_emitter(&sopts, registry, &source_map, write_dest); let diagnostic_handler = errors::Handler::with_emitter_and_flags( emitter, diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index f1565a2bd0a5f..ff673e52b60c2 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -26,6 +26,7 @@ rustc_plugin = { path = "../librustc_plugin/deprecated" } # To get this in the s rustc_plugin_impl = { path = "../librustc_plugin" } rustc_save_analysis = { path = "../librustc_save_analysis" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } +rustc_error_codes = { path = "../librustc_error_codes" } rustc_interface = { path = "../librustc_interface" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_resolve = { path = "../librustc_resolve" } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index d4f796ee3a702..ef638464adce9 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -40,7 +40,7 @@ use rustc::ty::TyCtxt; use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported}; use rustc_metadata::locator; use rustc_codegen_utils::codegen_backend::CodegenBackend; -use errors::PResult; +use errors::{PResult, registry::Registry}; use rustc_interface::interface; use rustc_interface::util::get_codegen_sysroot; use rustc_data_structures::sync::SeqCst; @@ -140,6 +140,10 @@ impl Callbacks for TimePassesCallbacks { } } +pub fn diagnostics_registry() -> Registry { + Registry::new(&rustc_error_codes::DIAGNOSTICS) +} + // Parse args and run the compiler. This is the primary entry point for rustc. // See comments on CompilerCalls below for details about the callbacks argument. // The FileLoader provides a way to load files from sources other than the file system. @@ -182,13 +186,14 @@ pub fn run_compiler( lint_caps: Default::default(), register_lints: None, override_queries: None, + registry: diagnostics_registry(), }; callbacks.config(&mut config); config }; if let Some(ref code) = matches.opt_str("explain") { - handle_explain(code, sopts.error_format); + handle_explain(diagnostics_registry(), code, sopts.error_format); return Ok(()); } @@ -261,6 +266,7 @@ pub fn run_compiler( lint_caps: Default::default(), register_lints: None, override_queries: None, + registry: diagnostics_registry(), }; callbacks.config(&mut config); @@ -510,15 +516,13 @@ fn stdout_isatty() -> bool { } } -fn handle_explain(code: &str, - output: ErrorOutputType) { - let descriptions = rustc_interface::util::diagnostics_registry(); +fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let normalised = if code.starts_with("E") { code.to_string() } else { format!("E{0:0>4}", code) }; - match descriptions.find_description(&normalised) { + match registry.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; let mut text = String::new(); diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index ffefe51f854f5..428cecf13a3b0 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -7,8 +7,7 @@ // Error messages' format must follow the RFC 1567 available here: // https://github.com/rust-lang/rfcs/pull/1567 -crate::register_diagnostics! { - +register_diagnostics! { E0001: include_str!("./error_codes/E0001.md"), E0002: include_str!("./error_codes/E0002.md"), E0004: include_str!("./error_codes/E0004.md"), diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs index 36b1518c869b9..14210fd69ad51 100644 --- a/src/librustc_error_codes/lib.rs +++ b/src/librustc_error_codes/lib.rs @@ -1,19 +1,14 @@ -//! This library is used to gather all error codes into one place. The goal -//! being to make their maintenance easier. +//! This library is used to gather all error codes into one place, +//! the goal being to make their maintenance easier. -#[macro_export] macro_rules! register_diagnostics { - ($($ecode:ident: $message:expr,)*) => ( - $crate::register_diagnostics!{$($ecode:$message,)* ;} - ); - ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => ( pub static DIAGNOSTICS: &[(&str, &str)] = &[ $( (stringify!($ecode), $message), )* ]; $( - pub const $ecode: &str = $message; + pub const $ecode: () = (); )* $( pub const $code: () = (); diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index b16cfe9efa747..de59882bbdf95 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -34,7 +34,6 @@ rustc_errors = { path = "../librustc_errors" } rustc_plugin = { path = "../librustc_plugin", package = "rustc_plugin_impl" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } -rustc_error_codes = { path = "../librustc_error_codes" } tempfile = "3.0.5" once_cell = "1" diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index fae4eb48c4a1b..c153de7103ac2 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -11,6 +11,7 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::OnDrop; use rustc_data_structures::sync::Lrc; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_errors::registry::Registry; use rustc_parse::new_parser_from_source_str; use rustc::ty; use std::path::PathBuf; @@ -141,12 +142,16 @@ pub struct Config { /// The second parameter is local providers and the third parameter is external providers. pub override_queries: Option, &mut ty::query::Providers<'_>)>, + + /// Registry of diagnostics codes. + pub registry: Registry, } -pub fn run_compiler_in_existing_thread_pool(config: Config, f: F) -> R -where - F: FnOnce(&Compiler) -> R, -{ +pub fn run_compiler_in_existing_thread_pool( + config: Config, + f: impl FnOnce(&Compiler) -> R, +) -> R { + let registry = &config.registry; let (sess, codegen_backend, source_map) = util::create_session( config.opts, config.crate_cfg, @@ -154,6 +159,7 @@ where config.file_loader, config.input_path.clone(), config.lint_caps, + registry.clone(), ); let compiler = Compiler { @@ -171,17 +177,13 @@ where }; let _sess_abort_error = OnDrop(|| { - compiler.sess.diagnostic().print_error_count(&util::diagnostics_registry()); + compiler.sess.diagnostic().print_error_count(registry); }); f(&compiler) } -pub fn run_compiler(mut config: Config, f: F) -> R -where - F: FnOnce(&Compiler) -> R + Send, - R: Send, -{ +pub fn run_compiler(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { let stderr = config.stderr.take(); util::spawn_thread_pool( config.opts.edition, @@ -191,11 +193,7 @@ where ) } -pub fn default_thread_pool(edition: edition::Edition, f: F) -> R -where - F: FnOnce() -> R + Send, - R: Send, -{ +pub fn default_thread_pool(edition: edition::Edition, f: impl FnOnce() -> R + Send) -> R { // the 1 here is duplicating code in config.opts.debugging_opts.threads // which also defaults to 1; it ultimately doesn't matter as the default // isn't threaded, and just ignores this parameter diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index a5653a21b31bf..2b4320c04e6e5 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -15,7 +15,6 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_errors::registry::Registry; use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_resolve::{self, Resolver}; -use rustc_error_codes; use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::io::{self, Write}; @@ -37,15 +36,6 @@ use syntax_pos::edition::Edition; #[cfg(not(parallel_compiler))] use std::{thread, panic}; -pub fn diagnostics_registry() -> Registry { - let mut all_errors = Vec::new(); - all_errors.extend_from_slice(&rustc_error_codes::DIAGNOSTICS); - // FIXME: need to figure out a way to get these back in here - // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics()); - - Registry::new(&all_errors) -} - /// Adds `target_feature = "..."` cfgs for a variety of platform /// specific features (SSE, NEON etc.). /// @@ -77,9 +67,8 @@ pub fn create_session( file_loader: Option>, input_path: Option, lint_caps: FxHashMap, + descriptions: Registry, ) -> (Lrc, Lrc>, Lrc) { - let descriptions = diagnostics_registry(); - let loader = file_loader.unwrap_or(box RealFileLoader); let source_map = Lrc::new(SourceMap::with_file_loader( loader, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a40325448b10b..d6f6751439452 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -21,7 +21,6 @@ use syntax::feature_gate::UnstableFeatures; use syntax::json::JsonEmitter; use syntax::symbol::sym; use syntax_pos::DUMMY_SP; -use errors; use errors::emitter::{Emitter, EmitterWriter}; use std::cell::RefCell; @@ -341,6 +340,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt lint_caps, register_lints: None, override_queries: None, + registry: rustc_driver::diagnostics_registry(), }; interface::run_compiler_in_existing_thread_pool(config, |compiler| { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4f102dbf128f4..8bfaf98f0867e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,8 +23,9 @@ extern crate getopts; extern crate env_logger; extern crate rustc; extern crate rustc_data_structures; -extern crate rustc_index; extern crate rustc_driver; +extern crate rustc_error_codes; +extern crate rustc_index; extern crate rustc_resolve; extern crate rustc_lint; extern crate rustc_interface; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index c483f6fb4770f..98e18d666f150 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -80,6 +80,7 @@ pub fn run(options: Options) -> i32 { lint_caps: Default::default(), register_lints: None, override_queries: None, + registry: rustc_driver::diagnostics_registry(), }; let mut test_args = options.test_args.clone(); diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 9f1850dfb4c90..f9ecff2abaa83 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -2,7 +2,7 @@ extern crate rustc; extern crate rustc_interface; -extern crate rustc_driver as _; +extern crate rustc_driver; extern crate syntax; use rustc::session::DiagnosticOutput; @@ -61,6 +61,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { lint_caps: Default::default(), register_lints: None, override_queries: None, + registry: rustc_driver::diagnostics_registry(), }; interface::run_compiler(config, |compiler| { From e85f40cbd202b8b87c5f2846f369bfa36d371bcb Mon Sep 17 00:00:00 2001 From: Magnus Ulimoen Date: Sat, 16 Nov 2019 08:22:40 +0100 Subject: [PATCH 04/18] add missing 'static lifetime in docs The example refers to a static lifetime parameter that can be elided. This parameter is not included, meaning lifetime elision is not shown. --- src/libstd/keyword_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index d025a7d16f256..b0baf36308e44 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -126,7 +126,7 @@ mod break_keyword { } /// look like this: /// /// ```rust -/// const WORDS: &str = "hello rust!"; +/// const WORDS: &'static str = "hello rust!"; /// ``` /// /// Thanks to static lifetime elision, you usually don't have to explicitly use 'static: From 52d7246a9368048154b9cb666f4b7a79377bd17d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 Nov 2019 09:27:06 +0100 Subject: [PATCH 05/18] miri panic_unwind: fix hack for SEH platforms --- src/libpanic_unwind/lib.rs | 5 ----- src/libpanic_unwind/miri.rs | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 5f345c2133f6b..d97a7a8a87d8d 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -39,11 +39,6 @@ cfg_if::cfg_if! { if #[cfg(miri)] { #[path = "miri.rs"] mod imp; - // On MSVC we need the SEH lang items as well... - // This should match the conditions of the `seh.rs` import below. - #[cfg(all(target_env = "msvc", not(target_arch = "aarch64")))] - #[allow(unused)] - mod seh; } else if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod imp; diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs index 254a9383b4223..7fdbf46ea487d 100644 --- a/src/libpanic_unwind/miri.rs +++ b/src/libpanic_unwind/miri.rs @@ -1,3 +1,5 @@ +#![allow(nonstandard_style)] + use core::any::Any; use alloc::boxed::Box; @@ -13,7 +15,6 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { Box::from_raw(ptr) } - // This is required by the compiler to exist (e.g., it's a lang item), // but is never used by Miri. Therefore, we just use a stub here #[lang = "eh_personality"] @@ -21,3 +22,26 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box { fn rust_eh_personality() { unsafe { core::intrinsics::abort() } } + +// The rest is required on *some* targets to exist (specifically, MSVC targets that use SEH). +// We just add it on all targets. Copied from `seh.rs`. +#[repr(C)] +pub struct _TypeDescriptor { + pub pVFTable: *const u8, + pub spare: *mut u8, + pub name: [u8; 11], +} + +extern "C" { + #[link_name = "\x01??_7type_info@@6B@"] + static TYPE_INFO_VTABLE: *const u8; +} + +const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; + +#[cfg_attr(not(test), lang = "eh_catch_typeinfo")] +static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { + pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, + spare: core::ptr::null_mut(), + name: TYPE_NAME, +}; From e8ff4656fcfc4df97f5d0124c999cb5392a15dcb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 Nov 2019 09:37:45 +0100 Subject: [PATCH 06/18] avoid linking errors --- src/libpanic_unwind/miri.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libpanic_unwind/miri.rs b/src/libpanic_unwind/miri.rs index 7fdbf46ea487d..f26c42fd4bcba 100644 --- a/src/libpanic_unwind/miri.rs +++ b/src/libpanic_unwind/miri.rs @@ -32,16 +32,11 @@ pub struct _TypeDescriptor { pub name: [u8; 11], } -extern "C" { - #[link_name = "\x01??_7type_info@@6B@"] - static TYPE_INFO_VTABLE: *const u8; -} - const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; #[cfg_attr(not(test), lang = "eh_catch_typeinfo")] static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { - pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, + pVFTable: core::ptr::null(), spare: core::ptr::null_mut(), name: TYPE_NAME, }; From bd63c594c25e559f49c52169ad4be0778c4c4d12 Mon Sep 17 00:00:00 2001 From: cosine Date: Sat, 16 Nov 2019 07:12:37 -0500 Subject: [PATCH 07/18] Use "field is never read" instead of "field is never used" --- src/librustc_passes/dead.rs | 2 +- src/test/ui/lint/dead-code/lint-dead-code-4.rs | 10 +++++----- src/test/ui/lint/dead-code/lint-dead-code-4.stderr | 10 +++++----- src/test/ui/union/union-fields-1.rs | 8 ++++---- src/test/ui/union/union-fields-1.stderr | 8 ++++---- src/test/ui/union/union-lint-dead-code.rs | 2 +- src/test/ui/union/union-lint-dead-code.stderr | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 2aeec029cc334..db661e7f4d2a5 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -631,7 +631,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_struct_field(&mut self, field: &'tcx hir::StructField) { if self.should_warn_about_field(&field) { - self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "used"); + self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "read"); } intravisit::walk_struct_field(self, field); } diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.rs b/src/test/ui/lint/dead-code/lint-dead-code-4.rs index 3f4a9e210401e..8bcb1e5ba8c0d 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.rs +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.rs @@ -4,7 +4,7 @@ struct Foo { x: usize, - b: bool, //~ ERROR: field is never used + b: bool, //~ ERROR: field is never read } fn field_read(f: Foo) -> usize { @@ -36,8 +36,8 @@ enum IJK { I, //~ ERROR variant is never constructed J { a: String, - b: i32, //~ ERROR field is never used - c: i32, //~ ERROR field is never used + b: i32, //~ ERROR field is never read + c: i32, //~ ERROR field is never read }, K //~ ERROR variant is never constructed @@ -58,9 +58,9 @@ fn field_match_in_patterns(b: XYZ) -> String { } struct Bar { - x: usize, //~ ERROR: field is never used + x: usize, //~ ERROR: field is never read b: bool, - c: bool, //~ ERROR: field is never used + c: bool, //~ ERROR: field is never read _guard: () } diff --git a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr index 8eaf789f8f793..cc00fa4e42afd 100644 --- a/src/test/ui/lint/dead-code/lint-dead-code-4.stderr +++ b/src/test/ui/lint/dead-code/lint-dead-code-4.stderr @@ -1,4 +1,4 @@ -error: field is never used: `b` +error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:7:5 | LL | b: bool, @@ -38,13 +38,13 @@ error: variant is never constructed: `I` LL | I, | ^ -error: field is never used: `b` +error: field is never read: `b` --> $DIR/lint-dead-code-4.rs:39:9 | LL | b: i32, | ^^^^^^ -error: field is never used: `c` +error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:40:9 | LL | c: i32, @@ -56,13 +56,13 @@ error: variant is never constructed: `K` LL | K | ^ -error: field is never used: `x` +error: field is never read: `x` --> $DIR/lint-dead-code-4.rs:61:5 | LL | x: usize, | ^^^^^^^^ -error: field is never used: `c` +error: field is never read: `c` --> $DIR/lint-dead-code-4.rs:63:5 | LL | c: bool, diff --git a/src/test/ui/union/union-fields-1.rs b/src/test/ui/union/union-fields-1.rs index 6d76e18cc7e06..edef41de159ba 100644 --- a/src/test/ui/union/union-fields-1.rs +++ b/src/test/ui/union/union-fields-1.rs @@ -3,19 +3,19 @@ union U1 { a: u8, // should not be reported b: u8, // should not be reported - c: u8, //~ ERROR field is never used + c: u8, //~ ERROR field is never read } union U2 { - a: u8, //~ ERROR field is never used + a: u8, //~ ERROR field is never read b: u8, // should not be reported c: u8, // should not be reported } -union NoDropLike { a: u8 } //~ ERROR field is never used +union NoDropLike { a: u8 } //~ ERROR field is never read union U { a: u8, // should not be reported b: u8, // should not be reported - c: u8, //~ ERROR field is never used + c: u8, //~ ERROR field is never read } type A = U; diff --git a/src/test/ui/union/union-fields-1.stderr b/src/test/ui/union/union-fields-1.stderr index f848db726f9ef..be145c9496c6c 100644 --- a/src/test/ui/union/union-fields-1.stderr +++ b/src/test/ui/union/union-fields-1.stderr @@ -1,4 +1,4 @@ -error: field is never used: `c` +error: field is never read: `c` --> $DIR/union-fields-1.rs:6:5 | LL | c: u8, @@ -10,19 +10,19 @@ note: lint level defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: field is never used: `a` +error: field is never read: `a` --> $DIR/union-fields-1.rs:9:5 | LL | a: u8, | ^^^^^ -error: field is never used: `a` +error: field is never read: `a` --> $DIR/union-fields-1.rs:13:20 | LL | union NoDropLike { a: u8 } | ^^^^^ -error: field is never used: `c` +error: field is never read: `c` --> $DIR/union-fields-1.rs:18:5 | LL | c: u8, diff --git a/src/test/ui/union/union-lint-dead-code.rs b/src/test/ui/union/union-lint-dead-code.rs index cb6415c18a83b..ae5337c618a75 100644 --- a/src/test/ui/union/union-lint-dead-code.rs +++ b/src/test/ui/union/union-lint-dead-code.rs @@ -2,7 +2,7 @@ union Foo { x: usize, - b: bool, //~ ERROR: field is never used + b: bool, //~ ERROR: field is never read _unused: u16, } diff --git a/src/test/ui/union/union-lint-dead-code.stderr b/src/test/ui/union/union-lint-dead-code.stderr index 79c38a4681445..5fe26dc253844 100644 --- a/src/test/ui/union/union-lint-dead-code.stderr +++ b/src/test/ui/union/union-lint-dead-code.stderr @@ -1,4 +1,4 @@ -error: field is never used: `b` +error: field is never read: `b` --> $DIR/union-lint-dead-code.rs:5:5 | LL | b: bool, From 857574379310d6ca70d3d44dbf00cc45b23e7eb8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 12 Nov 2019 21:22:16 +0300 Subject: [PATCH 08/18] rustc_plugin: Remove `Registry::register_attribute` --- src/librustc/hir/def.rs | 6 +--- src/librustc/session/mod.rs | 5 +-- src/librustc_interface/passes.rs | 9 +---- src/librustc_lint/unused.rs | 20 +---------- src/librustc_plugin/registry.rs | 13 ------- src/librustc_resolve/diagnostics.rs | 9 ----- src/librustc_resolve/lib.rs | 8 +---- src/librustc_resolve/macros.rs | 7 ---- .../ui-fulldeps/auxiliary/attr-plugin-test.rs | 3 -- .../auxiliary/issue-40001-plugin.rs | 15 +++----- src/test/ui-fulldeps/issue-40001.rs | 5 +-- .../ui-fulldeps/plugin-attr-register-deny.rs | 21 ------------ .../plugin-attr-register-deny.stderr | 34 ------------------- 13 files changed, 12 insertions(+), 143 deletions(-) delete mode 100644 src/test/ui-fulldeps/plugin-attr-register-deny.rs delete mode 100644 src/test/ui-fulldeps/plugin-attr-register-deny.stderr diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 025494e3fd7be..a1ad11580dbb7 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -42,8 +42,6 @@ pub enum NonMacroAttrKind { DeriveHelper, /// Single-segment custom attribute registered with `#[register_attr]`. Registered, - /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`). - LegacyPluginHelper, } #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] @@ -330,7 +328,6 @@ impl NonMacroAttrKind { NonMacroAttrKind::Tool => "tool attribute", NonMacroAttrKind::DeriveHelper => "derive helper attribute", NonMacroAttrKind::Registered => "explicitly registered attribute", - NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute", } } @@ -345,8 +342,7 @@ impl NonMacroAttrKind { pub fn is_used(self) -> bool { match self { NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true, - NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered | - NonMacroAttrKind::LegacyPluginHelper => false, + NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false, } } } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 4fbc8da9cbf02..cfcdb2340304a 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -21,11 +21,10 @@ use errors::emitter::{Emitter, EmitterWriter}; use errors::emitter::HumanReadableErrorType; use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; use syntax::edition::Edition; -use syntax::feature_gate::{self, AttributeType}; +use syntax::feature_gate; use errors::json::JsonEmitter; use syntax::source_map; use syntax::sess::{ParseSess, ProcessCfgMod}; -use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; @@ -79,7 +78,6 @@ pub struct Session { /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, pub plugin_llvm_passes: OneThread>>, - pub plugin_attributes: Lock>, pub crate_types: Once>, /// The `crate_disambiguator` is constructed out of all the `-C metadata` /// arguments passed to the compiler. Its value together with the crate-name @@ -1166,7 +1164,6 @@ fn build_session_( working_dir, one_time_diagnostics: Default::default(), plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), - plugin_attributes: Lock::new(Vec::new()), crate_types: Once::new(), crate_disambiguator: Once::new(), features: Once::new(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 83b936dd7aa2c..86d58bfe8bdac 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -240,15 +240,8 @@ pub fn register_plugins<'a>( } }); - let Registry { - syntax_exts, - llvm_passes, - attributes, - .. - } = registry; - + let Registry { syntax_exts, llvm_passes, .. } = registry; *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; - *sess.plugin_attributes.borrow_mut() = attributes; Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store))) } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 642b8e3279d66..9f293bdaa105e 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -309,29 +309,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { } } - let plugin_attributes = cx.sess().plugin_attributes.borrow(); - for &(name, ty) in plugin_attributes.iter() { - if ty == AttributeType::Whitelisted && attr.check_name(name) { - debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty); - break; - } - } - - let name = attr.name_or_empty(); if !attr::is_used(attr) { debug!("emitting warning for: {:?}", attr); cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); // Is it a builtin attribute that must be used at the crate level? - let known_crate = attr_info.map(|&&(_, ty, ..)| { - ty == AttributeType::CrateLevel - }).unwrap_or(false); - - // Has a plugin registered this attribute as one that must be used at - // the crate level? - let plugin_crate = plugin_attributes.iter() - .find(|&&(x, t)| name == x && AttributeType::CrateLevel == t) - .is_some(); - if known_crate || plugin_crate { + if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) { let msg = match attr.style { ast::AttrStyle::Outer => { "crate-level attribute should be an inner attribute: add an exclamation \ diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 3f4b87a97c773..aa5ea80f0b0e4 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -7,7 +7,6 @@ use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExten use syntax_expand::base::MacroExpanderFn; use syntax::symbol::Symbol; use syntax::ast; -use syntax::feature_gate::AttributeType; use syntax_pos::Span; use std::borrow::ToOwned; @@ -39,9 +38,6 @@ pub struct Registry<'a> { #[doc(hidden)] pub llvm_passes: Vec, - - #[doc(hidden)] - pub attributes: Vec<(Symbol, AttributeType)>, } impl<'a> Registry<'a> { @@ -54,7 +50,6 @@ impl<'a> Registry<'a> { krate_span, syntax_exts: vec![], llvm_passes: vec![], - attributes: vec![], } } @@ -98,12 +93,4 @@ impl<'a> Registry<'a> { pub fn register_llvm_pass(&mut self, name: &str) { self.llvm_passes.push(name.to_owned()); } - - /// Register an attribute with an attribute type. - /// - /// `Whitelisted` attributes will additionally not trigger the `unused_attribute` - /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate. - pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) { - self.attributes.push((name, ty)); - } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 1ebe9b5e120f4..97c00c576e6f7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -428,15 +428,6 @@ impl<'a> Resolver<'a> { })); } } - Scope::LegacyPluginHelpers => { - let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper); - if filter_fn(res) { - let plugin_attributes = this.session.plugin_attributes.borrow(); - suggestions.extend(plugin_attributes.iter().map(|(name, _)| { - TypoSuggestion::from_res(*name, res) - })); - } - } Scope::ExternPrelude => { suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| { let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 47e8cf80a05bf..350039736a068 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -104,7 +104,6 @@ enum Scope<'a> { RegisteredAttrs, MacroUsePrelude, BuiltinAttrs, - LegacyPluginHelpers, ExternPrelude, ToolPrelude, StdLibPrelude, @@ -1462,9 +1461,6 @@ impl<'a> Resolver<'a> { // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled). // 4c. Standard library prelude (de-facto closed, controlled). // 6. Language prelude: builtin attributes (closed, controlled). - // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers, - // but introduced by legacy plugins using `register_attribute`. Priority is somewhere - // in prelude, not sure where exactly (creates ambiguities with any other prelude names). let rust_2015 = ident.span.rust_2015(); let (ns, is_absolute_path) = match scope_set { @@ -1491,7 +1487,6 @@ impl<'a> Resolver<'a> { Scope::RegisteredAttrs => use_prelude, Scope::MacroUsePrelude => use_prelude || rust_2015, Scope::BuiltinAttrs => true, - Scope::LegacyPluginHelpers => use_prelude || rust_2015, Scope::ExternPrelude => use_prelude || is_absolute_path, Scope::ToolPrelude => use_prelude, Scope::StdLibPrelude => use_prelude || ns == MacroNS, @@ -1540,8 +1535,7 @@ impl<'a> Resolver<'a> { } Scope::RegisteredAttrs => Scope::MacroUsePrelude, Scope::MacroUsePrelude => Scope::StdLibPrelude, - Scope::BuiltinAttrs => Scope::LegacyPluginHelpers, - Scope::LegacyPluginHelpers => break, // nowhere else to search + Scope::BuiltinAttrs => break, // nowhere else to search Scope::ExternPrelude if is_absolute_path => break, Scope::ExternPrelude => Scope::ToolPrelude, Scope::ToolPrelude => Scope::StdLibPrelude, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2d125a459c86b..a8ace56f4fcb4 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -590,13 +590,6 @@ impl<'a> Resolver<'a> { } else { Err(Determinacy::Determined) } - Scope::LegacyPluginHelpers => if this.session.plugin_attributes.borrow().iter() - .any(|(name, _)| ident.name == *name) { - let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper); - ok(res, DUMMY_SP, this.arenas) - } else { - Err(Determinacy::Determined) - } Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) { Some(binding) => Ok((binding, Flags::empty())), None => Err(Determinacy::determined( diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index 3d08c1c9eeefa..b17c6a939655c 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -14,9 +14,6 @@ use syntax::symbol::Symbol; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal); - reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel); - reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted); reg.register_syntax_extension( Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition()) ); diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 6b914f501ca79..68ea10fe735ad 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -5,25 +5,17 @@ extern crate rustc; extern crate rustc_driver; extern crate syntax; -extern crate syntax_expand; use rustc_driver::plugin::Registry; -use syntax::attr; -use syntax_expand::base::*; -use syntax::feature_gate::AttributeType::Whitelisted; -use syntax::symbol::Symbol; - -use rustc::hir; -use rustc::hir::intravisit; -use hir::Node; +use rustc::hir::{self, intravisit, Node}; use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext}; +use syntax::print::pprust; use syntax::source_map; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]); reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass); - reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted); } declare_lint! { @@ -48,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass { _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)), }; - if !attr::contains_name(&item.attrs, Symbol::intern("whitelisted_attr")) { + let whitelisted = |attr| pprust::attribute_to_string(attr).contains("whitelisted_attr"); + if !item.attrs.iter().any(whitelisted) { cx.span_lint(MISSING_WHITELISTED_ATTR, span, "Missing 'whitelisted_attr' attribute"); } diff --git a/src/test/ui-fulldeps/issue-40001.rs b/src/test/ui-fulldeps/issue-40001.rs index e0dc3d6a45b53..c3f98197250d1 100644 --- a/src/test/ui-fulldeps/issue-40001.rs +++ b/src/test/ui-fulldeps/issue-40001.rs @@ -2,8 +2,9 @@ // aux-build:issue-40001-plugin.rs // ignore-stage1 -#![feature(plugin)] +#![feature(plugin, register_tool)] #![plugin(issue_40001_plugin)] //~ WARNING compiler plugins are deprecated +#![register_tool(plugin)] -#[whitelisted_attr] +#[plugin::whitelisted_attr] fn main() {} diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.rs b/src/test/ui-fulldeps/plugin-attr-register-deny.rs deleted file mode 100644 index dd7c009388e2c..0000000000000 --- a/src/test/ui-fulldeps/plugin-attr-register-deny.rs +++ /dev/null @@ -1,21 +0,0 @@ -// aux-build:attr-plugin-test.rs -// ignore-stage1 - -#![feature(plugin)] -#![plugin(attr_plugin_test)] -//~^ WARN use of deprecated attribute `plugin` -#![deny(unused_attributes)] - -#[baz] -fn baz() { } // no error - -#[foo] -pub fn main() { - //~^^ ERROR unused - #[bar] - fn inner() {} - //~^^ ERROR crate - //~^^^ ERROR unused - baz(); - inner(); -} diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr deleted file mode 100644 index 8d95d6ff2d89f..0000000000000 --- a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr +++ /dev/null @@ -1,34 +0,0 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 - --> $DIR/plugin-attr-register-deny.rs:5:1 - | -LL | #![plugin(attr_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version - | - = note: `#[warn(deprecated)]` on by default - -error: unused attribute - --> $DIR/plugin-attr-register-deny.rs:15:5 - | -LL | #[bar] - | ^^^^^^ - | -note: lint level defined here - --> $DIR/plugin-attr-register-deny.rs:7:9 - | -LL | #![deny(unused_attributes)] - | ^^^^^^^^^^^^^^^^^ - -error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/plugin-attr-register-deny.rs:15:5 - | -LL | #[bar] - | ^^^^^^ - -error: unused attribute - --> $DIR/plugin-attr-register-deny.rs:12:1 - | -LL | #[foo] - | ^^^^^^ - -error: aborting due to 3 previous errors - From 266f5471272532989332117e8a2e0bacb5b94ccf Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 9 Nov 2019 22:05:20 +0300 Subject: [PATCH 09/18] ast: Keep `extern` qualifiers in functions more precisely --- src/librustc/hir/lowering.rs | 2 +- src/librustc/hir/lowering/item.rs | 12 +++++-- src/librustc_parse/parser/item.rs | 35 +++++++++++-------- src/librustc_parse/parser/mod.rs | 24 +++++-------- src/librustc_parse/parser/ty.rs | 4 +-- src/librustc_save_analysis/sig.rs | 17 ++++----- src/libsyntax/ast.rs | 27 ++++++++------ src/libsyntax/feature_gate/check.rs | 16 ++++++--- src/libsyntax/mut_visit.rs | 4 +-- src/libsyntax/print/pprust.rs | 22 ++++++++---- src/libsyntax_ext/deriving/generic/mod.rs | 7 ++-- src/test/ui/proc-macro/span-preservation.rs | 10 ++---- .../ui/proc-macro/span-preservation.stderr | 26 ++++++++------ 13 files changed, 118 insertions(+), 88 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ef6a6ae23dc2f..12f6f66e96b50 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1219,7 +1219,7 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::disallowed(), ), unsafety: f.unsafety, - abi: this.lower_abi(f.abi), + abi: this.lower_extern(f.ext), decl: this.lower_fn_decl(&f.decl, None, false, None), param_names: this.lower_fn_params_to_names(&f.decl), })) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 4cd42927868d7..2dc7e014445d1 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -735,7 +735,7 @@ impl LoweringContext<'_> { fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod { hir::ForeignMod { - abi: self.lower_abi(fm.abi), + abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)), items: fm.items .iter() .map(|x| self.lower_foreign_item(x)) @@ -1283,7 +1283,7 @@ impl LoweringContext<'_> { unsafety: h.unsafety, asyncness: self.lower_asyncness(h.asyncness.node), constness: h.constness.node, - abi: self.lower_abi(h.abi), + abi: self.lower_extern(h.ext), } } @@ -1294,6 +1294,14 @@ impl LoweringContext<'_> { }) } + pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi { + match ext { + Extern::None => abi::Abi::Rust, + Extern::Implicit => abi::Abi::C, + Extern::Explicit(abi) => self.lower_abi(abi), + } + } + fn error_on_invalid_abi(&self, abi: Abi) { struct_span_err!( self.sess, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 7309916987989..fe86d03c6e782 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -114,7 +114,7 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi, + ext: Extern::from_abi(abi), }; return self.parse_item_fn(lo, vis, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { @@ -143,14 +143,14 @@ impl<'a> Parser<'a> { if self.check_keyword(kw::Extern) { self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span)); } - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.bump(); // `fn` let header = FnHeader { unsafety, asyncness: respan(const_span, IsAsync::NotAsync), constness: respan(const_span, Constness::Const), - abi, + ext, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -193,7 +193,7 @@ impl<'a> Parser<'a> { unsafety, asyncness, constness: respan(fn_span, Constness::NotConst), - abi: Abi::new(sym::Rust, fn_span), + ext: Extern::None, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -230,7 +230,7 @@ impl<'a> Parser<'a> { unsafety: Unsafety::Normal, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi: Abi::new(sym::Rust, fn_span), + ext: Extern::None, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -242,14 +242,14 @@ impl<'a> Parser<'a> { self.bump(); // `unsafe` // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. self.check(&token::OpenDelim(token::Brace)); - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; let fn_span = self.prev_span; let header = FnHeader { unsafety: Unsafety::Unsafe, asyncness: respan(fn_span, IsAsync::NotAsync), constness: respan(fn_span, Constness::NotConst), - abi, + ext, }; return self.parse_item_fn(lo, vis, attrs, header); } @@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, lo: Span, - abi: Abi, + abi: Option, visibility: Visibility, mut attrs: Vec, extern_sp: Span, @@ -1775,9 +1775,16 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { + let is_c_abi = match header.ext { + ast::Extern::None => false, + ast::Extern::Implicit => true, + ast::Extern::Explicit(abi) => abi.symbol == sym::C, + }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, - allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe, + // FIXME: Parsing should not depend on ABI or unsafety and + // the variadic parameter should always be parsed. + allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe, is_name_required: |_| true, })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; @@ -1905,11 +1912,11 @@ impl<'a> Parser<'a> { } let asyncness = respan(self.prev_span, asyncness); let unsafety = self.parse_unsafety(); - let (constness, unsafety, abi) = if is_const_fn { - (respan(const_span, Constness::Const), unsafety, Abi::default()) + let (constness, unsafety, ext) = if is_const_fn { + (respan(const_span, Constness::Const), unsafety, Extern::None) } else { - let abi = self.parse_extern_abi()?; - (respan(self.prev_span, Constness::NotConst), unsafety, abi) + let ext = self.parse_extern()?; + (respan(self.prev_span, Constness::NotConst), unsafety, ext) }; if !self.eat_keyword(kw::Fn) { // It is possible for `expect_one_of` to recover given the contents of @@ -1917,7 +1924,7 @@ impl<'a> Parser<'a> { // account for this. if !self.expect_one_of(&[], &[])? { unreachable!() } } - Ok(FnHeader { constness, unsafety, asyncness, abi }) + Ok(FnHeader { constness, unsafety, asyncness, ext }) } /// Parse the "signature", including the identifier, parameters, and generics of a function. diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index f62f0c9a2682e..2d05a696791ff 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership}; use crate::lexer::UnmatchedBrace; use syntax::ast::{ - self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, + self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; @@ -1212,23 +1212,20 @@ impl<'a> Parser<'a> { } /// Parses `extern string_literal?`. - /// If `extern` is not found, the Rust ABI is used. - /// If `extern` is found and a `string_literal` does not follow, the C ABI is used. - fn parse_extern_abi(&mut self) -> PResult<'a, Abi> { + fn parse_extern(&mut self) -> PResult<'a, Extern> { Ok(if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()? + Extern::from_abi(self.parse_opt_abi()?) } else { - Abi::default() + Extern::None }) } /// Parses a string literal as an ABI spec. - /// If one is not found, the "C" ABI is used. - fn parse_opt_abi(&mut self) -> PResult<'a, Abi> { - let span = if self.token.can_begin_literal_or_bool() { + fn parse_opt_abi(&mut self) -> PResult<'a, Option> { + if self.token.can_begin_literal_or_bool() { let ast::Lit { span, kind, .. } = self.parse_lit()?; match kind { - ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)), + ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") @@ -1241,11 +1238,8 @@ impl<'a> Parser<'a> { .emit(); } } - span - } else { - self.prev_span - }; - Ok(Abi::new(sym::C, span)) + } + Ok(None) } /// We are parsing `async fn`. If we are on Rust 2015, emit an error. diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 4c7d100618359..8e6bc29be5218 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -287,7 +287,7 @@ impl<'a> Parser<'a> { */ let unsafety = self.parse_unsafety(); - let abi = self.parse_extern_abi()?; + let ext = self.parse_extern()?; self.expect_keyword(kw::Fn)?; let cfg = ParamCfg { is_self_allowed: false, @@ -296,7 +296,7 @@ impl<'a> Parser<'a> { }; let decl = self.parse_fn_decl(cfg, false)?; Ok(TyKind::BareFn(P(BareFnTy { - abi, + ext, unsafety, generic_params, decl, diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 50dfac62024b1..255938a193c97 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -30,9 +30,8 @@ use crate::{id_from_def_id, id_from_node_id, SaveContext}; use rls_data::{SigElement, Signature}; use rustc::hir::def::{Res, DefKind}; -use syntax::ast::{self, NodeId}; +use syntax::ast::{self, Extern, NodeId}; use syntax::print::pprust; -use syntax_pos::sym; pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option { if !scx.config.signatures { @@ -157,9 +156,11 @@ fn text_sig(text: String) -> Signature { } } -fn push_abi(text: &mut String, abi: ast::Abi) { - if abi.symbol != sym::Rust { - text.push_str(&format!("extern \"{}\" ", abi.symbol)); +fn push_extern(text: &mut String, ext: Extern) { + match ext { + Extern::None => {} + Extern::Implicit => text.push_str("extern "), + Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)), } } @@ -237,7 +238,7 @@ impl Sig for ast::Ty { if f.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, f.abi); + push_extern(&mut text, f.ext); text.push_str("fn("); let mut defs = vec![]; @@ -387,7 +388,7 @@ impl Sig for ast::Item { if header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, header.abi); + push_extern(&mut text, header.ext); text.push_str("fn "); let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?; @@ -936,7 +937,7 @@ fn make_method_signature( if m.header.unsafety == ast::Unsafety::Unsafe { text.push_str("unsafe "); } - push_abi(&mut text, m.header.abi); + push_extern(&mut text, m.header.ext); text.push_str("fn "); let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d358efbe54364..575795758ae6c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1745,7 +1745,7 @@ pub struct Ty { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, - pub abi: Abi, + pub ext: Extern, pub generic_params: Vec, pub decl: P, } @@ -2128,7 +2128,7 @@ pub struct Mod { /// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { - pub abi: Abi, + pub abi: Option, pub items: Vec, } @@ -2420,15 +2420,20 @@ pub struct Abi { pub span: Span, } -impl Abi { - pub fn new(symbol: Symbol, span: Span) -> Self { - Self { symbol, span } - } +/// `extern` qualifier on a function item or function type. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] +pub enum Extern { + None, + Implicit, + Explicit(Abi), } -impl Default for Abi { - fn default() -> Self { - Self::new(sym::Rust, DUMMY_SP) +impl Extern { + pub fn from_abi(abi: Option) -> Extern { + match abi { + Some(abi) => Extern::Explicit(abi), + None => Extern::Implicit, + } } } @@ -2441,7 +2446,7 @@ pub struct FnHeader { pub unsafety: Unsafety, pub asyncness: Spanned, pub constness: Spanned, - pub abi: Abi, + pub ext: Extern, } impl Default for FnHeader { @@ -2450,7 +2455,7 @@ impl Default for FnHeader { unsafety: Unsafety::Normal, asyncness: dummy_spanned(IsAsync::NotAsync), constness: dummy_spanned(Constness::NotConst), - abi: Abi::default(), + ext: Extern::None, } } } diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index bd836eee42af8..d90fa9addf7f6 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -258,6 +258,12 @@ impl<'a> PostExpansionVisitor<'a> { } } + fn check_extern(&self, ext: ast::Extern) { + if let ast::Extern::Explicit(abi) = ext { + self.check_abi(abi); + } + } + fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { let has_fields = variants.iter().any(|variant| match variant.data { VariantData::Tuple(..) | VariantData::Struct(..) => true, @@ -388,7 +394,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_item(&mut self, i: &'a ast::Item) { match i.kind { ast::ItemKind::ForeignMod(ref foreign_module) => { - self.check_abi(foreign_module.abi); + if let Some(abi) = foreign_module.abi { + self.check_abi(abi); + } } ast::ItemKind::Fn(..) => { @@ -511,7 +519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_ty(&mut self, ty: &'a ast::Ty) { match ty.kind { ast::TyKind::BareFn(ref bare_fn_ty) => { - self.check_abi(bare_fn_ty.abi); + self.check_extern(bare_fn_ty.ext); } ast::TyKind::Never => { gate_feature_post!(&self, never_type, ty.span, @@ -605,7 +613,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // Stability of const fn methods are covered in // `visit_trait_item` and `visit_impl_item` below; this is // because default methods don't pass through this point. - self.check_abi(header.abi); + self.check_extern(header.ext); } if fn_decl.c_variadic() { @@ -639,7 +647,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match ti.kind { ast::TraitItemKind::Method(ref sig, ref block) => { if block.is_none() { - self.check_abi(sig.header.abi); + self.check_extern(sig.header.ext); } if sig.decl.c_variadic() { gate_feature_post!(&self, c_variadic, ti.span, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f4ef993edb95a..da3c885b8609d 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -441,7 +441,7 @@ pub fn noop_visit_ty(ty: &mut P, vis: &mut T) { vis.visit_mt(mt); } TyKind::BareFn(bft) => { - let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut(); + let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut(); generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_fn_decl(decl); } @@ -974,7 +974,7 @@ pub fn noop_flat_map_impl_item(mut item: ImplItem, visitor: &mut } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { - let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header; + let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header; vis.visit_asyncness(&mut asyncness.node); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index ef65a744e83b0..de28bd6cf8365 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1013,7 +1013,7 @@ impl<'a> State<'a> { self.pclose(); } ast::TyKind::BareFn(ref f) => { - self.print_ty_fn(f.abi, + self.print_ty_fn(f.ext, f.unsafety, &f.decl, None, @@ -1232,7 +1232,9 @@ impl<'a> State<'a> { } ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern"); - self.print_abi(nmod.abi); + if let Some(abi) = nmod.abi { + self.print_abi(abi); + } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); self.bclose(item.span); @@ -2805,7 +2807,7 @@ impl<'a> State<'a> { } crate fn print_ty_fn(&mut self, - abi: ast::Abi, + ext: ast::Extern, unsafety: ast::Unsafety, decl: &ast::FnDecl, name: Option, @@ -2825,7 +2827,7 @@ impl<'a> State<'a> { span: syntax_pos::DUMMY_SP, }; self.print_fn(decl, - ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() }, + ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() }, name, &generics, &source_map::dummy_spanned(ast::VisibilityKind::Inherited)); @@ -2866,9 +2868,15 @@ impl<'a> State<'a> { self.print_asyncness(header.asyncness.node); self.print_unsafety(header.unsafety); - if header.abi.symbol != sym::Rust { - self.word_nbsp("extern"); - self.print_abi(header.abi); + match header.ext { + ast::Extern::None => {} + ast::Extern::Implicit => { + self.word_nbsp("extern"); + } + ast::Extern::Explicit(abi) => { + self.word_nbsp("extern"); + self.print_abi(abi); + } } self.s.word("fn") diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index b24306def7482..b6bf2f881616f 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -182,7 +182,7 @@ use std::iter; use std::vec; use rustc_data_structures::thin_vec::ThinVec; -use syntax::ast::{self, Abi, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; +use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::source_map::respan; @@ -737,7 +737,6 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - sym::Rust, explicit_self, tys, body) @@ -792,7 +791,6 @@ impl<'a> TraitDef<'a> { self, type_ident, generics, - sym::Rust, explicit_self, tys, body) @@ -918,7 +916,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - abi: Symbol, explicit_self: Option, arg_types: Vec<(Ident, P)>, body: P) @@ -953,7 +950,7 @@ impl<'a> MethodDef<'a> { let sig = ast::FnSig { header: ast::FnHeader { unsafety, - abi: Abi::new(abi, trait_lo_sp), + ext: ast::Extern::None, ..ast::FnHeader::default() }, decl: fn_decl, diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 55835cb88f4e3..8b8e12fcba653 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -1,9 +1,8 @@ -//~ ERROR mismatched types -// aux-build:test-macros.rs - // For each of these, we should get the appropriate type mismatch error message, // and the function should be echoed. +// aux-build:test-macros.rs + #[macro_use] extern crate test_macros; @@ -35,12 +34,9 @@ fn c() { let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b` } -// FIXME: This doesn't work at the moment. See the one below. The pretty-printer -// injects a "C" between `extern` and `fn` which causes a "probably_eq" -// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST. #[recollect_attr] extern fn bar() { - 0 + 0 //~ ERROR mismatched types } #[recollect_attr] diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 0290f4b2cc982..9e9271f529c73 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -1,10 +1,5 @@ error[E0308]: mismatched types - | - = note: expected type `()` - found type `{integer}` - -error[E0308]: mismatched types - --> $DIR/span-preservation.rs:12:20 + --> $DIR/span-preservation.rs:11:20 | LL | let x: usize = "hello"; | ^^^^^^^ expected usize, found reference @@ -13,7 +8,7 @@ LL | let x: usize = "hello"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:18:29 + --> $DIR/span-preservation.rs:17:29 | LL | fn b(x: Option) -> usize { | ----- expected `usize` because of return type @@ -22,13 +17,13 @@ LL | Some(x) => { return x }, | ^ expected usize, found isize error[E0308]: mismatched types - --> $DIR/span-preservation.rs:34:22 + --> $DIR/span-preservation.rs:33:22 | LL | let x = Foo { a: 10isize }; | ^^^^^^^ expected usize, found isize error[E0560]: struct `c::Foo` has no field named `b` - --> $DIR/span-preservation.rs:35:26 + --> $DIR/span-preservation.rs:34:26 | LL | let y = Foo { a: 10, b: 10isize }; | ^ `c::Foo` does not have this field @@ -36,7 +31,18 @@ LL | let y = Foo { a: 10, b: 10isize }; = note: available fields are: `a` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:48:5 + --> $DIR/span-preservation.rs:39:5 + | +LL | extern fn bar() { + | - possibly return type missing here? +LL | 0 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:44:5 | LL | extern "C" fn baz() { | - possibly return type missing here? From 00bc4496026a3168eed95e88c29f17dac2739d48 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Nov 2019 00:44:59 +0300 Subject: [PATCH 10/18] ast: Keep string literals in ABIs precisely --- src/librustc/hir/lowering/item.rs | 6 ++--- src/librustc_parse/parser/item.rs | 4 +-- src/librustc_parse/parser/mod.rs | 11 +++++--- src/libsyntax/ast.rs | 42 ++++++++++++++++++++--------- src/libsyntax/feature_gate/check.rs | 6 ++--- src/libsyntax/print/pprust.rs | 10 +++---- 6 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 2dc7e014445d1..f689e7f96222f 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -1287,8 +1287,8 @@ impl LoweringContext<'_> { } } - pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi { - abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| { + pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi { + abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| { self.error_on_invalid_abi(abi); abi::Abi::Rust }) @@ -1302,7 +1302,7 @@ impl LoweringContext<'_> { } } - fn error_on_invalid_abi(&self, abi: Abi) { + fn error_on_invalid_abi(&self, abi: StrLit) { struct_span_err!( self.sess, abi.span, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index fe86d03c6e782..3b824dc939f6e 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, lo: Span, - abi: Option, + abi: Option, visibility: Visibility, mut attrs: Vec, extern_sp: Span, @@ -1778,7 +1778,7 @@ impl<'a> Parser<'a> { let is_c_abi = match header.ext { ast::Extern::None => false, ast::Extern::Implicit => true, - ast::Extern::Explicit(abi) => abi.symbol == sym::C, + ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C, }; let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { is_self_allowed: false, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 2d05a696791ff..2b49091192c38 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership}; use crate::lexer::UnmatchedBrace; use syntax::ast::{ - self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, + self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; @@ -1221,11 +1221,14 @@ impl<'a> Parser<'a> { } /// Parses a string literal as an ABI spec. - fn parse_opt_abi(&mut self) -> PResult<'a, Option> { + fn parse_opt_abi(&mut self) -> PResult<'a, Option> { if self.token.can_begin_literal_or_bool() { - let ast::Lit { span, kind, .. } = self.parse_lit()?; + let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind } + = self.parse_lit()?; match kind { - ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })), + ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit { + style, symbol, suffix, span, symbol_unescaped, + })), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 575795758ae6c..dee493a708e49 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1422,6 +1422,33 @@ pub struct Lit { pub span: Span, } +/// Same as `Lit`, but restricted to string literals. +#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] +pub struct StrLit { + /// The original literal token as written in source code. + pub style: StrStyle, + pub symbol: Symbol, + pub suffix: Option, + pub span: Span, + /// The unescaped "semantic" representation of the literal lowered from the original token. + /// FIXME: Remove this and only create the semantic representation during lowering to HIR. + pub symbol_unescaped: Symbol, +} + +impl StrLit { + crate fn as_lit(&self) -> Lit { + let token_kind = match self.style { + StrStyle::Cooked => token::Str, + StrStyle::Raw(n) => token::StrRaw(n), + }; + Lit { + token: token::Lit::new(token_kind, self.symbol, self.suffix), + span: self.span, + kind: LitKind::Str(self.symbol_unescaped, self.style), + } + } +} + // Clippy uses Hash and PartialEq /// Type of the integer literal based on provided suffix. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)] @@ -2128,7 +2155,7 @@ pub struct Mod { /// E.g., `extern { .. }` or `extern C { .. }`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ForeignMod { - pub abi: Option, + pub abi: Option, pub items: Vec, } @@ -2411,25 +2438,16 @@ impl Item { } } -/// A reference to an ABI. -/// -/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`. -#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)] -pub struct Abi { - pub symbol: Symbol, - pub span: Span, -} - /// `extern` qualifier on a function item or function type. #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] pub enum Extern { None, Implicit, - Explicit(Abi), + Explicit(StrLit), } impl Extern { - pub fn from_abi(abi: Option) -> Extern { + pub fn from_abi(abi: Option) -> Extern { match abi { Some(abi) => Extern::Explicit(abi), None => Extern::Implicit, diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index d90fa9addf7f6..abf9adefd3c44 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -191,10 +191,10 @@ macro_rules! gate_feature_post { } impl<'a> PostExpansionVisitor<'a> { - fn check_abi(&self, abi: ast::Abi) { - let ast::Abi { symbol, span } = abi; + fn check_abi(&self, abi: ast::StrLit) { + let ast::StrLit { symbol_unescaped, span, .. } = abi; - match &*symbol.as_str() { + match &*symbol_unescaped.as_str() { // Stable "Rust" | "C" | diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index de28bd6cf8365..17a7cbddff9cc 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1233,7 +1233,8 @@ impl<'a> State<'a> { ast::ItemKind::ForeignMod(ref nmod) => { self.head("extern"); if let Some(abi) = nmod.abi { - self.print_abi(abi); + self.print_literal(&abi.as_lit()); + self.nbsp(); } self.bopen(); self.print_foreign_mod(nmod, &item.attrs); @@ -2875,17 +2876,14 @@ impl<'a> State<'a> { } ast::Extern::Explicit(abi) => { self.word_nbsp("extern"); - self.print_abi(abi); + self.print_literal(&abi.as_lit()); + self.nbsp(); } } self.s.word("fn") } - fn print_abi(&mut self, abi: ast::Abi) { - self.word_nbsp(format!("\"{}\"", abi.symbol)); - } - crate fn print_unsafety(&mut self, s: ast::Unsafety) { match s { ast::Unsafety::Normal => {}, From b85a3da421abad7d1936ec6e57e43c7b0ff10bd3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Nov 2019 15:32:41 +0300 Subject: [PATCH 11/18] parse: Support parsing optional literals Revert weird renaming of the former `LitError::report` --- src/librustc_parse/parser/expr.rs | 31 +++++++++++++++++++------------ src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/mod.rs | 15 +++++++-------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index dadb91f8b3c16..df2f682246512 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -778,13 +778,12 @@ impl<'a> Parser<'a> { macro_rules! parse_lit { () => { - match self.parse_lit() { - Ok(literal) => { + match self.parse_opt_lit() { + Some(literal) => { hi = self.prev_span; ex = ExprKind::Lit(literal); } - Err(mut err) => { - err.cancel(); + None => { return Err(self.expected_expression_found()); } } @@ -1074,11 +1073,20 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - /// Matches `lit = true | false | token_lit`. pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { + self.parse_opt_lit().ok_or_else(|| { + let msg = format!("unexpected token: {}", self.this_token_descr()); + self.span_fatal(self.token.span, &msg) + }) + } + + /// Matches `lit = true | false | token_lit`. + /// Returns `None` if the next token is not a literal. + pub(super) fn parse_opt_lit(&mut self) -> Option { let mut recovered = None; if self.token == token::Dot { - // Attempt to recover `.4` as `0.4`. + // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where + // dot would follow an optional literal, so we do this unconditionally. recovered = self.look_ahead(1, |next_token| { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = next_token.kind { @@ -1107,11 +1115,10 @@ impl<'a> Parser<'a> { match Lit::from_token(token) { Ok(lit) => { self.bump(); - Ok(lit) + Some(lit) } Err(LitError::NotLiteral) => { - let msg = format!("unexpected token: {}", self.this_token_descr()); - Err(self.span_fatal(token.span, &msg)) + None } Err(err) => { let span = token.span; @@ -1120,18 +1127,18 @@ impl<'a> Parser<'a> { _ => unreachable!(), }; self.bump(); - self.error_literal_from_token(err, lit, span); + self.report_lit_error(err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let symbol = Symbol::intern(&suffixless_lit.to_string()); let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) + Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!())) } } } - fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) { + fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 3b824dc939f6e..8e6df0fa4f39f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -105,7 +105,7 @@ impl<'a> Parser<'a> { return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } - let abi = self.parse_opt_abi()?; + let abi = self.parse_opt_abi(); if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 2b49091192c38..7757e00020a22 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1214,21 +1214,20 @@ impl<'a> Parser<'a> { /// Parses `extern string_literal?`. fn parse_extern(&mut self) -> PResult<'a, Extern> { Ok(if self.eat_keyword(kw::Extern) { - Extern::from_abi(self.parse_opt_abi()?) + Extern::from_abi(self.parse_opt_abi()) } else { Extern::None }) } /// Parses a string literal as an ABI spec. - fn parse_opt_abi(&mut self) -> PResult<'a, Option> { - if self.token.can_begin_literal_or_bool() { - let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind } - = self.parse_lit()?; + fn parse_opt_abi(&mut self) -> Option { + if let Some(ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind }) + = self.parse_opt_lit() { match kind { - ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit { + ast::LitKind::Str(symbol_unescaped, style) => return Some(StrLit { style, symbol, suffix, span, symbol_unescaped, - })), + }), ast::LitKind::Err(_) => {} _ => { self.struct_span_err(span, "non-string ABI literal") @@ -1242,7 +1241,7 @@ impl<'a> Parser<'a> { } } } - Ok(None) + None } /// We are parsing `async fn`. If we are on Rust 2015, emit an error. From a699f17483baeff87dc027331bce9a552a6b0624 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Nov 2019 17:04:12 +0300 Subject: [PATCH 12/18] parse: Use string literal parsing in the `asm` macro --- src/librustc_parse/parser/expr.rs | 16 +++++++++ src/librustc_parse/parser/item.rs | 6 ++-- src/librustc_parse/parser/mod.rs | 54 +++++++------------------------ src/libsyntax_ext/asm.rs | 39 ++++++++++++++-------- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index df2f682246512..be1dc4f19a70e 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1073,6 +1073,22 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + pub fn parse_str_lit(&mut self) -> Result> { + match self.parse_opt_lit() { + Some(lit) => match lit.kind { + ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit { + style, + symbol: lit.token.symbol, + suffix: lit.token.suffix, + span: lit.span, + symbol_unescaped, + }), + _ => Err(Some(lit)), + } + None => Err(None), + } + } + pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { self.parse_opt_lit().ok_or_else(|| { let msg = format!("unexpected token: {}", self.this_token_descr()); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 8e6df0fa4f39f..20b96d5cd62f6 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -3,9 +3,9 @@ use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim}; use crate::maybe_whole; -use syntax::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; +use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item}; use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; -use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness}; +use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField}; use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param}; @@ -105,7 +105,7 @@ impl<'a> Parser<'a> { return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } - let abi = self.parse_opt_abi(); + let abi = self.parse_abi(); if self.eat_keyword(kw::Fn) { // EXTERN FUNCTION ITEM diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 7757e00020a22..d5ec461149806 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -15,8 +15,8 @@ use crate::{Directory, DirectoryOwnership}; use crate::lexer::UnmatchedBrace; use syntax::ast::{ - self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, - IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, + self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit, + IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety, }; use syntax::print::pprust; @@ -1214,34 +1214,32 @@ impl<'a> Parser<'a> { /// Parses `extern string_literal?`. fn parse_extern(&mut self) -> PResult<'a, Extern> { Ok(if self.eat_keyword(kw::Extern) { - Extern::from_abi(self.parse_opt_abi()) + Extern::from_abi(self.parse_abi()) } else { Extern::None }) } /// Parses a string literal as an ABI spec. - fn parse_opt_abi(&mut self) -> Option { - if let Some(ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind }) - = self.parse_opt_lit() { - match kind { - ast::LitKind::Str(symbol_unescaped, style) => return Some(StrLit { - style, symbol, suffix, span, symbol_unescaped, - }), - ast::LitKind::Err(_) => {} + fn parse_abi(&mut self) -> Option { + match self.parse_str_lit() { + Ok(str_lit) => Some(str_lit), + Err(Some(lit)) => match lit.kind { + ast::LitKind::Err(_) => None, _ => { - self.struct_span_err(span, "non-string ABI literal") + self.struct_span_err(lit.span, "non-string ABI literal") .span_suggestion( - span, + lit.span, "specify the ABI with a string literal", "\"C\"".to_string(), Applicability::MaybeIncorrect, ) .emit(); + None } } + Err(None) => None, } - None } /// We are parsing `async fn`. If we are on Rust 2015, emit an error. @@ -1333,34 +1331,6 @@ impl<'a> Parser<'a> { self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) || *t == token::BinOp(token::Star)) } - - fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { - let ret = match self.token.kind { - token::Literal(token::Lit { kind: token::Str, symbol, suffix }) => - (symbol, ast::StrStyle::Cooked, suffix), - token::Literal(token::Lit { kind: token::StrRaw(n), symbol, suffix }) => - (symbol, ast::StrStyle::Raw(n), suffix), - _ => return None - }; - self.bump(); - Some(ret) - } - - pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> { - match self.parse_optional_str() { - Some((s, style, suf)) => { - let sp = self.prev_span; - self.expect_no_suffix(sp, "a string literal", suf); - Ok((s, style)) - } - _ => { - let msg = "expected string literal"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - Err(err) - } - } - } } crate fn make_unclosed_delims_error( diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 5fab101957a0a..9b37143557efb 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -2,19 +2,17 @@ // use State::*; +use errors::{DiagnosticBuilder, PResult}; use rustc_data_structures::thin_vec::ThinVec; - -use errors::DiagnosticBuilder; - -use syntax::ast; -use syntax_expand::base::{self, *}; -use syntax::token::{self, Token}; +use rustc_parse::parser::Parser; +use syntax_expand::base::*; +use syntax_pos::Span; +use syntax::{span_err, struct_span_err}; +use syntax::ast::{self, AsmDialect}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; -use syntax::ast::AsmDialect; -use syntax_pos::Span; +use syntax::token::{self, Token}; use syntax::tokenstream::{self, TokenStream}; -use syntax::{span_err, struct_span_err}; use rustc_error_codes::*; @@ -45,7 +43,7 @@ const OPTIONS: &[Symbol] = &[sym::volatile, sym::alignstack, sym::intel]; pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) - -> Box { + -> Box { let mut inline_asm = match parse_inline_asm(cx, sp, tts) { Ok(Some(inline_asm)) => inline_asm, Ok(None) => return DummyResult::any(sp), @@ -69,6 +67,19 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>, })) } +fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> { + match p.parse_str_lit() { + Ok(str_lit) => Ok(str_lit.symbol_unescaped), + Err(opt_lit) => { + let span = opt_lit.map_or(p.token.span, |lit| lit.span); + let msg = "expected string literal"; + let mut err = p.sess.span_diagnostic.struct_span_fatal(span, msg); + err.span_label(span, msg); + Err(err) + } + } +} + fn parse_inline_asm<'a>( cx: &mut ExtCtxt<'a>, sp: Span, @@ -144,7 +155,7 @@ fn parse_inline_asm<'a>( p.eat(&token::Comma); } - let (constraint, _) = p.parse_str()?; + let constraint = parse_asm_str(&mut p)?; let span = p.prev_span; @@ -189,7 +200,7 @@ fn parse_inline_asm<'a>( p.eat(&token::Comma); } - let (constraint, _) = p.parse_str()?; + let constraint = parse_asm_str(&mut p)?; if constraint.as_str().starts_with("=") { span_err!(cx, p.prev_span, E0662, @@ -212,7 +223,7 @@ fn parse_inline_asm<'a>( p.eat(&token::Comma); } - let (s, _) = p.parse_str()?; + let s = parse_asm_str(&mut p)?; if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.prev_span, "expected a clobber, found an option"); @@ -225,7 +236,7 @@ fn parse_inline_asm<'a>( } } Options => { - let (option, _) = p.parse_str()?; + let option = parse_asm_str(&mut p)?; if option == sym::volatile { // Indicates that the inline assembly has side effects From 8c7530ade81b14d48ebc7cdd5e5fbdc0d9612bbe Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Wed, 23 Oct 2019 16:32:16 -0500 Subject: [PATCH 13/18] Improve documentation of `Vec::split_off(...)` The previous ordering of the sentences kept switching between the return value and the value of `self` after execution, making it hard to follow. Additionally, as rendered in the browser, the period in "`Self`. `self`" was difficult to make out as being a sentence separator and not one code block. --- src/liballoc/vec.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 4363314dc4580..963b012c71149 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1333,10 +1333,10 @@ impl Vec { /// Splits the collection into two at the given index. /// - /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`, - /// and the returned `Self` contains elements `[at, len)`. - /// - /// Note that the capacity of `self` does not change. + /// Copies the range from `[at, len)` to a newly allocated `Self` + /// and returns the result. The original `Self` will contain the + /// range from `[0, at)`. Note that the capacity of `self` does + /// not change. /// /// # Panics /// From a36c3f6f68f969da1141572531e140229bda4301 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Sat, 16 Nov 2019 14:11:08 -0600 Subject: [PATCH 14/18] Revise the text of `vec::split_off()` per review in #65739 Remove the incorrect usage of "copy" as the trait is not called. --- src/liballoc/vec.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 963b012c71149..07e4358d644c6 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1333,10 +1333,9 @@ impl Vec { /// Splits the collection into two at the given index. /// - /// Copies the range from `[at, len)` to a newly allocated `Self` - /// and returns the result. The original `Self` will contain the - /// range from `[0, at)`. Note that the capacity of `self` does - /// not change. + /// Returns a newly allocated vector containing the elements in the range + /// `[at, len)`. After the call, the original vector will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. /// /// # Panics /// From 3407c49c41915e8850de621bd6ddf70d8b7540f5 Mon Sep 17 00:00:00 2001 From: Adam Schwalm Date: Sat, 16 Nov 2019 14:47:33 -0600 Subject: [PATCH 15/18] Clarify transmute_copy documentation example --- src/libcore/mem/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index dc7c36ff03c4e..fff010385c302 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -744,11 +744,11 @@ pub fn drop(_x: T) { } /// bar: u8, /// } /// -/// let foo_slice = [10u8]; +/// let foo_array = [10u8]; /// /// unsafe { -/// // Copy the data from 'foo_slice' and treat it as a 'Foo' -/// let mut foo_struct: Foo = mem::transmute_copy(&foo_slice); +/// // Copy the data from 'foo_array' and treat it as a 'Foo' +/// let mut foo_struct: Foo = mem::transmute_copy(&foo_array); /// assert_eq!(foo_struct.bar, 10); /// /// // Modify the copied data @@ -756,8 +756,8 @@ pub fn drop(_x: T) { } /// assert_eq!(foo_struct.bar, 20); /// } /// -/// // The contents of 'foo_slice' should not have changed -/// assert_eq!(foo_slice, [10]); +/// // The contents of 'foo_array' should not have changed +/// assert_eq!(foo_array, [10]); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] From 11580ced403211c8c422a952a2c5dabedf6812d6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 16 Nov 2019 20:11:05 +0300 Subject: [PATCH 16/18] Address review comments --- src/librustc_parse/parser/expr.rs | 3 +++ src/libsyntax/ast.rs | 5 +---- src/libsyntax_ext/asm.rs | 5 ++--- src/libsyntax_pos/symbol.rs | 1 - src/test/ui/asm/asm-parse-errors.stderr | 10 +++++----- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index be1dc4f19a70e..a56a7bf1802c7 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1073,6 +1073,9 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + /// Returns a string literal if the next token is a string literal. + /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, + /// and returns `None` if the next token is not literal at all. pub fn parse_str_lit(&mut self) -> Result> { match self.parse_opt_lit() { Some(lit) => match lit.kind { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dee493a708e49..bbf00825acb33 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2448,10 +2448,7 @@ pub enum Extern { impl Extern { pub fn from_abi(abi: Option) -> Extern { - match abi { - Some(abi) => Extern::Explicit(abi), - None => Extern::Implicit, - } + abi.map_or(Extern::Implicit, Extern::Explicit) } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 9b37143557efb..bd345a9a7dada 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -72,9 +72,8 @@ fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> { Ok(str_lit) => Ok(str_lit.symbol_unescaped), Err(opt_lit) => { let span = opt_lit.map_or(p.token.span, |lit| lit.span); - let msg = "expected string literal"; - let mut err = p.sess.span_diagnostic.struct_span_fatal(span, msg); - err.span_label(span, msg); + let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal"); + err.span_label(span, "not a string literal"); Err(err) } } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index b3e9576f43f59..86eaeeab5a426 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -570,7 +570,6 @@ symbols! { rust_2018_preview, rust_begin_unwind, rustc, - Rust, RustcDecodable, RustcEncodable, rustc_allocator, diff --git a/src/test/ui/asm/asm-parse-errors.stderr b/src/test/ui/asm/asm-parse-errors.stderr index 9fe59d12e12cd..2b29332fef5e5 100644 --- a/src/test/ui/asm/asm-parse-errors.stderr +++ b/src/test/ui/asm/asm-parse-errors.stderr @@ -8,13 +8,13 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:5:18 | LL | asm!("nop" : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected string literal --> $DIR/asm-parse-errors.rs:6:30 | LL | asm!("mov %eax, $$0x2" : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected `(`, found keyword `struct` --> $DIR/asm-parse-errors.rs:7:39 @@ -32,7 +32,7 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:9:44 | LL | asm!("in %dx, %al" : "={al}"(result) : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected `(`, found keyword `struct` --> $DIR/asm-parse-errors.rs:10:51 @@ -50,13 +50,13 @@ error: expected string literal --> $DIR/asm-parse-errors.rs:12:36 | LL | asm!("mov $$0x200, %eax" : : : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: expected string literal --> $DIR/asm-parse-errors.rs:13:45 | LL | asm!("mov eax, 2" : "={eax}"(foo) : : : struct); - | ^^^^^^ expected string literal + | ^^^^^^ not a string literal error: inline assembly must be a string literal --> $DIR/asm-parse-errors.rs:14:10 From 28aec1beaa5e16b17143f993cab408debe1dcda5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 17 Nov 2019 01:11:35 +0300 Subject: [PATCH 17/18] Add some more tests --- src/test/ui/asm/asm-literal-escaping.rs | 12 ++++++++++ src/test/ui/proc-macro/span-preservation.rs | 10 ++++++++ .../ui/proc-macro/span-preservation.stderr | 24 ++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/asm/asm-literal-escaping.rs diff --git a/src/test/ui/asm/asm-literal-escaping.rs b/src/test/ui/asm/asm-literal-escaping.rs new file mode 100644 index 0000000000000..8d464e752e637 --- /dev/null +++ b/src/test/ui/asm/asm-literal-escaping.rs @@ -0,0 +1,12 @@ +// build-pass +// only-x86_64 + +#![feature(asm)] + +fn main() { + unsafe { + // "nop" :: "r"(x) : "eax" : "volatile" + let x = 10; + asm!("\x6Eop" :: "\x72"(x) : "\x65ax" : "\x76olatile"); + } +} diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 8b8e12fcba653..b22e50c4c1715 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -44,4 +44,14 @@ extern "C" fn baz() { 0 //~ ERROR mismatched types } +#[recollect_attr] +extern "Rust" fn rust_abi() { + 0 //~ ERROR mismatched types +} + +#[recollect_attr] +extern "\x43" fn c_abi_escaped() { + 0 //~ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 9e9271f529c73..545c2fa5f40e4 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -52,7 +52,29 @@ LL | 0 = note: expected type `()` found type `{integer}` -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:49:5 + | +LL | extern "Rust" fn rust_abi() { + | - possibly return type missing here? +LL | 0 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/span-preservation.rs:54:5 + | +LL | extern "\x43" fn c_abi_escaped() { + | - possibly return type missing here? +LL | 0 + | ^ expected (), found integer + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0308, E0560. For more information about an error, try `rustc --explain E0308`. From cfe94b421bf0db86670434d5391819c15dd70e57 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Sat, 16 Nov 2019 14:54:09 +0000 Subject: [PATCH 18/18] Add test for issue 63116 --- src/test/ui/parser/issue-63116.rs | 3 +++ src/test/ui/parser/issue-63116.stderr | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/parser/issue-63116.rs create mode 100644 src/test/ui/parser/issue-63116.stderr diff --git a/src/test/ui/parser/issue-63116.rs b/src/test/ui/parser/issue-63116.rs new file mode 100644 index 0000000000000..430bc1d716c91 --- /dev/null +++ b/src/test/ui/parser/issue-63116.rs @@ -0,0 +1,3 @@ +// fixed by #66361 +// error-pattern: aborting due to 3 previous errors +impl W $DIR/issue-63116.rs:3:18 + | +LL | impl W $DIR/issue-63116.rs:3:12 + | +LL | impl W `, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, or lifetime, found `;` + --> $DIR/issue-63116.rs:3:15 + | +LL | impl W