diff --git a/RELEASES.md b/RELEASES.md index a49091373df9f..da8333e6287ca 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -306,6 +306,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 @@ -332,6 +333,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 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/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index b943977e4c2bb..fac808075ba4a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -216,6 +216,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, @@ -223,6 +224,7 @@ fn run_compiler( input_path: None, output_file: ofile, output_dir: odir, + temps_dir, file_loader, diagnostic_output, stderr: None, @@ -268,6 +270,7 @@ fn run_compiler( None, &compiler.output_dir(), &compiler.output_file(), + &compiler.temps_dir(), ); if should_stop == Compilation::Stop { @@ -296,6 +299,7 @@ fn run_compiler( Some(compiler.input()), compiler.output_dir(), compiler.output_file(), + compiler.temps_dir(), ) .and_then(|| { RustcDefaultCalls::list_metadata( @@ -461,6 +465,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, @@ -650,6 +659,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 @@ -691,7 +701,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 9e3e96df3a7f2..08218902631fb 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -709,6 +709,7 @@ pub fn prepare_outputs( &compiler.input, &compiler.output_dir, &compiler.output_file, + &compiler.temps_dir, &krate.attrs, sess, ); @@ -739,6 +740,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) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 6485fbebd665f..969c3f47e262d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -636,6 +636,7 @@ pub fn build_output_filenames( input: &Input, odir: &Option, ofile: &Option, + temps_dir: &Option, attrs: &[ast::Attribute], sess: &Session, ) -> OutputFilenames { @@ -658,6 +659,7 @@ pub fn build_output_filenames( dirpath, stem, None, + temps_dir.clone(), sess.opts.cg.extra_filename.clone(), sess.opts.output_types.clone(), ) @@ -686,6 +688,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_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 a6f9a7c96f0a5..dda407940e3c3 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_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/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index af24358fe645f..cbeceace469b3 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), } @@ -593,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 @@ -628,11 +638,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 } @@ -1072,6 +1088,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/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index ee3ac3b62d9ec..248669a2c0cb8 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, @@ -180,8 +179,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 +189,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, @@ -2352,29 +2357,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 diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4a1d564e2ab87..b59d2977add95 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 37af3557fdd51..f44e22b3dbd7c 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) { 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")] diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index c2d21ad23ac19..a609567ce93f3 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2256,6 +2256,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`. @@ -2264,9 +2267,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 {} 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 diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c3d9c4ea7f25a..13d7bbf4b3cec 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -259,6 +259,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 88e2f6048e9c7..80c3851b7714e 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, 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) ); 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, 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 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`. 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 + 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/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`. 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