diff --git a/Cargo.lock b/Cargo.lock index 070858cd185ec..c784246ba396e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,7 +106,7 @@ dependencies = [ "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2729,7 +2729,7 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2887,7 +2887,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "rustc_metadata 0.0.0", "rustc_target 0.0.0", @@ -4592,7 +4592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-ap-serialize 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61673783f2089e01033ffa82d1988f55175402071b31253a358292e1624d4602" "checksum rustc-ap-syntax 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28f3dd1346d5b0269c07a4a78855e309a298ab569c9c1302d4d4f57f8eee4e84" "checksum rustc-ap-syntax_pos 546.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45e67b526dbda3a0c7dab91c8947d43685e7697f52686a4949da3c179cd7c979" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" "checksum rustc-rayon-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d38ca7cbc22fa59f09d8534ea4b27f67b0facf0cbe274433aceea227a02543" diff --git a/config.toml.example b/config.toml.example index cb9f388a8e47b..a3ec4f2044cbd 100644 --- a/config.toml.example +++ b/config.toml.example @@ -141,10 +141,10 @@ # library and facade crates. #compiler-docs = false -# Indicate whether submodules are managed and updated automatically. +# Indicate whether git submodules are managed and updated automatically. #submodules = true -# Update submodules only when the checked out commit in the submodules differs +# Update git submodules only when the checked out commit in the submodules differs # from what is committed in the main rustc repo. #fast-submodules = true diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 9c01de8aa8251..da372781738d6 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -102,8 +102,13 @@ fn main() { // FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule // being broken on the beta compiler with bootstrap passed, so this is a temporary workaround // (we've just snapped, so there are no cfg(bootstrap) related annotations in core). - if stage == "0" && crate_name != Some("core") { - cmd.arg("--cfg").arg("bootstrap"); + if stage == "0" { + if crate_name != Some("core") { + cmd.arg("--cfg").arg("bootstrap"); + } else { + // NOTE(eddyb) see FIXME above, except now we need annotations again in core. + cmd.arg("--cfg").arg("boostrap_stdarch_ignore_this"); + } } // Print backtrace in case of ICE @@ -276,10 +281,6 @@ fn main() { cmd.arg("-C").arg("target-feature=-crt-static"); } } - - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { - cmd.arg("--remap-path-prefix").arg(&map); - } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { @@ -296,6 +297,10 @@ fn main() { } } + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); + } + // Force all crates compiled by this compiler to (a) be unstable and (b) // allow the `rustc_private` feature to link to other unstable crates // also in the sysroot. We also do this for host crates, since those diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index d774e465118b3..59e7c808cdad5 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -304,3 +304,10 @@ to customize the output: Note that it is invalid to combine the `--json` argument with the `--color` argument, and it is required to combine `--json` with `--error-format=json`. + +## `@path`: load command-line flags from a path + +If you specify `@path` on the command-line, then it will open `path` and read +command line options from it. These options are one per line; a blank line indicates +an empty option. The file can use Unix or Windows style line endings, and must be +encoded as UTF-8. \ No newline at end of file diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ceaa870d2b3f7..d145f2212f93a 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1293,18 +1293,40 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(boostrap_stdarch_ignore_this)] pub fn overflowing_mul(a: T, b: T) -> T; + /// Returns (a + b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_add` method. For example, + /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_add(a: T, b: T) -> T; + /// Returns (a - b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_sub` method. For example, + /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_sub(a: T, b: T) -> T; + /// Returns (a * b) mod 2N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_mul` method. For example, + /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) + #[cfg(not(boostrap_stdarch_ignore_this))] + pub fn wrapping_mul(a: T, b: T) -> T; + /// Computes `a + b`, while saturating at numeric bounds. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `saturating_add` method. For example, diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 67e30e7ffcb24..b46e06f8d8ada 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,7 +1112,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -1135,7 +1141,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -1157,7 +1169,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } } @@ -3031,7 +3049,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - intrinsics::overflowing_add(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_add(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_add(self, rhs) + } } } @@ -3053,7 +3077,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - intrinsics::overflowing_sub(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_sub(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_sub(self, rhs) + } } } @@ -3076,7 +3106,13 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - intrinsics::overflowing_mul(self, rhs) + #[cfg(boostrap_stdarch_ignore_this)] { + intrinsics::overflowing_mul(self, rhs) + } + + #[cfg(not(boostrap_stdarch_ignore_this))] { + intrinsics::wrapping_mul(self, rhs) + } } doc_comment! { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a9b8962f45b1b..9483ffca448e3 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -328,7 +328,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }, "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | "bitreverse" | "add_with_overflow" | "sub_with_overflow" | - "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" | "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => { @@ -398,9 +398,9 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { return; }, - "overflowing_add" => self.add(args[0].immediate(), args[1].immediate()), - "overflowing_sub" => self.sub(args[0].immediate(), args[1].immediate()), - "overflowing_mul" => self.mul(args[0].immediate(), args[1].immediate()), + "wrapping_add" => self.add(args[0].immediate(), args[1].immediate()), + "wrapping_sub" => self.sub(args[0].immediate(), args[1].immediate()), + "wrapping_mul" => self.mul(args[0].immediate(), args[1].immediate()), "exact_div" => if signed { self.exactsdiv(args[0].immediate(), args[1].immediate()) diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index d93589ea84be0..89b50c5daccae 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -13,7 +13,7 @@ test = false flate2 = "1.0" log = "0.4" punycode = "0.4.0" -rustc-demangle = "0.1.15" +rustc-demangle = "0.1.16" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_driver/args/mod.rs b/src/librustc_driver/args/mod.rs new file mode 100644 index 0000000000000..a59f9afd8beb5 --- /dev/null +++ b/src/librustc_driver/args/mod.rs @@ -0,0 +1,84 @@ +use std::env; +use std::error; +use std::fmt; +use std::fs; +use std::io; +use std::str; +use std::sync::atomic::{AtomicBool, Ordering}; + +#[cfg(test)] +mod tests; + +static USED_ARGSFILE_FEATURE: AtomicBool = AtomicBool::new(false); + +pub fn used_unstable_argsfile() -> bool { + USED_ARGSFILE_FEATURE.load(Ordering::Relaxed) +} + +pub struct ArgsIter { + base: env::ArgsOs, + file: std::vec::IntoIter, +} + +impl ArgsIter { + pub fn new() -> Self { + ArgsIter { base: env::args_os(), file: vec![].into_iter() } + } +} + +impl Iterator for ArgsIter { + type Item = Result; + + fn next(&mut self) -> Option { + loop { + if let Some(line) = self.file.next() { + return Some(Ok(line)); + } + + let arg = + self.base.next().map(|arg| arg.into_string().map_err(|_| Error::Utf8Error(None))); + match arg { + Some(Err(err)) => return Some(Err(err)), + Some(Ok(ref arg)) if arg.starts_with("@") => { + let path = &arg[1..]; + let file = match fs::read_to_string(path) { + Ok(file) => { + USED_ARGSFILE_FEATURE.store(true, Ordering::Relaxed); + file + } + Err(ref err) if err.kind() == io::ErrorKind::InvalidData => { + return Some(Err(Error::Utf8Error(Some(path.to_string())))); + } + Err(err) => return Some(Err(Error::IOError(path.to_string(), err))), + }; + self.file = + file.lines().map(ToString::to_string).collect::>().into_iter(); + } + Some(Ok(arg)) => return Some(Ok(arg)), + None => return None, + } + } + } +} + +#[derive(Debug)] +pub enum Error { + Utf8Error(Option), + IOError(String, io::Error), +} + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::Utf8Error(None) => write!(fmt, "Utf8 error"), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), + Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + } + } +} + +impl error::Error for Error { + fn description(&self) -> &'static str { + "argument error" + } +} diff --git a/src/librustc_driver/args/tests.rs b/src/librustc_driver/args/tests.rs new file mode 100644 index 0000000000000..080dd5cb746c3 --- /dev/null +++ b/src/librustc_driver/args/tests.rs @@ -0,0 +1,145 @@ +use super::*; + +use std::str; + +fn want_args(v: impl IntoIterator) -> Vec { + v.into_iter().map(String::from).collect() +} + +fn got_args(file: &[u8]) -> Result, Error> { + let ret = str::from_utf8(file) + .map_err(|_| Error::Utf8Error(None))? + .lines() + .map(ToString::to_string) + .collect::>(); + Ok(ret) +} + +#[test] +fn nothing() { + let file = b""; + + assert_eq!(got_args(file).unwrap(), want_args(vec![])); +} + +#[test] +fn empty() { + let file = b"\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec![""])); +} + +#[test] +fn simple() { + let file = b"foo"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn simple_eol() { + let file = b"foo\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn multi() { + let file = b"foo\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_eol() { + let file = b"foo\nbar\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_empty() { + let file = b"foo\n\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_eol() { + let file = b"foo\n\nbar\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_start() { + let file = b"\nfoo\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); +} + +#[test] +fn multi_empty_end() { + let file = b"foo\nbar\n\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); +} + +#[test] +fn simple_eol_crlf() { + let file = b"foo\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo"])); +} + +#[test] +fn multi_crlf() { + let file = b"foo\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_eol_crlf() { + let file = b"foo\r\nbar\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar"])); +} + +#[test] +fn multi_empty_crlf() { + let file = b"foo\r\n\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_eol_crlf() { + let file = b"foo\r\n\r\nbar\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "", "bar"])); +} + +#[test] +fn multi_empty_start_crlf() { + let file = b"\r\nfoo\r\nbar"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["", "foo", "bar"])); +} + +#[test] +fn multi_empty_end_crlf() { + let file = b"foo\r\nbar\r\n\r\n"; + + assert_eq!(got_args(file).unwrap(), want_args(vec!["foo", "bar", ""])); +} + +#[test] +fn bad_utf8() { + let file = b"foo\x80foo"; + + match got_args(file).unwrap_err() { + Error::Utf8Error(_) => (), + bad => panic!("bad err: {:?}", bad), + } +} diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index fdd0773b73ae2..4843c1a951b31 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -66,6 +66,7 @@ use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; pub mod pretty; +mod args; /// Exit status code used for successful compilation and help output. pub const EXIT_SUCCESS: i32 = 0; @@ -777,13 +778,19 @@ fn usage(verbose: bool, include_unstable_options: bool) { } else { "\n --help -v Print the full set of options rustc accepts" }; - println!("{}\nAdditional help: + let at_path = if verbose && nightly_options::is_nightly_build() { + " @path Read newline separated options from `path`\n" + } else { + "" + }; + println!("{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ - Print 'lint' options and default settings{}{}\n", - options.usage(message), - nightly_help, - verbose_help); + Print 'lint' options and default settings{nightly}{verbose}\n", + options = options.usage(message), + at_path = at_path, + nightly = nightly_help, + verbose = verbose_help); } fn print_wall_help() { @@ -1008,6 +1015,12 @@ pub fn handle_options(args: &[String]) -> Option { // (unstable option being used on stable) nightly_options::check_nightly_options(&matches, &config::rustc_optgroups()); + // Late check to see if @file was used without unstable options enabled + if crate::args::used_unstable_argsfile() && !nightly_options::is_unstable_enabled(&matches) { + early_error(ErrorOutputType::default(), + "@path is unstable - use -Z unstable-options to enable its use"); + } + if matches.opt_present("h") || matches.opt_present("help") { // Only show unstable options in --help if we accept unstable options. usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches)); @@ -1186,10 +1199,10 @@ pub fn main() { init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); let result = report_ices_to_stderr_if_any(|| { - let args = env::args_os().enumerate() - .map(|(i, arg)| arg.into_string().unwrap_or_else(|arg| { + let args = args::ArgsIter::new().enumerate() + .map(|(i, arg)| arg.unwrap_or_else(|err| { early_error(ErrorOutputType::default(), - &format!("Argument {} is not valid Unicode: {:?}", i, arg)) + &format!("Argument {} is not valid: {}", i, err)) })) .collect::>(); run_compiler(&args, &mut callbacks, None, None) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 89c5be137a4e5..ee105fed1a324 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -110,18 +110,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(out_val, dest)?; } - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let lhs = self.read_immediate(args[0])?; let rhs = self.read_immediate(args[1])?; let (bin_op, ignore_overflow) = match intrinsic_name { - "overflowing_add" => (BinOp::Add, true), - "overflowing_sub" => (BinOp::Sub, true), - "overflowing_mul" => (BinOp::Mul, true), + "wrapping_add" => (BinOp::Add, true), + "wrapping_sub" => (BinOp::Sub, true), + "wrapping_mul" => (BinOp::Mul, true), "add_with_overflow" => (BinOp::Add, false), "sub_with_overflow" => (BinOp::Sub, false), "mul_with_overflow" => (BinOp::Mul, false), diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 0eed43b10868e..649cccc36c346 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -537,9 +537,9 @@ impl Qualif for IsNotPromotable { | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" - | "overflowing_add" - | "overflowing_sub" - | "overflowing_mul" + | "wrapping_add" + | "wrapping_sub" + | "wrapping_mul" | "unchecked_shl" | "unchecked_shr" | "rotate_left" diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b84bc31ec2ae2..334d0cee9fbe7 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -379,9 +379,9 @@ fn is_intrinsic_whitelisted(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { | "add_with_overflow" // ~> .overflowing_add | "sub_with_overflow" // ~> .overflowing_sub | "mul_with_overflow" // ~> .overflowing_mul - | "overflowing_add" // ~> .wrapping_add - | "overflowing_sub" // ~> .wrapping_sub - | "overflowing_mul" // ~> .wrapping_mul + | "wrapping_add" // ~> .wrapping_add + | "wrapping_sub" // ~> .wrapping_sub + | "wrapping_mul" // ~> .wrapping_mul | "saturating_add" // ~> .saturating_add | "saturating_sub" // ~> .saturating_sub | "unchecked_shl" // ~> .wrapping_shl diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 539e4a301e012..1510d74babb6d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -16,6 +16,7 @@ use crate::{ResolutionError, Determinacy, PathResult, CrateLint}; use rustc::bug; use rustc::hir::def::{self, *}; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::map::DefCollector; use rustc::ty; use rustc::middle::cstore::CrateStore; use rustc_metadata::cstore::LoadedMacro; @@ -159,26 +160,23 @@ impl<'a> Resolver<'a> { Some(ext) } - /// Ensures that the reduced graph rooted at the given external module - /// is built, building it if it is not. - crate fn populate_module_if_necessary(&mut self, module: Module<'a>) { - if module.populated.get() { return } - let def_id = module.def_id().unwrap(); - for child in self.cstore.item_children_untracked(def_id, self.session) { - let child = child.map_id(|_| panic!("unexpected id")); - BuildReducedGraphVisitor { parent_scope: ParentScope::module(module), r: self } - .build_reduced_graph_for_external_crate_res(child); - } - module.populated.set(true) - } - crate fn build_reduced_graph( &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a> ) -> LegacyScope<'a> { + fragment.visit_with(&mut DefCollector::new(&mut self.definitions, parent_scope.expansion)); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); visitor.parent_scope.legacy } + + crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { + let def_id = module.def_id().expect("unpopulated module without a def-id"); + for child in self.cstore.item_children_untracked(def_id, self.session) { + let child = child.map_id(|_| panic!("unexpected id")); + BuildReducedGraphVisitor { r: self, parent_scope: ParentScope::module(module) } + .build_reduced_graph_for_external_crate_res(child); + } + } } struct BuildReducedGraphVisitor<'a, 'b> { @@ -186,6 +184,10 @@ struct BuildReducedGraphVisitor<'a, 'b> { parent_scope: ParentScope<'a>, } +impl<'a> AsMut> for BuildReducedGraphVisitor<'a, '_> { + fn as_mut(&mut self) -> &mut Resolver<'a> { self.r } +} + impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { let parent_scope = &self.parent_scope; @@ -603,8 +605,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; - self.r.populate_module_if_necessary(module); - let used = self.process_legacy_macro_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); @@ -879,9 +879,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // This is only a guess, two equivalent idents may incorrectly get different gensyms here. let ident = ident.gensym_if_underscore(); let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene + // Record primary definitions. match res { Res::Def(kind @ DefKind::Mod, def_id) - | Res::Def(kind @ DefKind::Enum, def_id) => { + | Res::Def(kind @ DefKind::Enum, def_id) + | Res::Def(kind @ DefKind::Trait, def_id) => { let module = self.r.new_module(parent, ModuleKind::Def(kind, def_id, ident.name), def_id, @@ -889,70 +891,55 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { span); self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Res::Def(DefKind::Variant, _) + Res::Def(DefKind::Struct, _) + | Res::Def(DefKind::Union, _) + | Res::Def(DefKind::Variant, _) | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::ForeignTy, _) | Res::Def(DefKind::OpaqueTy, _) | Res::Def(DefKind::TraitAlias, _) + | Res::Def(DefKind::AssocTy, _) + | Res::Def(DefKind::AssocOpaqueTy, _) | Res::PrimTy(..) - | Res::ToolMod => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - } + | Res::ToolMod => + self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)), Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::Method, _) | Res::Def(DefKind::Static, _) | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), _) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - } - Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { - self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)); - - if let Some(struct_def_id) = - self.r.cstore.def_key(def_id).parent - .map(|index| DefId { krate: def_id.krate, index: index }) { - self.r.struct_constructors.insert(struct_def_id, (res, vis)); - } - } - Res::Def(DefKind::Trait, def_id) => { - let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name); - let module = self.r.new_module(parent, - module_kind, - parent.normal_ancestor_id, - expansion, - span); - self.r.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); - - for child in self.r.cstore.item_children_untracked(def_id, self.r.session) { - let res = child.res.map_id(|_| panic!("unexpected id")); - let ns = if let Res::Def(DefKind::AssocTy, _) = res { - TypeNS - } else { ValueNS }; - self.r.define(module, child.ident, ns, - (res, ty::Visibility::Public, DUMMY_SP, expansion)); - - if self.r.cstore.associated_item_cloned_untracked(child.res.def_id()) - .method_has_self_argument { - self.r.has_self.insert(res.def_id()); - } - } - module.populated.set(true); - } + | Res::Def(DefKind::AssocConst, _) + | Res::Def(DefKind::Ctor(..), _) => + self.r.define(parent, ident, ValueNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::Macro(..), _) + | Res::NonMacroAttr(..) => + self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)), + Res::Def(DefKind::TyParam, _) | Res::Def(DefKind::ConstParam, _) + | Res::Local(..) | Res::SelfTy(..) | Res::SelfCtor(..) | Res::Err => + bug!("unexpected resolution: {:?}", res) + } + // Record some extra data for better diagnostics. + match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - self.r.define(parent, ident, TypeNS, (res, vis, DUMMY_SP, expansion)); - - // Record field names for error reporting. let field_names = self.r.cstore.struct_field_names_untracked(def_id); self.insert_field_names(def_id, field_names); } - Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.r.define(parent, ident, MacroNS, (res, vis, DUMMY_SP, expansion)); + Res::Def(DefKind::Method, def_id) => { + if self.r.cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { + self.r.has_self.insert(def_id); + } + } + Res::Def(DefKind::Ctor(CtorOf::Struct, ..), def_id) => { + let parent = self.r.cstore.def_key(def_id).parent; + if let Some(struct_def_id) = parent.map(|index| DefId { index, ..def_id }) { + self.r.struct_constructors.insert(struct_def_id, (res, vis)); + } } - _ => bug!("unexpected resolution: {:?}", res) + _ => {} } } fn legacy_import_macro(&mut self, - name: Name, + name: ast::Name, binding: &'a NameBinding<'a>, span: Span, allow_shadowing: bool) { @@ -1021,9 +1008,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if let Some(span) = import_all { let directive = macro_use_directive(self, span); self.r.potentially_unused_imports.push(directive); - module.for_each_child(|ident, ns, binding| if ns == MacroNS { - let imported_binding = self.r.import(binding, directive); - self.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); + module.for_each_child(self, |this, ident, ns, binding| if ns == MacroNS { + let imported_binding = this.r.import(binding, directive); + this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); }); } else { for ident in single_imports.iter().cloned() { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 861b0fd44ac41..afdcec19d8ef6 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -73,20 +73,23 @@ crate fn add_typo_suggestion( false } -crate fn add_module_candidates( - module: Module<'_>, names: &mut Vec, filter_fn: &impl Fn(Res) -> bool -) { - for (&(ident, _), resolution) in module.resolutions.borrow().iter() { - if let Some(binding) = resolution.borrow().binding { - let res = binding.res(); - if filter_fn(res) { - names.push(TypoSuggestion::from_res(ident.name, res)); +impl<'a> Resolver<'a> { + crate fn add_module_candidates( + &mut self, + module: Module<'a>, + names: &mut Vec, + filter_fn: &impl Fn(Res) -> bool, + ) { + for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() { + if let Some(binding) = resolution.borrow().binding { + let res = binding.res(); + if filter_fn(res) { + names.push(TypoSuggestion::from_res(ident.name, res)); + } } } } -} -impl<'a> Resolver<'a> { /// Combines an error with provided span and emits it. /// /// This takes the error provided, combines it with the span and any additional spans inside the @@ -402,10 +405,10 @@ impl<'a> Resolver<'a> { Scope::CrateRoot => { let root_ident = Ident::new(kw::PathRoot, ident.span); let root_module = this.resolve_crate_root(root_ident); - add_module_candidates(root_module, &mut suggestions, filter_fn); + this.add_module_candidates(root_module, &mut suggestions, filter_fn); } Scope::Module(module) => { - add_module_candidates(module, &mut suggestions, filter_fn); + this.add_module_candidates(module, &mut suggestions, filter_fn); } Scope::MacroUsePrelude => { suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| { @@ -453,7 +456,7 @@ impl<'a> Resolver<'a> { Scope::StdLibPrelude => { if let Some(prelude) = this.prelude { let mut tmp_suggestions = Vec::new(); - add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); + this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn); suggestions.extend(tmp_suggestions.into_iter().filter(|s| { use_prelude || this.is_builtin_macro(s.res) })); @@ -509,11 +512,9 @@ impl<'a> Resolver<'a> { while let Some((in_module, path_segments, in_module_is_extern)) = worklist.pop() { - self.populate_module_if_necessary(in_module); - // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). - in_module.for_each_child_stable(|ident, ns, name_binding| { + in_module.for_each_child_stable(self, |this, ident, ns, name_binding| { // avoid imports entirely if name_binding.is_import() && !name_binding.is_extern_crate() { return; } // avoid non-importable candidates as well @@ -547,7 +548,7 @@ impl<'a> Resolver<'a> { // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { let did = match res { - Res::Def(DefKind::Ctor(..), did) => self.parent(did), + Res::Def(DefKind::Ctor(..), did) => this.parent(did), _ => res.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); @@ -607,8 +608,6 @@ impl<'a> Resolver<'a> { krate: crate_id, index: CRATE_DEF_INDEX, }); - self.populate_module_if_necessary(&crate_root); - suggestions.extend(self.lookup_import_candidates_from_module( lookup_ident, namespace, crate_root, ident, &filter_fn)); } @@ -805,7 +804,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// at the root of the crate instead of the module where it is defined /// ``` pub(crate) fn check_for_module_export_macro( - &self, + &mut self, directive: &'b ImportDirective<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, @@ -826,7 +825,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return None; } - let resolutions = crate_module.resolutions.borrow(); + let resolutions = self.r.resolutions(crate_module).borrow(); let resolution = resolutions.get(&(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ffdfd85002bca..d8bd86699b7af 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1929,7 +1929,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { let mut traits = module.traits.borrow_mut(); if traits.is_none() { let mut collected_traits = Vec::new(); - module.for_each_child(|name, ns, binding| { + module.for_each_child(self.r, |_, name, ns, binding| { if ns != TypeNS { return } match binding.res() { Res::Def(DefKind::Trait, _) | diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 68f9c1684d6fb..a822fa049ca1c 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1,8 +1,7 @@ use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; use crate::path_names_to_string; -use crate::diagnostics::{add_typo_suggestion, add_module_candidates}; -use crate::diagnostics::{ImportSuggestion, TypoSuggestion}; +use crate::diagnostics::{add_typo_suggestion, ImportSuggestion, TypoSuggestion}; use crate::late::{LateResolutionVisitor, RibKind}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; @@ -548,7 +547,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // Items in scope if let RibKind::ModuleRibKind(module) = rib.kind { // Items from this module - add_module_candidates(module, &mut names, &filter_fn); + self.r.add_module_candidates(module, &mut names, &filter_fn); if let ModuleKind::Block(..) = module.kind { // We can see through blocks @@ -577,7 +576,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { })); if let Some(prelude) = self.r.prelude { - add_module_candidates(prelude, &mut names, &filter_fn); + self.r.add_module_candidates(prelude, &mut names, &filter_fn); } } break; @@ -599,7 +598,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { mod_path, Some(TypeNS), false, span, CrateLint::No ) { if let ModuleOrUniformRoot::Module(module) = module { - add_module_candidates(module, &mut names, &filter_fn); + self.r.add_module_candidates(module, &mut names, &filter_fn); } } } @@ -717,9 +716,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // abort if the module is already found if result.is_some() { break; } - self.r.populate_module_if_necessary(in_module); - - in_module.for_each_child_stable(|ident, _, name_binding| { + in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { // abort if the module is already found or if name_binding is private external if result.is_some() || !name_binding.vis.is_visible_locally() { return @@ -750,10 +747,8 @@ impl<'a> LateResolutionVisitor<'a, '_> { fn collect_enum_variants(&mut self, def_id: DefId) -> Option> { self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| { - self.r.populate_module_if_necessary(enum_module); - let mut variants = Vec::new(); - enum_module.for_each_child_stable(|ident, _, name_binding| { + enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { if let Res::Def(DefKind::Variant, _) = name_binding.res() { let mut segms = enum_import_suggestion.path.segments.clone(); segms.push(ast::PathSegment::from_ident(ident)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9b5eb51eb582d..12c4f5bfe8e61 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -431,6 +431,8 @@ impl ModuleKind { } } +type Resolutions<'a> = RefCell>>>; + /// One node in the tree of modules. pub struct ModuleData<'a> { parent: Option>, @@ -439,7 +441,11 @@ pub struct ModuleData<'a> { // The def id of the closest normal module (`mod`) ancestor (including this module). normal_ancestor_id: DefId, - resolutions: RefCell>>>, + // Mapping between names and their (possibly in-progress) resolutions in this module. + // Resolutions in modules from other crates are not populated until accessed. + lazy_resolutions: Resolutions<'a>, + // True if this is a module from other crate that needs to be populated on access. + populate_on_access: Cell, // Macro invocations that can expand into items in this module. unresolved_invocations: RefCell>, @@ -452,11 +458,6 @@ pub struct ModuleData<'a> { // Used to memoize the traits in this module for faster searches through all traits in scope. traits: RefCell)]>>>, - // Whether this module is populated. If not populated, any attempt to - // access the children must be preceded with a - // `populate_module_if_necessary` call. - populated: Cell, - /// Span of the module itself. Used for error reporting. span: Span, @@ -475,30 +476,34 @@ impl<'a> ModuleData<'a> { parent, kind, normal_ancestor_id, - resolutions: Default::default(), + lazy_resolutions: Default::default(), + populate_on_access: Cell::new(!normal_ancestor_id.is_local()), unresolved_invocations: Default::default(), no_implicit_prelude: false, glob_importers: RefCell::new(Vec::new()), globs: RefCell::new(Vec::new()), traits: RefCell::new(None), - populated: Cell::new(normal_ancestor_id.is_local()), span, expansion, } } - fn for_each_child)>(&self, mut f: F) { - for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() { - name_resolution.borrow().binding.map(|binding| f(ident, ns, binding)); + fn for_each_child(&'a self, resolver: &mut R, mut f: F) + where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) + { + for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { + name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); } } - fn for_each_child_stable)>(&self, mut f: F) { - let resolutions = self.resolutions.borrow(); + fn for_each_child_stable(&'a self, resolver: &mut R, mut f: F) + where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) + { + let resolutions = resolver.as_mut().resolutions(self).borrow(); let mut resolutions = resolutions.iter().collect::>(); resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns)); for &(&(ident, ns), &resolution) in resolutions.iter() { - resolution.borrow().binding.map(|binding| f(ident, ns, binding)); + resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); } } @@ -983,6 +988,10 @@ impl<'a> ResolverArenas<'a> { } } +impl<'a> AsMut> for Resolver<'a> { + fn as_mut(&mut self) -> &mut Resolver<'a> { self } +} + impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { match id.krate { @@ -1248,6 +1257,20 @@ impl<'a> Resolver<'a> { self.arenas.alloc_module(module) } + fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { + if module.populate_on_access.get() { + module.populate_on_access.set(false); + self.build_reduced_graph_external(module); + } + &module.lazy_resolutions + } + + fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace) + -> &'a RefCell> { + *self.resolutions(module).borrow_mut().entry((ident.modern(), ns)) + .or_insert_with(|| self.arenas.alloc_name_resolution()) + } + fn record_use(&mut self, ident: Ident, ns: Namespace, used_binding: &'a NameBinding<'a>, is_lexical_scope: bool) { if let Some((b2, kind)) = used_binding.ambiguity { @@ -2634,7 +2657,6 @@ impl<'a> Resolver<'a> { return None; }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); - self.populate_module_if_necessary(&crate_root); Some((crate_root, ty::Visibility::Public, DUMMY_SP, ExpnId::root()) .to_name_binding(self.arenas)) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 079145e816cd5..6f49377c187aa 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -8,7 +8,6 @@ use crate::{ModuleOrUniformRoot, KNOWN_TOOLS}; use crate::Namespace::*; use crate::resolve_imports::ImportResolver; use rustc::hir::def::{self, DefKind, NonMacroAttrKind}; -use rustc::hir::map::DefCollector; use rustc::middle::stability; use rustc::{ty, lint, span_bug}; use syntax::ast::{self, Ident}; @@ -131,7 +130,6 @@ impl<'a> base::Resolver for Resolver<'a> { parent_scope.module.unresolved_invocations.borrow_mut().extend(derives); // Integrate the new AST fragment into all the definition and module structures. - fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expansion)); let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 693893e9ef13b..b49f186870669 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -7,9 +7,8 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope use crate::Determinacy::{self, *}; use crate::Namespace::{self, TypeNS, MacroNS}; use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use crate::{Resolver, ResolutionError, Segment}; +use crate::{Resolver, ResolutionError, Segment, ModuleKind}; use crate::{names_to_string, module_to_string}; -use crate::ModuleKind; use crate::diagnostics::Suggestion; use errors::Applicability; @@ -37,7 +36,7 @@ use syntax_pos::{MultiSpan, Span}; use log::*; -use std::cell::{Cell, RefCell}; +use std::cell::Cell; use std::{mem, ptr}; type Res = def::Res; @@ -161,12 +160,6 @@ impl<'a> NameResolution<'a> { } impl<'a> Resolver<'a> { - crate fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace) - -> &'a RefCell> { - *module.resolutions.borrow_mut().entry((ident.modern(), ns)) - .or_insert_with(|| self.arenas.alloc_name_resolution()) - } - crate fn resolve_ident_in_module_unadjusted( &mut self, module: ModuleOrUniformRoot<'a>, @@ -242,8 +235,6 @@ impl<'a> Resolver<'a> { } }; - self.populate_module_if_necessary(module); - let resolution = self.resolution(module, ident, ns) .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. @@ -1027,7 +1018,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return if all_ns_failed { let resolutions = match module { - ModuleOrUniformRoot::Module(module) => Some(module.resolutions.borrow()), + ModuleOrUniformRoot::Module(module) => + Some(self.r.resolutions(module).borrow()), _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); @@ -1265,8 +1257,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } }; - self.r.populate_module_if_necessary(module); - if module.is_trait() { self.r.session.span_err(directive.span, "items in traits are not importable."); return; @@ -1282,8 +1272,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. - let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| { - resolution.borrow().binding().map(|binding| (ident, binding)) + let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| { + resolution.borrow().binding().map(|binding| (*ident, binding)) }).collect::>(); for ((mut ident, ns), binding) in bindings { let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { @@ -1310,7 +1300,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - for (&(ident, ns), resolution) in module.resolutions.borrow().iter() { + for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() { let resolution = &mut *resolution.borrow_mut(); let binding = match resolution.binding { Some(binding) => binding, @@ -1369,8 +1359,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; - let resolutions = imported_module.parent.expect("parent should exist") - .resolutions.borrow(); + let parent_module = imported_module.parent.expect("parent should exist"); + let resolutions = self.r.resolutions(parent_module).borrow(); let enum_path_segment_index = directive.module_path.len() - 1; let enum_ident = directive.module_path[enum_path_segment_index].ident; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 8bb24eef5e94c..dfbf8bcd0f60f 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -67,7 +67,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { match intrinsic { "size_of" | "min_align_of" | "needs_drop" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | - "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" | @@ -314,7 +314,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem) { (1, vec![param(0), param(0)], param(0)), "unchecked_add" | "unchecked_sub" | "unchecked_mul" => (1, vec![param(0), param(0)], param(0)), - "overflowing_add" | "overflowing_sub" | "overflowing_mul" => + "wrapping_add" | "wrapping_sub" | "wrapping_mul" => (1, vec![param(0), param(0)], param(0)), "saturating_add" | "saturating_sub" => (1, vec![param(0), param(0)], param(0)), diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8a56ae13b6f6e..1a87a903156d2 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -30,7 +30,6 @@ use crate::tokenstream::TokenTree; use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; use log::debug; @@ -2088,11 +2087,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "type ascription is experimental"); } } - ast::ExprKind::Yield(..) => { - gate_feature_post!(&self, generators, - e.span, - "yield syntax is experimental"); - } ast::ExprKind::TryBlock(_) => { gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental"); } @@ -2427,10 +2421,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], features } -fn for_each_in_lock(vec: &Lock>, f: impl Fn(&T)) { - vec.borrow().iter().for_each(f); -} - pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, @@ -2443,26 +2433,16 @@ pub fn check_crate(krate: &ast::Crate, plugin_attributes, }; - for_each_in_lock(&sess.param_attr_spans, |span| gate_feature!( - &ctx, - param_attrs, - *span, - "attributes on function parameters are unstable" - )); - - for_each_in_lock(&sess.let_chains_spans, |span| gate_feature!( - &ctx, - let_chains, - *span, - "`let` expressions in this position are experimental" - )); - - for_each_in_lock(&sess.async_closure_spans, |span| gate_feature!( - &ctx, - async_closure, - *span, - "async closures are unstable" - )); + macro_rules! gate_all { + ($spans:ident, $gate:ident, $msg:literal) => { + for span in &*sess.$spans.borrow() { gate_feature!(&ctx, $gate, *span, $msg); } + } + } + + gate_all!(param_attr_spans, param_attrs, "attributes on function parameters are unstable"); + gate_all!(let_chains_spans, let_chains, "`let` expressions in this position are experimental"); + gate_all!(async_closure_spans, async_closure, "async closures are unstable"); + gate_all!(yield_spans, generators, "yield syntax is experimental"); let visitor = &mut PostExpansionVisitor { context: &ctx, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 26f78b9c5c784..9088f929372c9 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -63,6 +63,8 @@ pub struct ParseSess { pub let_chains_spans: Lock>, // Places where `async || ..` exprs were used and should be feature gated. pub async_closure_spans: Lock>, + // Places where `yield e?` exprs were used and should be feature gated. + pub yield_spans: Lock>, pub injected_crate_name: Once, } @@ -92,6 +94,7 @@ impl ParseSess { param_attr_spans: Lock::new(Vec::new()), let_chains_spans: Lock::new(Vec::new()), async_closure_spans: Lock::new(Vec::new()), + yield_spans: Lock::new(Vec::new()), injected_crate_name: Once::new(), } } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index f4b6a926734fb..ccc6bd1506709 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -997,6 +997,9 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } + + let span = lo.to(hi); + self.sess.yield_spans.borrow_mut().push(span); } else if self.eat_keyword(kw::Let) { return self.parse_let_expr(attrs); } else if is_span_rust_2018 && self.eat_keyword(kw::Await) { diff --git a/src/test/ui/commandline-argfile-badutf8.args b/src/test/ui/commandline-argfile-badutf8.args new file mode 100644 index 0000000000000..c070b0c2400d8 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.args @@ -0,0 +1,2 @@ +--cfg +unbroken€ \ No newline at end of file diff --git a/src/test/ui/commandline-argfile-badutf8.rs b/src/test/ui/commandline-argfile-badutf8.rs new file mode 100644 index 0000000000000..c017e7b5ea60b --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.rs @@ -0,0 +1,14 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-fail +// normalize-stderr-test: "Argument \d+" -> "Argument $$N" +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-badutf8.stderr b/src/test/ui/commandline-argfile-badutf8.stderr new file mode 100644 index 0000000000000..cd8a03e34eac9 --- /dev/null +++ b/src/test/ui/commandline-argfile-badutf8.stderr @@ -0,0 +1,2 @@ +error: Argument $N is not valid: Utf8 error in $DIR/commandline-argfile-badutf8.args + diff --git a/src/test/ui/commandline-argfile-missing.rs b/src/test/ui/commandline-argfile-missing.rs new file mode 100644 index 0000000000000..ad223feb2d1c1 --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.rs @@ -0,0 +1,15 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-fail +// normalize-stderr-test: "Argument \d+" -> "Argument $$N" +// normalize-stderr-test: "os error \d+" -> "os error $$ERR" +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/commandline-argfile-missing.stderr b/src/test/ui/commandline-argfile-missing.stderr new file mode 100644 index 0000000000000..e33d312e7ce1d --- /dev/null +++ b/src/test/ui/commandline-argfile-missing.stderr @@ -0,0 +1,2 @@ +error: Argument $N is not valid: IO Error: $DIR/commandline-argfile-missing.args: No such file or directory (os error $ERR) + diff --git a/src/test/ui/commandline-argfile.args b/src/test/ui/commandline-argfile.args new file mode 100644 index 0000000000000..972938bf6c8dd --- /dev/null +++ b/src/test/ui/commandline-argfile.args @@ -0,0 +1,2 @@ +--cfg +unbroken \ No newline at end of file diff --git a/src/test/ui/commandline-argfile.rs b/src/test/ui/commandline-argfile.rs new file mode 100644 index 0000000000000..fc1ba0c8d677d --- /dev/null +++ b/src/test/ui/commandline-argfile.rs @@ -0,0 +1,13 @@ +// Check to see if we can get parameters from an @argsfile file +// +// build-pass +// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args + +#[cfg(not(cmdline_set))] +compile_error!("cmdline_set not set"); + +#[cfg(not(unbroken))] +compile_error!("unbroken not set"); + +fn main() { +} diff --git a/src/test/ui/feature-gates/feature-gate-generators.rs b/src/test/ui/feature-gates/feature-gate-generators.rs index cee930fd785b9..382d891feed84 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.rs +++ b/src/test/ui/feature-gates/feature-gate-generators.rs @@ -2,3 +2,9 @@ fn main() { yield true; //~ ERROR yield syntax is experimental //~^ ERROR yield statement outside of generator literal } + +#[cfg(FALSE)] +fn foo() { + yield; //~ ERROR yield syntax is experimental + yield 0; //~ ERROR yield syntax is experimental +} diff --git a/src/test/ui/feature-gates/feature-gate-generators.stderr b/src/test/ui/feature-gates/feature-gate-generators.stderr index cdb056012542b..24b814b410c9d 100644 --- a/src/test/ui/feature-gates/feature-gate-generators.stderr +++ b/src/test/ui/feature-gates/feature-gate-generators.stderr @@ -7,12 +7,30 @@ LL | yield true; = note: for more information, see https://github.com/rust-lang/rust/issues/43122 = help: add `#![feature(generators)]` to the crate attributes to enable +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:8:5 + | +LL | yield; + | ^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + +error[E0658]: yield syntax is experimental + --> $DIR/feature-gate-generators.rs:9:5 + | +LL | yield 0; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/43122 + = help: add `#![feature(generators)]` to the crate attributes to enable + error[E0627]: yield statement outside of generator literal --> $DIR/feature-gate-generators.rs:2:5 | LL | yield true; | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 7fcd2ede31b69..de8efdde737f0 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -4,13 +4,13 @@ error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3f LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h059a991a004536ad) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling-alt(issue_60925::foo::Foo::foo) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs index 89de15cc0f3e4..02438351dbc6e 100644 --- a/src/test/ui/symbol-names/issue-60925.rs +++ b/src/test/ui/symbol-names/issue-60925.rs @@ -20,8 +20,8 @@ mod foo { impl Foo<::llvm::Foo> { #[rustc_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo - //[legacy]~| ERROR demangling(issue_60925::foo::Foo::foo + //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo::foo) //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo) //[v0]~| ERROR demangling(>::foo) //[v0]~| ERROR demangling-alt(>::foo)