From 419185355f86bdb16726965873a4868b2d3eec8d Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 09:44:02 +0200 Subject: [PATCH 01/16] Added the --temps-dir option. --- compiler/rustc_driver/src/lib.rs | 12 +++++++++++- compiler/rustc_interface/src/interface.rs | 7 +++++++ compiler/rustc_interface/src/passes.rs | 7 +++++++ compiler/rustc_interface/src/util.rs | 3 +++ compiler/rustc_session/src/config.rs | 14 ++++++++++++-- src/librustdoc/core.rs | 1 + src/librustdoc/doctest.rs | 1 + 7 files changed, 42 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 1811463420975..0bd0517db4d1c 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -217,6 +217,7 @@ fn run_compiler( let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg")); let (odir, ofile) = make_output(&matches); + let temps_dir = make_temps_dir(&matches); let mut config = interface::Config { opts: sopts, crate_cfg: cfg, @@ -224,6 +225,7 @@ fn run_compiler( input_path: None, output_file: ofile, output_dir: odir, + temps_dir, file_loader, diagnostic_output, stderr: None, @@ -269,6 +271,7 @@ fn run_compiler( None, &compiler.output_dir(), &compiler.output_file(), + &compiler.temps_dir(), ); if should_stop == Compilation::Stop { @@ -297,6 +300,7 @@ fn run_compiler( Some(compiler.input()), compiler.output_dir(), compiler.output_file(), + compiler.temps_dir(), ) .and_then(|| { RustcDefaultCalls::list_metadata( @@ -462,6 +466,11 @@ fn make_output(matches: &getopts::Matches) -> (Option, Option) (odir, ofile) } +// Extract temporary directory from matches. +fn make_temps_dir(matches: &getopts::Matches) -> Option { + matches.opt_str("temps-dir").map(|o| PathBuf::from(&o)) +} + // Extract input (string or file and optional path) from matches. fn make_input( error_format: ErrorOutputType, @@ -651,6 +660,7 @@ impl RustcDefaultCalls { input: Option<&Input>, odir: &Option, ofile: &Option, + temps_dir: &Option, ) -> Compilation { use rustc_session::config::PrintRequest::*; // PrintRequest::NativeStaticLibs is special - printed during linking @@ -692,7 +702,7 @@ impl RustcDefaultCalls { }); let attrs = attrs.as_ref().unwrap(); let t_outputs = rustc_interface::util::build_output_filenames( - input, odir, ofile, attrs, sess, + input, odir, ofile, temps_dir, attrs, sess, ); let id = rustc_session::output::find_crate_name(sess, attrs, input); if *req == PrintRequest::CrateName { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index a1090ee316db4..65937a2fc3ea9 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -35,6 +35,7 @@ pub struct Compiler { pub(crate) input_path: Option, pub(crate) output_dir: Option, pub(crate) output_file: Option, + pub(crate) temps_dir: Option, pub(crate) register_lints: Option>, pub(crate) override_queries: Option, @@ -56,6 +57,9 @@ impl Compiler { pub fn output_file(&self) -> &Option { &self.output_file } + pub fn temps_dir(&self) -> &Option { + &self.temps_dir + } pub fn register_lints(&self) -> &Option> { &self.register_lints } @@ -68,6 +72,7 @@ impl Compiler { &self.input, &self.output_dir, &self.output_file, + &self.temps_dir, &attrs, &sess, ) @@ -134,6 +139,7 @@ pub struct Config { pub input_path: Option, pub output_dir: Option, pub output_file: Option, + pub temps_dir: Option, pub file_loader: Option>, pub diagnostic_output: DiagnosticOutput, @@ -195,6 +201,7 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R input_path: config.input_path, output_dir: config.output_dir, output_file: config.output_file, + temps_dir: config.temps_dir, register_lints: config.register_lints, override_queries: config.override_queries, }; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 9005325f0b42d..40aa49f6290e1 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -660,6 +660,7 @@ pub fn prepare_outputs( &compiler.input, &compiler.output_dir, &compiler.output_file, + &compiler.temps_dir, &krate.attrs, sess, ); @@ -702,6 +703,12 @@ pub fn prepare_outputs( return Err(ErrorReported); } } + if let Some(ref dir) = compiler.temps_dir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by `--temps-dir`"); + return Err(ErrorReported); + } + } } Ok(outputs) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index fd29053433e55..fd48a5ef7eeea 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -645,6 +645,7 @@ pub fn build_output_filenames( input: &Input, odir: &Option, ofile: &Option, + temps_dir: &Option, attrs: &[ast::Attribute], sess: &Session, ) -> OutputFilenames { @@ -667,6 +668,7 @@ pub fn build_output_filenames( dirpath, stem, None, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -695,6 +697,7 @@ pub fn build_output_filenames( out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(), out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(), ofile, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index f517c483758d2..edfe5e6ffc245 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -563,6 +563,7 @@ pub struct OutputFilenames { pub out_directory: PathBuf, filestem: String, pub single_output_file: Option, + pub temps_directory: Option, pub outputs: OutputTypes, } @@ -577,12 +578,14 @@ impl OutputFilenames { out_directory: PathBuf, out_filestem: String, single_output_file: Option, + temps_directory: Option, extra: String, outputs: OutputTypes, ) -> Self { OutputFilenames { out_directory, single_output_file, + temps_directory, outputs, filestem: format!("{}{}", out_filestem, extra), } @@ -628,11 +631,17 @@ impl OutputFilenames { extension.push_str(ext); } - self.with_extension(&extension) + let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); + + self.with_directory_and_extension(&temps_directory, &extension) } pub fn with_extension(&self, extension: &str) -> PathBuf { - let mut path = self.out_directory.join(&self.filestem); + self.with_directory_and_extension(&self.out_directory, extension) + } + + fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { + let mut path = directory.join(&self.filestem); path.set_extension(extension); path } @@ -1071,6 +1080,7 @@ pub fn rustc_short_optgroups() -> Vec { in ", "DIR", ), + opt::opt_s("", "temps-dir", "Write temporary output files to ", "DIR"), opt::opt_s( "", "explain", diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b43916f9f332c..b667733af6e6a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -258,6 +258,7 @@ crate fn create_config( input_path: cpath, output_file: None, output_dir: None, + temps_dir: None, file_loader: None, diagnostic_output: DiagnosticOutput::Default, stderr: None, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 3a4d39e1d7f72..3d4a9f322e6c4 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -92,6 +92,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> { input_path: None, output_file: None, output_dir: None, + temps_dir: None, file_loader: None, diagnostic_output: DiagnosticOutput::Default, stderr: None, From c0e8578c05440dfee8d804e7349c3d99b79c0759 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 13:33:33 +0200 Subject: [PATCH 02/16] Create temps_dir before it's needed. --- compiler/rustc_interface/src/passes.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 40aa49f6290e1..f6f54564220a1 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -691,6 +691,13 @@ pub fn prepare_outputs( } } + if let Some(ref dir) = compiler.temps_dir { + if fs::create_dir_all(dir).is_err() { + sess.err("failed to find or create the directory specified by `--temps-dir`"); + return Err(ErrorReported); + } + } + write_out_deps(sess, boxed_resolver, &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) @@ -703,12 +710,6 @@ pub fn prepare_outputs( return Err(ErrorReported); } } - if let Some(ref dir) = compiler.temps_dir { - if fs::create_dir_all(dir).is_err() { - sess.err("failed to find or create the directory specified by `--temps-dir`"); - return Err(ErrorReported); - } - } } Ok(outputs) From abf9653bb387e13148ffbad17a2d9c22836b22fb Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 13:35:04 +0200 Subject: [PATCH 03/16] Emitted files go to the output dir. --- compiler/rustc_session/src/config.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index edfe5e6ffc245..75153b14d4c9b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -596,7 +596,14 @@ impl OutputFilenames { .get(&flavor) .and_then(|p| p.to_owned()) .or_else(|| self.single_output_file.clone()) - .unwrap_or_else(|| self.temp_path(flavor, None)) + .unwrap_or_else(|| self.output_path(flavor)) + } + + /// Gets the output path where a compilation artifact of the given type + /// should be placed on disk. + pub fn output_path(&self, flavor: OutputType) -> PathBuf { + let extension = flavor.extension(); + self.with_directory_and_extension(&self.out_directory, &extension) } /// Gets the path where a compilation artifact of the given type for the From e146192b610395ced5417155553560d33d593563 Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 14:48:07 +0200 Subject: [PATCH 04/16] Documentation. --- src/doc/rustc/src/command-line-arguments.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7d3cad7988c8c..0a198103b44a0 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -194,6 +194,15 @@ This flag controls the output filename. The outputted crate will be written to this directory. This flag is ignored if the [`-o` flag](#option-o-output) is used. + +## `--temps-dir`: directory to write the intermediate files in + +Intermediate files will be written to this directory. If not set, the output +directory is used. This option is useful if you are running more than one +instance of `rustc` (e.g. with different `--crate-type` settings), and you +need to make sure they are not overwriting each other's intermediate files. +No files are kept unless `-C save-temps=yes` is also set. + ## `--explain`: provide a detailed explanation of an error message From 9a60e4729717c226febb4480b57285cf4cbaf20b Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 15:24:17 +0200 Subject: [PATCH 05/16] Fix test. --- src/test/run-make-fulldeps/issue-19371/foo.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 4acabbb70ede2..626f74a342e37 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -53,6 +53,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { input_path: None, output_file: Some(output), output_dir: None, + temps_dir: None, file_loader: None, diagnostic_output: DiagnosticOutput::Default, stderr: None, From 857b19d3dd69c8f7dc253dfafc5f6663f0f42d4a Mon Sep 17 00:00:00 2001 From: Tor Hovland Date: Sun, 4 Apr 2021 15:54:21 +0200 Subject: [PATCH 06/16] Added a regression test. --- src/test/run-make/issue-10971-temps-dir/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/test/run-make/issue-10971-temps-dir/Makefile diff --git a/src/test/run-make/issue-10971-temps-dir/Makefile b/src/test/run-make/issue-10971-temps-dir/Makefile new file mode 100644 index 0000000000000..6d60e4824b0c0 --- /dev/null +++ b/src/test/run-make/issue-10971-temps-dir/Makefile @@ -0,0 +1,8 @@ +# Regression test for issue #10971 +# Running two invocations in parallel would overwrite each other's temp files. + +all: + touch $(TMPDIR)/lib.rs + + $(RUSTC) --crate-type=lib --temps-dir=$(TMPDIR)/temp1 --out-dir=$(TMPDIR) $(TMPDIR)/lib.rs \ + & $(RUSTC) --crate-type=cdylib --temps-dir=$(TMPDIR)/temp2 --out-dir=$(TMPDIR) $(TMPDIR)/lib.rs From 14f3ec2815e9edae3057641ab8f1371cb7cef094 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 7 Jun 2021 17:42:42 +0200 Subject: [PATCH 07/16] Fix span calculation in format strings --- compiler/rustc_builtin_macros/src/format.rs | 15 ++++++++++++++- src/test/ui/fmt/format-concat-span.rs | 15 +++++++++++++++ src/test/ui/fmt/format-concat-span.stderr | 11 +++++++++++ src/test/ui/fmt/issue-86085.rs | 6 ++++++ src/test/ui/fmt/issue-86085.stderr | 11 +++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/fmt/format-concat-span.rs create mode 100644 src/test/ui/fmt/format-concat-span.stderr create mode 100644 src/test/ui/fmt/issue-86085.rs create mode 100644 src/test/ui/fmt/issue-86085.stderr diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 7e88b58c0e29d..00f2f37146db6 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -939,6 +939,7 @@ pub fn expand_preparsed_format_args( let msg = "format argument must be a string literal"; let fmt_sp = efmt.span; + let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_)); let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) { Ok(mut fmt) if append_newline => { fmt.0 = Symbol::intern(&format!("{}\n", fmt.0)); @@ -989,7 +990,19 @@ pub fn expand_preparsed_format_args( if !parser.errors.is_empty() { let err = parser.errors.remove(0); - let sp = fmt_span.from_inner(err.span); + let sp = if efmt_kind_is_lit { + fmt_span.from_inner(err.span) + } else { + // The format string could be another macro invocation, e.g.: + // format!(concat!("abc", "{}"), 4); + // However, `err.span` is an inner span relative to the *result* of + // the macro invocation, which is why we would get a nonsensical + // result calling `fmt_span.from_inner(err.span)` as above, and + // might even end up inside a multibyte character (issue #86085). + // Therefore, we conservatively report the error for the entire + // argument span here. + fmt_span + }; let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description)); e.span_label(sp, err.label + " in format string"); if let Some(note) = err.note { diff --git a/src/test/ui/fmt/format-concat-span.rs b/src/test/ui/fmt/format-concat-span.rs new file mode 100644 index 0000000000000..ce92df0ad92bd --- /dev/null +++ b/src/test/ui/fmt/format-concat-span.rs @@ -0,0 +1,15 @@ +// If the format string is another macro invocation, rustc would previously +// compute nonsensical spans, such as: +// +// error: invalid format string: unmatched `}` found +// --> test.rs:2:17 +// | +// 2 | format!(concat!("abc}")); +// | ^ unmatched `}` in format string +// +// This test checks that this behavior has been fixed. + +fn main() { + format!(concat!("abc}")); + //~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/src/test/ui/fmt/format-concat-span.stderr b/src/test/ui/fmt/format-concat-span.stderr new file mode 100644 index 0000000000000..da46f40abcb97 --- /dev/null +++ b/src/test/ui/fmt/format-concat-span.stderr @@ -0,0 +1,11 @@ +error: invalid format string: unmatched `}` found + --> $DIR/format-concat-span.rs:13:13 + | +LL | format!(concat!("abc}")); + | ^^^^^^^^^^^^^^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/fmt/issue-86085.rs b/src/test/ui/fmt/issue-86085.rs new file mode 100644 index 0000000000000..63d42b76969cd --- /dev/null +++ b/src/test/ui/fmt/issue-86085.rs @@ -0,0 +1,6 @@ +// Tests for an ICE with the fuzzed input below. + +fn main ( ) { +format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" ) ) ; +//~^ ERROR: invalid format string: unmatched `}` found +} diff --git a/src/test/ui/fmt/issue-86085.stderr b/src/test/ui/fmt/issue-86085.stderr new file mode 100644 index 0000000000000..ee7d8a5cc237a --- /dev/null +++ b/src/test/ui/fmt/issue-86085.stderr @@ -0,0 +1,11 @@ +error: invalid format string: unmatched `}` found + --> $DIR/issue-86085.rs:4:12 + | +LL | format ! ( concat ! ( r#"lJ𐏿Æ�.𐏿�"# , "r} {}" ) ) ; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string + | + = note: if you intended to print `}`, you can escape it using `}}` + = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + From 7728476239114f9915d4dc24cf2df6b2ce1e7046 Mon Sep 17 00:00:00 2001 From: Adrien Morison Date: Tue, 8 Jun 2021 16:49:57 +0100 Subject: [PATCH 08/16] Link reference in `dyn` keyword documentation The "read more" sentence formatted "object safety" as inline code instead of providing a link to more information. This PR adds a link to the Reference about this matter, as well as the page regarding trait objects. --- library/std/src/keyword_docs.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index ba2b8b6955d66..cb5f619ba8d93 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2259,6 +2259,9 @@ mod await_keyword {} /// At run-time, when a method needs to be called on the `dyn Trait`, the vtable is consulted to get /// the function pointer and then that function pointer is called. /// +/// See the Reference for more information on [trait objects][ref-trait-obj] +/// and [object safety][ref-obj-safety]. +/// /// ## Trade-offs /// /// The above indirection is the additional runtime cost of calling a function on a `dyn Trait`. @@ -2267,9 +2270,9 @@ mod await_keyword {} /// However, `dyn Trait` is likely to produce smaller code than `impl Trait` / generic parameters as /// the method won't be duplicated for each concrete type. /// -/// Read more about `object safety` and [trait object]s. -/// /// [trait object]: ../book/ch17-02-trait-objects.html +/// [ref-trait-obj]: ../reference/types/trait-object.html +/// [ref-obj-safety]: ../reference/items/traits.html#object-safety /// [erased]: https://en.wikipedia.org/wiki/Type_erasure mod dyn_keyword {} From 3802d573c36902dbab68199beee3041514efd8bd Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 8 Jun 2021 08:51:44 -0700 Subject: [PATCH 09/16] Mention the Borrow guarantee on the Hash implementations for Array and Vec To remind people like me who forget about it and send PRs to make them different, and to (probably) get a test failure if the code is changed to no longer uphold it. --- library/alloc/src/vec/mod.rs | 17 +++++++++++++++++ library/core/src/array/mod.rs | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 105c60e7bf085..aff27b7af306d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2407,6 +2407,23 @@ impl Clone for Vec { } } +/// The hash of a vector is the same as that of the corresponding slice, +/// as required by the `core::borrow::Borrow` implementation. +/// +/// ``` +/// use std::hash::{BuildHasher, Hash, Hasher}; +/// +/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 { +/// let mut h = b.build_hasher(); +/// x.hash(&mut h); +/// h.finish() +/// } +/// +/// let b = std::collections::hash_map::RandomState::new(); +/// let v: Vec = vec![0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(hash_of(v, &b), hash_of(s, &b)); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] impl Hash for Vec { #[inline] diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index e25d006d213c7..aa7f71cf85b5f 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -139,6 +139,23 @@ impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] { } } +/// The hash of an array is the same as that of the corresponding slice, +/// as required by the `Borrow` implementation. +/// +/// ``` +/// use std::hash::{BuildHasher, Hash, Hasher}; +/// +/// fn hash_of(x: impl Hash, b: &impl BuildHasher) -> u64 { +/// let mut h = b.build_hasher(); +/// x.hash(&mut h); +/// h.finish() +/// } +/// +/// let b = std::collections::hash_map::RandomState::new(); +/// let a: [u8; 3] = [0xa8, 0x3c, 0x09]; +/// let s: &[u8] = &[0xa8, 0x3c, 0x09]; +/// assert_eq!(hash_of(a, &b), hash_of(s, &b)); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] impl Hash for [T; N] { fn hash(&self, state: &mut H) { From 78df1b8284b4b77720fb2436818c70920134354c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 16 Jun 2021 07:18:14 +0900 Subject: [PATCH 10/16] Mention #79078 on compatibility notes of 1.52 --- RELEASES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 8adc450ac9869..2e9a66c65939a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -320,6 +320,7 @@ Compatibility Notes - [Rustc now catches more cases of `pub_use_of_private_extern_crate`][80763] - [Changes in how proc macros handle whitespace may lead to panics when used with older `proc-macro-hack` versions. A `cargo update` should be sufficient to fix this in all cases.][84136] +- [Turn `#[derive]` into a regular macro attribute][79078] [84136]: https://github.com/rust-lang/rust/issues/84136 [80763]: https://github.com/rust-lang/rust/pull/80763 @@ -346,6 +347,7 @@ Compatibility Notes [78429]: https://github.com/rust-lang/rust/pull/78429 [82733]: https://github.com/rust-lang/rust/pull/82733 [82594]: https://github.com/rust-lang/rust/pull/82594 +[79078]: https://github.com/rust-lang/rust/pull/79078 [cargo/9181]: https://github.com/rust-lang/cargo/pull/9181 [`char::MAX`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.MAX [`char::REPLACEMENT_CHARACTER`]: https://doc.rust-lang.org/std/primitive.char.html#associatedconstant.REPLACEMENT_CHARACTER From c8a8a23a31e9e4831ccab4efbc085852b7a86fa5 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 16 Jun 2021 09:44:47 +0900 Subject: [PATCH 11/16] Do not emit invalid suggestions on multiple mutable borrow errors --- .../diagnostics/conflict_errors.rs | 8 ++++++ .../diagnostics/explain_borrow.rs | 26 +++++++++++++------ src/test/ui/borrowck/issue-85581.rs | 15 +++++++++++ src/test/ui/borrowck/issue-85581.stderr | 17 ++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/borrowck/issue-85581.rs create mode 100644 src/test/ui/borrowck/issue-85581.stderr diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 8b0761889b834..a0c9b43d5afee 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -453,6 +453,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", Some(borrow_span), + None, ); err.buffer(&mut self.errors_buffer); } @@ -498,6 +499,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); err } @@ -718,6 +720,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, first_borrow_desc, None, + Some((issued_span, span)), ); err @@ -1076,6 +1079,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); } } else { @@ -1093,6 +1097,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); } @@ -1158,6 +1163,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); err.buffer(&mut self.errors_buffer); @@ -1236,6 +1242,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); let within = if borrow_spans.for_generator() { " by generator" } else { "" }; @@ -1614,6 +1621,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut err, "", None, + None, ); self.explain_deref_coercion(loan, &mut err); diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index e9f1ecb9bbc81..76de010d1393b 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -66,6 +66,7 @@ impl BorrowExplanation { err: &mut DiagnosticBuilder<'_>, borrow_desc: &str, borrow_span: Option, + multiple_borrow_span: Option<(Span, Span)>, ) { match *self { BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => { @@ -192,14 +193,23 @@ impl BorrowExplanation { if let Some(info) = &local_decl.is_block_tail { if info.tail_result_is_ignored { - err.span_suggestion_verbose( - info.span.shrink_to_hi(), - "consider adding semicolon after the expression so its \ - temporaries are dropped sooner, before the local variables \ - declared by the block are dropped", - ";".to_string(), - Applicability::MaybeIncorrect, - ); + // #85581: If the first mutable borrow's scope contains + // the second borrow, this suggestion isn't helpful. + if !multiple_borrow_span + .map(|(old, new)| { + old.to(info.span.shrink_to_hi()).contains(new) + }) + .unwrap_or(false) + { + err.span_suggestion_verbose( + info.span.shrink_to_hi(), + "consider adding semicolon after the expression so its \ + temporaries are dropped sooner, before the local variables \ + declared by the block are dropped", + ";".to_string(), + Applicability::MaybeIncorrect, + ); + } } else { err.note( "the temporary is part of an expression at the end of a \ diff --git a/src/test/ui/borrowck/issue-85581.rs b/src/test/ui/borrowck/issue-85581.rs new file mode 100644 index 0000000000000..ccc120c5421f5 --- /dev/null +++ b/src/test/ui/borrowck/issue-85581.rs @@ -0,0 +1,15 @@ +// Regression test of #85581. +// Checks not to suggest to add `;` when the second mutable borrow +// is in the first's scope. + +use std::collections::BinaryHeap; + +fn foo(heap: &mut BinaryHeap) { + match heap.peek_mut() { + Some(_) => { heap.pop(); }, + //~^ ERROR: cannot borrow `*heap` as mutable more than once at a time + None => (), + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-85581.stderr b/src/test/ui/borrowck/issue-85581.stderr new file mode 100644 index 0000000000000..29c0429f2a046 --- /dev/null +++ b/src/test/ui/borrowck/issue-85581.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `*heap` as mutable more than once at a time + --> $DIR/issue-85581.rs:9:22 + | +LL | match heap.peek_mut() { + | --------------- + | | + | first mutable borrow occurs here + | a temporary with access to the first borrow is created here ... +LL | Some(_) => { heap.pop(); }, + | ^^^^ second mutable borrow occurs here +... +LL | } + | - ... and the first borrow might be used here, when that temporary is dropped and runs the destructor for type `Option>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0499`. From 280d19395d264d295e6d8d4f3c7cef368e04aad0 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 16 Jun 2021 16:33:03 +0900 Subject: [PATCH 12/16] Remove `projection_ty_from_predicates` --- .../rustc_middle/src/dep_graph/dep_node.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 ---- compiler/rustc_typeck/src/collect.rs | 24 ------------------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 8476929eaeced..aa54d1ae7b9d1 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode; // required that their size stay the same, but we don't want to change // it inadvertently. This assert just ensures we're aware of any change. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 18); +static_assert_size!(DepNode, 17); #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] static_assert_size!(DepNode, 24); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 0860520ef9dfe..a73d193408030 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -191,10 +191,6 @@ rustc_queries! { desc { |tcx| "elaborating item bounds for `{}`", tcx.def_path_str(key) } } - query projection_ty_from_predicates(key: (DefId, DefId)) -> Option> { - desc { |tcx| "finding projection type inside predicates of `{}`", tcx.def_path_str(key.0) } - } - query native_libraries(_: CrateNum) -> Lrc> { desc { "looking up the native libraries of a linked crate" } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ee3ac3b62d9ec..55de04bfba0fe 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -77,7 +77,6 @@ pub fn provide(providers: &mut Providers) { generics_of, predicates_of, predicates_defined_on, - projection_ty_from_predicates, explicit_predicates_of, super_predicates_of, super_predicates_that_define_assoc_type, @@ -2352,29 +2351,6 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat } } -fn projection_ty_from_predicates( - tcx: TyCtxt<'tcx>, - key: ( - // ty_def_id - DefId, - // def_id of `N` in `::N` - DefId, - ), -) -> Option> { - let (ty_def_id, item_def_id) = key; - let mut projection_ty = None; - for (predicate, _) in tcx.predicates_of(ty_def_id).predicates { - if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() - { - if item_def_id == projection_predicate.projection_ty.item_def_id { - projection_ty = Some(projection_predicate.projection_ty); - break; - } - } - } - projection_ty -} - /// Converts a specific `GenericBound` from the AST into a set of /// predicates that apply to the self type. A vector is returned /// because this can be anywhere from zero predicates (`T: ?Sized` adds no From d828eadd7a29c3aed92704358f1742ba5aa225d8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 16 Jun 2021 18:47:26 +0900 Subject: [PATCH 13/16] Remove invalid suggestions for assoc consts on placeholder type error --- compiler/rustc_typeck/src/collect.rs | 26 ++++++++++++------- .../ui/typeck/type-placeholder-fn-in-const.rs | 14 ++++++++++ .../type-placeholder-fn-in-const.stderr | 21 +++++++++++++++ 3 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/typeck/type-placeholder-fn-in-const.rs create mode 100644 src/test/ui/typeck/type-placeholder-fn-in-const.stderr diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ee3ac3b62d9ec..05a0a5a6cc04e 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -180,8 +180,7 @@ crate fn placeholder_type_error( // Suggest, but only if it is not a function in const or static if suggest { let mut is_fn = false; - let mut is_const = false; - let mut is_static = false; + let mut is_const_or_static = false; if let Some(hir_ty) = hir_ty { if let hir::TyKind::BareFn(_) = hir_ty.kind { @@ -191,19 +190,26 @@ crate fn placeholder_type_error( let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); let parent_node = tcx.hir().get(parent_id); - if let hir::Node::Item(item) = parent_node { - if let hir::ItemKind::Const(_, _) = item.kind { - is_const = true; - } else if let hir::ItemKind::Static(_, _, _) = item.kind { - is_static = true; - } - } + is_const_or_static = match parent_node { + Node::Item(&hir::Item { + kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), + .. + }) + | Node::TraitItem(&hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) + | Node::ImplItem(&hir::ImplItem { + kind: hir::ImplItemKind::Const(..), .. + }) => true, + _ => false, + }; } } // if function is wrapped around a const or static, // then don't show the suggestion - if !(is_fn && (is_const || is_static)) { + if !(is_fn && is_const_or_static) { err.multipart_suggestion( "use type parameters instead", sugg, diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.rs b/src/test/ui/typeck/type-placeholder-fn-in-const.rs new file mode 100644 index 0000000000000..c27edc8485b92 --- /dev/null +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.rs @@ -0,0 +1,14 @@ +struct MyStruct; + +trait Test { + const TEST: fn() -> _; + //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures [E0121] + //~| ERROR: the type placeholder `_` is not allowed within types on item signatures [E0121] +} + +impl Test for MyStruct { + const TEST: fn() -> _ = 42; + //~^ ERROR: the type placeholder `_` is not allowed within types on item signatures [E0121] +} + +fn main() {} diff --git a/src/test/ui/typeck/type-placeholder-fn-in-const.stderr b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr new file mode 100644 index 0000000000000..662871779a10e --- /dev/null +++ b/src/test/ui/typeck/type-placeholder-fn-in-const.stderr @@ -0,0 +1,21 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/type-placeholder-fn-in-const.rs:4:25 + | +LL | const TEST: fn() -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/type-placeholder-fn-in-const.rs:10:25 + | +LL | const TEST: fn() -> _ = 42; + | ^ not allowed in type signatures + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. From fb06d9e0cdffd8b6bcb1eb7f41f0237038611a17 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 16 Jun 2021 18:49:40 +0900 Subject: [PATCH 14/16] Move some typeck-related tests to the typeck dir --- src/test/ui/{issues => typeck}/issue-74086.rs | 0 src/test/ui/{issues => typeck}/issue-74086.stderr | 0 src/test/ui/{issues => typeck}/issue-81885.rs | 0 src/test/ui/{issues => typeck}/issue-81885.stderr | 0 src/test/ui/{ => typeck}/typeck-closure-to-unsafe-fn-ptr.rs | 0 src/test/ui/{ => typeck}/typeck-fn-to-unsafe-fn-ptr.rs | 0 src/test/ui/{ => typeck}/typeck_type_placeholder_1.rs | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{issues => typeck}/issue-74086.rs (100%) rename src/test/ui/{issues => typeck}/issue-74086.stderr (100%) rename src/test/ui/{issues => typeck}/issue-81885.rs (100%) rename src/test/ui/{issues => typeck}/issue-81885.stderr (100%) rename src/test/ui/{ => typeck}/typeck-closure-to-unsafe-fn-ptr.rs (100%) rename src/test/ui/{ => typeck}/typeck-fn-to-unsafe-fn-ptr.rs (100%) rename src/test/ui/{ => typeck}/typeck_type_placeholder_1.rs (100%) diff --git a/src/test/ui/issues/issue-74086.rs b/src/test/ui/typeck/issue-74086.rs similarity index 100% rename from src/test/ui/issues/issue-74086.rs rename to src/test/ui/typeck/issue-74086.rs diff --git a/src/test/ui/issues/issue-74086.stderr b/src/test/ui/typeck/issue-74086.stderr similarity index 100% rename from src/test/ui/issues/issue-74086.stderr rename to src/test/ui/typeck/issue-74086.stderr diff --git a/src/test/ui/issues/issue-81885.rs b/src/test/ui/typeck/issue-81885.rs similarity index 100% rename from src/test/ui/issues/issue-81885.rs rename to src/test/ui/typeck/issue-81885.rs diff --git a/src/test/ui/issues/issue-81885.stderr b/src/test/ui/typeck/issue-81885.stderr similarity index 100% rename from src/test/ui/issues/issue-81885.stderr rename to src/test/ui/typeck/issue-81885.stderr diff --git a/src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs similarity index 100% rename from src/test/ui/typeck-closure-to-unsafe-fn-ptr.rs rename to src/test/ui/typeck/typeck-closure-to-unsafe-fn-ptr.rs diff --git a/src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs b/src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs similarity index 100% rename from src/test/ui/typeck-fn-to-unsafe-fn-ptr.rs rename to src/test/ui/typeck/typeck-fn-to-unsafe-fn-ptr.rs diff --git a/src/test/ui/typeck_type_placeholder_1.rs b/src/test/ui/typeck/typeck_type_placeholder_1.rs similarity index 100% rename from src/test/ui/typeck_type_placeholder_1.rs rename to src/test/ui/typeck/typeck_type_placeholder_1.rs From a2a006d1cc7d529aaccba48ec7986f76dfc14e60 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 16 Jun 2021 14:39:44 +0200 Subject: [PATCH 15/16] Add missing backslashes to prevent unwanted backlines in rustdoc HTML --- src/librustdoc/html/render/print_item.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 04464b622d7a3..88ec172a18bca 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -864,7 +864,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni if fields.peek().is_some() { write!( w, - "

+ "

\ Fields

" ); for (field, ty) in fields { @@ -953,8 +953,8 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum if !e.variants.is_empty() { write!( w, - "

- Variants{}

\n", + "

\ + Variants{}

", document_non_exhaustive_header(it) ); document_non_exhaustive(w, it); @@ -1139,7 +1139,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St if fields.peek().is_some() { write!( w, - "

+ "

\ Fields{}

", document_non_exhaustive_header(it) ); From 770e8cc01e783be7e4620bc0148ada14a2c7a4df Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Wed, 16 Jun 2021 19:20:15 +0300 Subject: [PATCH 16/16] Typo correction: s/is/its --- library/core/src/ptr/non_null.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 1c65518af04f5..3ab40f1faa1d6 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -194,7 +194,7 @@ impl NonNull { } } - /// Decompose a (possibly wide) pointer into is address and metadata components. + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`NonNull::from_raw_parts`]. #[unstable(feature = "ptr_metadata", issue = "81513")]