diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 478f5d30a255c..491463865b5db 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -14,7 +14,7 @@ use cranelift_codegen::isa::CallConv; use cranelift_module::ModuleError; use rustc_abi::{CanonAbi, ExternAbi, X86Call}; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; -use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; +use rustc_codegen_ssa::diagnostics::CompilerBuiltinsCannotCall; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 0e3fa72fbcfb3..184db4cb25778 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type}; use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; -use rustc_codegen_ssa::errors as ssa_errors; +use rustc_codegen_ssa::diagnostics as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 06fbd287435d6..09ad3254e5714 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -8,7 +8,7 @@ use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, Unary use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 82ef99703b253..1416f4eec9c4a 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -7,8 +7,8 @@ use rustc_abi::{Align, Size}; use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; #[cfg(feature = "master")] -use rustc_codegen_ssa::errors::ExpectedPointerMutability; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::diagnostics::ExpectedPointerMutability; +use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 7ea30a5b4db6d..c018ab23c849a 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,7 +8,7 @@ use std::str; use rustc_abi::{HasDataLayout, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; -use rustc_codegen_ssa::errors as ssa_errors; +use rustc_codegen_ssa::diagnostics as ssa_errors; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::FxHashMap; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 0d11f1e4fb69b..edf943c81a755 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -9,7 +9,7 @@ use rustc_abi::{ use rustc_codegen_ssa::RetagInfo; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; +use rustc_codegen_ssa::diagnostics::{ExpectedPointerMutability, InvalidMonomorphization}; use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index f34a7b956e040..a25131c5ff9b4 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -37,7 +37,7 @@ use rustc_session::Session; use rustc_span::{Span, Symbol}; use tracing::debug; -use crate::errors; +use crate::diagnostics; #[allow(missing_docs)] pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTracker)) { @@ -107,7 +107,7 @@ impl<'tcx> AssertModuleSource<'tcx> { | CguFields::PartitionReused { cfg, module }) = cgu_fields; if !self.tcx.sess.opts.unstable_opts.query_dep_graph { - self.tcx.dcx().emit_fatal(errors::MissingQueryDepGraph { span }); + self.tcx.dcx().emit_fatal(diagnostics::MissingQueryDepGraph { span }); } if !self.check_config(cfg) { @@ -120,7 +120,11 @@ impl<'tcx> AssertModuleSource<'tcx> { let crate_name = crate_name.as_str(); if !user_path.starts_with(&crate_name) { - self.tcx.dcx().emit_fatal(errors::MalformedCguName { span, user_path, crate_name }); + self.tcx.dcx().emit_fatal(diagnostics::MalformedCguName { + span, + user_path, + crate_name, + }); } // Split of the "special suffix" if there is one. @@ -149,7 +153,7 @@ impl<'tcx> AssertModuleSource<'tcx> { if !self.available_cgus.contains(&cgu_name) { let cgu_names: Vec<&str> = self.available_cgus.items().map(|cgu| cgu.as_str()).into_sorted_stable_ord(); - self.tcx.dcx().emit_err(errors::NoModuleNamed { + self.tcx.dcx().emit_err(diagnostics::NoModuleNamed { span, user_path, cgu_name, @@ -273,7 +277,7 @@ impl CguReuseTracker { if error { let at_least = if at_least { 1 } else { 0 }; - sess.dcx().emit_err(errors::IncorrectCguReuseType { + sess.dcx().emit_err(diagnostics::IncorrectCguReuseType { span: *error_span, cgu_user_name, actual_reuse, @@ -282,7 +286,7 @@ impl CguReuseTracker { }); } } else { - sess.dcx().emit_fatal(errors::CguNotRecorded { cgu_user_name, cgu_name }); + sess.dcx().emit_fatal(diagnostics::CguNotRecorded { cgu_user_name, cgu_name }); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 1b707a24066e1..104a3de012615 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -10,7 +10,7 @@ pub(super) use rustc_target::spec::apple::OSVersion; use rustc_target::spec::{Arch, Env, Os, Target}; use tracing::debug; -use crate::errors::{XcrunError, XcrunSdkPathWarning}; +use crate::diagnostics::{XcrunError, XcrunSdkPathWarning}; #[cfg(test)] mod tests; diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 4fc516b244857..c4107b4a60f27 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -26,8 +26,8 @@ use super::rmeta_link::{self, RmetaLinkCache}; use super::symbol_edit::{apply_edits, collect_internal_names}; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs -pub use crate::errors::ExtractBundledLibsError; -use crate::errors::{ +pub use crate::diagnostics::ExtractBundledLibsError; +use crate::diagnostics::{ ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile, UnknownArchiveKind, }; @@ -502,7 +502,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { { let actual_kind = archive.kind(); if !archive_kinds_compatible(actual_kind, expected_kind) { - self.sess.dcx().emit_warn(crate::errors::IncompatibleArchiveFormat { + self.sess.dcx().emit_warn(crate::diagnostics::IncompatibleArchiveFormat { path: archive_path.clone(), actual: archive_kind_display_name(actual_kind), expected: archive_kind_display_name(expected_kind), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 45c9495570ed2..539b228e2b4b2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -66,7 +66,7 @@ use super::{apple, rmeta_link, versioned_llvm_target}; use crate::base::needs_allocator_shim_for_linking; use crate::{ CodegenLintLevelSpecs, CompiledModule, CompiledModules, CrateInfo, NativeLib, SymbolExport, - errors, + diagnostics, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -187,7 +187,9 @@ pub fn link_binary( let tmpdir = TempDirBuilder::new() .prefix("rustc") .tempdir_in(output.parent().unwrap_or_else(|| Path::new("."))) - .unwrap_or_else(|error| sess.dcx().emit_fatal(errors::CreateTempDir { error })); + .unwrap_or_else(|error| { + sess.dcx().emit_fatal(diagnostics::CreateTempDir { error }) + }); let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps); let crate_name = format!("{}", crate_info.local_crate_name); @@ -259,11 +261,15 @@ pub fn link_binary( if output.is_stdout() { if output.is_tty() { - sess.dcx().emit_err(errors::BinaryOutputToTty { + sess.dcx().emit_err(diagnostics::BinaryOutputToTty { shorthand: OutputType::Exe.shorthand(), }); } else if let Err(e) = copy_to_stdout(&out_filename) { - sess.dcx().emit_err(errors::CopyPath::new(&out_filename, output.as_path(), e)); + sess.dcx().emit_err(diagnostics::CopyPath::new( + &out_filename, + output.as_path(), + e, + )); } tempfiles_for_stdout_output.push(out_filename); } @@ -327,18 +333,18 @@ pub fn each_linked_rlib( info: &CrateInfo, crate_type: Option, f: &mut dyn FnMut(CrateNum, &Path), -) -> Result<(), errors::LinkRlibError> { +) -> Result<(), diagnostics::LinkRlibError> { let fmts = if let Some(crate_type) = crate_type { let Some(fmts) = info.dependency_formats.get(&crate_type) else { - return Err(errors::LinkRlibError::MissingFormat); + return Err(diagnostics::LinkRlibError::MissingFormat); }; fmts } else { let mut dep_formats = info.dependency_formats.iter(); - let (ty1, list1) = dep_formats.next().ok_or(errors::LinkRlibError::MissingFormat)?; + let (ty1, list1) = dep_formats.next().ok_or(diagnostics::LinkRlibError::MissingFormat)?; if let Some((ty2, list2)) = dep_formats.find(|(_, list2)| list1 != *list2) { - return Err(errors::LinkRlibError::IncompatibleDependencyFormats { + return Err(diagnostics::LinkRlibError::IncompatibleDependencyFormats { ty1: format!("{ty1:?}"), ty2: format!("{ty2:?}"), list1: format!("{list1:?}"), @@ -353,16 +359,16 @@ pub fn each_linked_rlib( match fmts.get(cnum) { Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, Some(_) => {} - None => return Err(errors::LinkRlibError::MissingFormat), + None => return Err(diagnostics::LinkRlibError::MissingFormat), } let crate_name = info.crate_name[&cnum]; let used_crate_source = &info.used_crate_source[&cnum]; if let Some(path) = &used_crate_source.rlib { f(cnum, path); } else if used_crate_source.rmeta.is_some() { - return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name }); + return Err(diagnostics::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - return Err(errors::LinkRlibError::NotFound { crate_name }); + return Err(diagnostics::LinkRlibError::NotFound { crate_name }); } } Ok(()) @@ -505,15 +511,16 @@ fn link_rlib<'a>( && let Some(filename) = native_lib_filenames[i] { let path = find_native_static_library(filename.as_str(), true, sess); - let src = read(path) - .unwrap_or_else(|e| sess.dcx().emit_fatal(errors::ReadFileError { message: e })); + let src = read(path).unwrap_or_else(|e| { + sess.dcx().emit_fatal(diagnostics::ReadFileError { message: e }) + }); let (data, _) = create_wrapper_file(sess, ".bundled_lib".to_string(), &src); let wrapper_file = emit_wrapper_file(sess, &data, tmpdir.as_ref(), filename.as_str()); packed_bundled_libs.push(wrapper_file); } else { let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess); ab.add_archive(&path, AddArchiveKind::Other).unwrap_or_else(|error| { - sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: path, error }) + sess.dcx().emit_fatal(diagnostics::AddNativeLibrary { library_path: path, error }) }); } } @@ -531,7 +538,7 @@ fn link_rlib<'a>( ) { ab.add_archive(&output_path, AddArchiveKind::Other).unwrap_or_else(|error| { sess.dcx() - .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); + .emit_fatal(diagnostics::AddNativeLibrary { library_path: output_path, error }); }); } } @@ -676,12 +683,12 @@ fn link_staticlib( let exported_symbols = if hide || rename { if !matches!(sess.target.binary_format, BinaryFormat::Elf | BinaryFormat::MachO) { if hide { - sess.dcx().emit_warn(errors::StaticlibHideInternalSymbolsUnsupported { + sess.dcx().emit_warn(diagnostics::StaticlibHideInternalSymbolsUnsupported { binary_format: sess.target.archive_format.to_string(), }); } if rename { - sess.dcx().emit_warn(errors::StaticlibRenameInternalSymbolsUnsupported { + sess.dcx().emit_warn(diagnostics::StaticlibRenameInternalSymbolsUnsupported { binary_format: sess.target.archive_format.to_string(), }); } @@ -721,9 +728,9 @@ fn link_staticlib( if let Some(path) = &used_crate_source.dylib { all_rust_dylibs.push(&**path); } else if used_crate_source.rmeta.is_some() { - sess.dcx().emit_fatal(errors::LinkRlibError::OnlyRmetaFound { crate_name }); + sess.dcx().emit_fatal(diagnostics::LinkRlibError::OnlyRmetaFound { crate_name }); } else { - sess.dcx().emit_fatal(errors::LinkRlibError::NotFound { crate_name }); + sess.dcx().emit_fatal(diagnostics::LinkRlibError::NotFound { crate_name }); } } @@ -844,7 +851,7 @@ fn link_dwarf_object( Ok(()) }) { Ok(()) => {} - Err(e) => sess.dcx().emit_fatal(errors::ThorinErrorWrapper(e)), + Err(e) => sess.dcx().emit_fatal(diagnostics::ThorinErrorWrapper(e)), } } @@ -1226,7 +1233,7 @@ fn link_natively( let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); let escaped_output = escape_linker_output(&output, flavor); - let err = errors::LinkingFailed { + let err = diagnostics::LinkingFailed { linker_path: &linker_path, exit_status: prog.status, command: cmd, @@ -1247,25 +1254,25 @@ fn link_natively( find_msvc_tools::find_tool(sess.target.arch.desc(), "link.exe") .is_some(); - sess.dcx().emit_note(errors::LinkExeUnexpectedError); + sess.dcx().emit_note(diagnostics::LinkExeUnexpectedError); // STATUS_STACK_BUFFER_OVERRUN is also used for fast abnormal program termination, e.g. abort(). // Emit a special diagnostic to let people know that this most likely doesn't indicate a stack buffer overrun. const STATUS_STACK_BUFFER_OVERRUN: i32 = 0xc0000409u32 as _; if code == STATUS_STACK_BUFFER_OVERRUN { - sess.dcx().emit_note(errors::LinkExeStatusStackBufferOverrun); + sess.dcx().emit_note(diagnostics::LinkExeStatusStackBufferOverrun); } if is_vs_installed && has_linker { // the linker is broken - sess.dcx().emit_note(errors::RepairVSBuildTools); - sess.dcx().emit_note(errors::MissingCppBuildToolComponent); + sess.dcx().emit_note(diagnostics::RepairVSBuildTools); + sess.dcx().emit_note(diagnostics::MissingCppBuildToolComponent); } else if is_vs_installed { // the linker is not installed - sess.dcx().emit_note(errors::SelectCppBuildToolWorkload); + sess.dcx().emit_note(diagnostics::SelectCppBuildToolWorkload); } else { // visual studio is not installed - sess.dcx().emit_note(errors::VisualStudioNotInstalled); + sess.dcx().emit_note(diagnostics::VisualStudioNotInstalled); } } } @@ -1280,9 +1287,9 @@ fn link_natively( let linker_not_found = e.kind() == io::ErrorKind::NotFound; let err = if linker_not_found { - sess.dcx().emit_err(errors::LinkerNotFound { linker_path, error: e }) + sess.dcx().emit_err(diagnostics::LinkerNotFound { linker_path, error: e }) } else { - sess.dcx().emit_err(errors::UnableToExeLinker { + sess.dcx().emit_err(diagnostics::UnableToExeLinker { linker_path, error: e, command_formatted: format!("{cmd:?}"), @@ -1290,9 +1297,9 @@ fn link_natively( }; if sess.target.is_like_msvc && linker_not_found { - sess.dcx().emit_note(errors::MsvcMissingLinker); - sess.dcx().emit_note(errors::CheckInstalledVisualStudio); - sess.dcx().emit_note(errors::InsufficientVSCodeProduct); + sess.dcx().emit_note(diagnostics::MsvcMissingLinker); + sess.dcx().emit_note(diagnostics::CheckInstalledVisualStudio); + sess.dcx().emit_note(diagnostics::InsufficientVSCodeProduct); } err.raise_fatal(); } @@ -1317,13 +1324,13 @@ fn link_natively( if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.dcx().emit_warn(errors::ProcessingDymutilFailed { + sess.dcx().emit_warn(diagnostics::ProcessingDymutilFailed { status: prog.status, output: escape_string(&output), }); } } - Err(error) => sess.dcx().emit_fatal(errors::UnableToRunDsymutil { error }), + Err(error) => sess.dcx().emit_fatal(diagnostics::UnableToRunDsymutil { error }), } } @@ -1382,7 +1389,7 @@ fn link_natively( if sess.target.is_like_aix { // `llvm-strip` doesn't work for AIX - their strip must be used. if !sess.host.is_like_aix { - sess.dcx().emit_warn(errors::AixStripNotUsed); + sess.dcx().emit_warn(diagnostics::AixStripNotUsed); } let stripcmd = "/usr/bin/strip"; match strip { @@ -1421,14 +1428,14 @@ fn strip_with_external_utility(sess: &Session, util: &str, out_filename: &Path, if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); - sess.dcx().emit_warn(errors::StrippingDebugInfoFailed { + sess.dcx().emit_warn(diagnostics::StrippingDebugInfoFailed { util, status: prog.status, output: escape_string(&output), }); } } - Err(error) => sess.dcx().emit_fatal(errors::UnableToRun { util, error }), + Err(error) => sess.dcx().emit_fatal(diagnostics::UnableToRun { util, error }), } } @@ -1692,7 +1699,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) { )), (Some(linker), None) => { let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| { - sess.dcx().emit_fatal(errors::LinkerFileStem); + sess.dcx().emit_fatal(diagnostics::LinkerFileStem); }); let flavor = sess.target.linker_flavor.with_linker_hints(stem); let flavor = adjust_flavor_to_features(flavor, features); @@ -1863,10 +1870,10 @@ fn print_native_static_libs( match out { OutFileName::Real(path) => { out.overwrite(&lib_args.join(" "), sess); - sess.dcx().emit_note(errors::StaticLibraryNativeArtifactsToFile { path }); + sess.dcx().emit_note(diagnostics::StaticLibraryNativeArtifactsToFile { path }); } OutFileName::Stdout => { - sess.dcx().emit_note(errors::StaticLibraryNativeArtifacts); + sess.dcx().emit_note(diagnostics::StaticLibraryNativeArtifacts); // Prefix for greppability // Note: This must not be translated as tools are allowed to depend on this exact string. sess.dcx().note(format!("native-static-libs: {}", lib_args.join(" "))); @@ -2114,7 +2121,7 @@ fn self_contained_components( // Emit an error if the user requested self-contained mode on the CLI but the target // explicitly refuses it. if sess.target.link_self_contained.is_disabled() { - sess.dcx().emit_err(errors::UnsupportedLinkSelfContained); + sess.dcx().emit_err(diagnostics::UnsupportedLinkSelfContained); } self_contained } else { @@ -2202,14 +2209,14 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty match (crate_type, &sess.target.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { if !sess.target.linker_flavor.is_gnu() { - sess.dcx().emit_fatal(errors::LinkScriptUnavailable); + sess.dcx().emit_fatal(diagnostics::LinkScriptUnavailable); } let file_name = ["rustc", &sess.target.llvm_target, "linkfile.ld"].join("-"); let path = tmpdir.join(file_name); if let Err(error) = fs::write(&path, script.as_ref()) { - sess.dcx().emit_fatal(errors::LinkScriptWriteFailure { path, error }); + sess.dcx().emit_fatal(diagnostics::LinkScriptWriteFailure { path, error }); } cmd.link_arg("--script").link_arg(path); @@ -2428,7 +2435,7 @@ fn add_linked_symbol_object( let path = tmpdir.join("symbols.o"); let result = std::fs::write(&path, file.write().unwrap()); if let Err(error) = result { - sess.dcx().emit_fatal(errors::FailedToWrite { path, error }); + sess.dcx().emit_fatal(diagnostics::FailedToWrite { path, error }); } cmd.add_object(&path); } @@ -2868,7 +2875,7 @@ fn linker_with_args( // the directory of the stub to the linker search path. // We make an extra directory for this to avoid polluting the search path. if let Err(error) = fs::create_dir(&raw_dylib_dir) { - sess.dcx().emit_fatal(errors::CreateTempDir { error }) + sess.dcx().emit_fatal(diagnostics::CreateTempDir { error }) } cmd.include_path(&raw_dylib_dir); } @@ -3140,7 +3147,7 @@ fn collect_natvis_visualizers( visualizer_paths.push(visualizer_out_file); } Err(error) => { - sess.dcx().emit_warn(errors::UnableToWriteDebuggerVisualizer { + sess.dcx().emit_warn(diagnostics::UnableToWriteDebuggerVisualizer { path: visualizer_out_file, error, }); @@ -3562,8 +3569,10 @@ fn add_static_crate( false }), ) { - sess.dcx() - .emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error }); + sess.dcx().emit_fatal(diagnostics::RlibArchiveBuildFailure { + path: cratepath.clone(), + error, + }); } if archive.build(&dst, None) { link_upstream(&dst); @@ -3910,7 +3919,7 @@ fn add_lld_args( if !linker_path_exists { // As a sanity check, we emit an error if none of these paths exist: we want // self-contained linking and have no linker. - sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing); + sess.dcx().emit_fatal(diagnostics::SelfContainedLinkerMissing); } } diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs index 956373381122d..dbc0abdb50da8 100644 --- a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs +++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs @@ -15,8 +15,8 @@ use rustc_target::spec::Arch; use crate::back::archive::ImportLibraryItem; use crate::back::link::ArchiveBuilderBuilder; -use crate::errors::ErrorCreatingImportLibrary; -use crate::{NativeLib, common, errors}; +use crate::diagnostics::ErrorCreatingImportLibrary; +use crate::{NativeLib, common, diagnostics}; /// Extract all symbols defined in raw-dylib libraries, collated by library name. /// @@ -41,7 +41,7 @@ fn collate_raw_dylibs_windows<'a>( // FIXME: when we add support for ordinals, figure out if we need to do anything // if we have two DllImport values with the same name but different ordinals. if import.calling_convention != old_import.calling_convention { - sess.dcx().emit_err(errors::MultipleExternalFuncDecl { + sess.dcx().emit_err(diagnostics::MultipleExternalFuncDecl { span: import.span, function: import.name, library_name: &name, diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e24e7bad2b945..e1b4ce372507c 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -25,7 +25,7 @@ use super::command::Command; use super::symbol_export; use crate::back::symbol_export::allocator_shim_symbols; use crate::base::needs_allocator_shim_for_linking; -use crate::{SymbolExport, errors}; +use crate::{SymbolExport, diagnostics}; #[cfg(test)] mod tests; @@ -484,11 +484,11 @@ impl<'a> GccLinker<'a> { // FIXME(81490): ld64 doesn't support these flags but macOS 11 // has -needed-l{} / -needed_library {} // but we have no way to detect that here. - self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); + self.sess.dcx().emit_warn(diagnostics::Ld64UnimplementedModifier); } else if self.is_gnu && !self.sess.target.is_like_windows { self.link_arg("--no-as-needed"); } else { - self.sess.dcx().emit_warn(errors::LinkerUnsupportedModifier); + self.sess.dcx().emit_warn(diagnostics::LinkerUnsupportedModifier); } } @@ -619,7 +619,7 @@ impl<'a> Linker for GccLinker<'a> { // FIXME(81490): ld64 as of macOS 11 supports the -needed_framework // flag but we have no way to detect that here. // self.link_or_cc_arg("-needed_framework").link_or_cc_arg(name); - self.sess.dcx().emit_warn(errors::Ld64UnimplementedModifier); + self.sess.dcx().emit_warn(diagnostics::Ld64UnimplementedModifier); } self.link_or_cc_args(&["-framework", name]); } @@ -822,7 +822,7 @@ impl<'a> Linker for GccLinker<'a> { } }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error }); } self.link_arg("-exported_symbols_list").link_arg(path); } else if self.sess.target.is_like_windows { @@ -842,7 +842,7 @@ impl<'a> Linker for GccLinker<'a> { } }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error }); } self.link_arg(path); } else if self.sess.target.is_like_wasm { @@ -861,7 +861,7 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "}};")?; }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::VersionScriptWriteFailure { error }); } self.link_arg("--dynamic-list").link_arg(path); } else { @@ -879,7 +879,7 @@ impl<'a> Linker for GccLinker<'a> { writeln!(f, "\n local:\n *;\n}};")?; }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::VersionScriptWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::VersionScriptWriteFailure { error }); } if self.sess.target.is_like_solaris { self.link_arg("-M").link_arg(path); @@ -1103,7 +1103,7 @@ impl<'a> Linker for MsvcLinker<'a> { } } Err(error) => { - self.sess.dcx().emit_warn(errors::NoNatvisDirectory { error }); + self.sess.dcx().emit_warn(diagnostics::NoNatvisDirectory { error }); } } } @@ -1136,7 +1136,7 @@ impl<'a> Linker for MsvcLinker<'a> { writeln!(f, "EXPORTS")?; }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::LibDefWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::LibDefWriteFailure { error }); } let mut arg = OsString::from("/DEF:"); arg.push(path); @@ -1556,7 +1556,7 @@ impl<'a> Linker for L4Bender<'a> { fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[SymbolExport]) { // ToDo, not implemented, copy from GCC - self.sess.dcx().emit_warn(errors::L4BenderExportingSymbolsUnimplemented); + self.sess.dcx().emit_warn(diagnostics::L4BenderExportingSymbolsUnimplemented); } fn windows_subsystem(&mut self, subsystem: WindowsSubsystemKind) { @@ -2012,7 +2012,7 @@ impl<'a> Linker for BpfLinker<'a> { } fn link_staticlib_by_name(&mut self, _name: &str, _verbatim: bool, _whole_archive: bool) { - self.sess.dcx().emit_fatal(errors::BpfStaticlibNotSupported) + self.sess.dcx().emit_fatal(diagnostics::BpfStaticlibNotSupported) } fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) { @@ -2061,7 +2061,7 @@ impl<'a> Linker for BpfLinker<'a> { } }; if let Err(error) = res { - self.sess.dcx().emit_fatal(errors::SymbolFileWriteFailure { error }); + self.sess.dcx().emit_fatal(diagnostics::SymbolFileWriteFailure { error }); } else { self.link_arg("--export-symbols").link_arg(&path); } diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index ed36fae3cdc4d..0b33c1db8e5dc 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -14,7 +14,7 @@ use tracing::info; use crate::back::symbol_export::{self, allocator_shim_symbols, symbol_name_for_instance_in_crate}; use crate::back::write::CodegenContext; use crate::base::allocator_kind_for_codegen; -use crate::errors::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro}; +use crate::diagnostics::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro}; use crate::traits::*; pub struct ThinModule { diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 6f526879f7766..951a60426b5d5 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -24,7 +24,7 @@ use rustc_target::spec::{CfgAbi, LlvmAbi, Os, RelocModel, Target, ef_avr_arch}; use tracing::debug; use super::apple; -use crate::errors; +use crate::diagnostics; /// The default metadata loader. This is used by cg_llvm and cg_clif. /// @@ -371,7 +371,7 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { if let Some(ref cpu) = sess.opts.cg.target_cpu { ef_avr_arch(cpu) } else { - sess.dcx().emit_fatal(errors::CpuRequired) + sess.dcx().emit_fatal(diagnostics::CpuRequired) } } Architecture::Csky => { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 1419fcaf733f3..1db2321f7b249 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -33,11 +33,11 @@ use tracing::debug; use crate::back::link::ensure_removed; use crate::back::lto::{self, SerializedModule, check_lto_allowed}; -use crate::errors::ErrorCreatingRemarkDir; +use crate::diagnostics::ErrorCreatingRemarkDir; use crate::traits::*; use crate::{ CachedModuleCodegen, CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, ModuleKind, - errors, + diagnostics, }; const PRE_LTO_BC_EXT: &str = "pre-lto.bc"; @@ -515,10 +515,10 @@ pub fn produce_final_output_artifacts( // Produce final compile outputs. let copy_gracefully = |from: &Path, to: &OutFileName| match to { OutFileName::Stdout if let Err(e) = copy_to_stdout(from) => { - sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e)); + sess.dcx().emit_err(diagnostics::CopyPath::new(from, to.as_path(), e)); } OutFileName::Real(path) if let Err(e) = fs::copy(from, path) => { - sess.dcx().emit_err(errors::CopyPath::new(from, path, e)); + sess.dcx().emit_err(diagnostics::CopyPath::new(from, path, e)); } _ => {} }; @@ -530,8 +530,9 @@ pub fn produce_final_output_artifacts( let path = crate_output.temp_path_for_cgu(output_type, &module.name); let output = crate_output.path(output_type); if !output_type.is_text_output() && output.is_tty() { - sess.dcx() - .emit_err(errors::BinaryOutputToTty { shorthand: output_type.shorthand() }); + sess.dcx().emit_err(diagnostics::BinaryOutputToTty { + shorthand: output_type.shorthand(), + }); } else { copy_gracefully(&path, &output); } @@ -543,12 +544,14 @@ pub fn produce_final_output_artifacts( if crate_output.outputs.contains_explicit_name(&output_type) { // 2) Multiple codegen units, with `--emit foo=some_name`. We have // no good solution for this case, so warn the user. - sess.dcx() - .emit_warn(errors::IgnoringEmitPath { extension: output_type.extension() }); + sess.dcx().emit_warn(diagnostics::IgnoringEmitPath { + extension: output_type.extension(), + }); } else if crate_output.single_output_file.is_some() { // 3) Multiple codegen units, with `-o some_name`. We have // no good solution for this case, so warn the user. - sess.dcx().emit_warn(errors::IgnoringOutput { extension: output_type.extension() }); + sess.dcx() + .emit_warn(diagnostics::IgnoringOutput { extension: output_type.extension() }); } else { // 4) Multiple codegen units, but no explicit name. We // just leave the `foo.0.x` files in place. @@ -900,7 +903,7 @@ fn execute_copy_from_cache_work_item( Some(output_path) } Err(error) => { - dcx.emit_err(errors::CopyPathBuf { + dcx.emit_err(diagnostics::CopyPathBuf { source_file: source_file_in_incr_comp_dir, output_path, error, @@ -945,7 +948,7 @@ fn execute_copy_from_cache_work_item( None }; if should_emit_obj && object.is_none() { - dcx.emit_fatal(errors::NoSavedObjectFile { cgu_name: &module.name }) + dcx.emit_fatal(diagnostics::NoSavedObjectFile { cgu_name: &module.name }) } CompiledModule { @@ -1011,12 +1014,17 @@ fn do_thin_lto( // After we've requested tokens then we'll, when we can, // get tokens on `coordinator_receive` which will // get managed in the main loop below. - let coordinator_send2 = coordinator_send.clone(); - let helper = jobserver::client() - .into_helper_thread(move |token| { - drop(coordinator_send2.send(ThinLtoMessage::Token(token))); - }) - .expect("failed to spawn helper thread"); + // Note that using `jobserver::Proxy` is not necessary here, the code below always acquires + // tokens before releasing them, so we can never accidentally release the last token + // permanently held by rustc process. + let jobserver_helper = cgcx.parallel.then(|| { + let coordinator_send2 = coordinator_send.clone(); + jobserver::client() + .into_helper_thread(move |token| { + drop(coordinator_send2.send(ThinLtoMessage::Token(token))); + }) + .expect("failed to spawn helper thread") + }); let mut work_items = vec![]; @@ -1036,7 +1044,7 @@ fn do_thin_lto( let insertion_index = work_items.binary_search_by_key(&cost, |&(_, cost)| cost).unwrap_or_else(|e| e); work_items.insert(insertion_index, (work, cost)); - if cgcx.parallel { + if let Some(helper) = &jobserver_helper { helper.request_token(); } } @@ -1240,12 +1248,18 @@ fn start_executing_work( // After we've requested tokens then we'll, when we can, // get tokens on `coordinator_receive` which will // get managed in the main loop below. - let coordinator_send2 = coordinator_send.clone(); - let helper = jobserver::client() - .into_helper_thread(move |token| { - drop(coordinator_send2.send(Message::Token::(token))); - }) - .expect("failed to spawn helper thread"); + // Note that using `jobserver::Proxy` is not necessary here, the code below always acquires + // tokens before releasing them, so we can never accidentally release the last token + // permanently held by rustc process. + let parallel = !sess.opts.unstable_opts.no_parallel_backend && backend.supports_parallel(); + let jobserver_helper = parallel.then(|| { + let coordinator_send2 = coordinator_send.clone(); + jobserver::client() + .into_helper_thread(move |token| { + drop(coordinator_send2.send(Message::Token::(token))); + }) + .expect("failed to spawn helper thread") + }); let opt_level = tcx.backend_optimization_level(()); let backend_features = tcx.global_backend_features(()).clone(); @@ -1286,7 +1300,7 @@ fn start_executing_work( target_is_like_gpu: tcx.sess.target.is_like_gpu, split_debuginfo: tcx.sess.split_debuginfo(), split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind, - parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend, + parallel, pointer_size: tcx.data_layout.pointer_size(), }; @@ -1633,7 +1647,7 @@ fn start_executing_work( }; work_items.insert(insertion_index, (llvm_work_item, cost)); - if cgcx.parallel { + if let Some(helper) = &jobserver_helper { helper.request_token(); } assert_eq!(main_thread_state, MainThreadState::Codegenning); @@ -1716,7 +1730,7 @@ fn start_executing_work( drop(codegen_state); drop(tokens); - drop(helper); + drop(jobserver_helper); assert!(work_items.is_empty()); if !needs_fat_lto.is_empty() { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 43d5e312c6b40..ae049cfc37f95 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -51,7 +51,7 @@ use crate::mir::place::PlaceRef; use crate::traits::*; use crate::{ CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, EiiLinkageImplInfo, EiiLinkageInfo, - ModuleCodegen, errors, meth, mir, + ModuleCodegen, diagnostics, meth, mir, }; pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { @@ -529,7 +529,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. let span = cx.tcx().def_span(rust_main_def_id); - cx.tcx().dcx().emit_fatal(errors::MultipleMainFunctions { span }); + cx.tcx().dcx().emit_fatal(diagnostics::MultipleMainFunctions { span }); }; // `main` should respect same config for frame pointer elimination as rest of code @@ -698,14 +698,14 @@ pub fn codegen_crate< ) -> OngoingCodegen { if tcx.sess.target.need_explicit_cpu && tcx.sess.opts.cg.target_cpu.is_none() { // The target has no default cpu, but none is set explicitly - tcx.dcx().emit_fatal(errors::CpuRequired); + tcx.dcx().emit_fatal(diagnostics::CpuRequired); } if let Some(target_cpu) = &tcx.sess.opts.cg.target_cpu && tcx.sess.target.unsupported_cpus.contains(&target_cpu.into()) { // The target cpu is explicitly listed as an unsupported cpu - tcx.dcx().emit_fatal(errors::CpuUnsupported { target_cpu: target_cpu.clone() }); + tcx.dcx().emit_fatal(diagnostics::CpuUnsupported { target_cpu: target_cpu.clone() }); } let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index fb21f9ddbf2fa..691b13f03e965 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -19,7 +19,7 @@ use rustc_session::lint; use rustc_span::{Span, sym}; use rustc_target::spec::Os; -use crate::errors; +use crate::diagnostics; use crate::target_features::{ check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr, }; @@ -517,10 +517,10 @@ fn check_result( .unwrap_or_else(|| tcx.def_span(did)); tcx.dcx() - .create_err(errors::TargetFeatureDisableOrEnable { + .create_err(diagnostics::TargetFeatureDisableOrEnable { features, span: Some(span), - missing_features: Some(errors::MissingFeatures), + missing_features: Some(diagnostics::MissingFeatures), }) .emit(); } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/diagnostics.rs similarity index 100% rename from compiler/rustc_codegen_ssa/src/errors.rs rename to compiler/rustc_codegen_ssa/src/diagnostics.rs diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 3608f18345ed0..9a42debe1dd97 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -48,7 +48,7 @@ pub mod base; pub mod codegen_attrs; pub mod common; pub mod debuginfo; -pub mod errors; +pub mod diagnostics; pub mod meth; pub mod mir; pub mod mono_item; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index fba0cff0e6e14..99075536d04a8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -26,7 +26,7 @@ use super::place::{PlaceRef, PlaceValue}; use super::{CachedLlbb, FunctionCx, LocalRef}; use crate::base::{self, is_call_from_compiler_builtins_to_upstream_monomorphization}; use crate::common::{self, IntPredicate}; -use crate::errors::CompilerBuiltinsCannotCall; +use crate::diagnostics::CompilerBuiltinsCannotCall; use crate::mir::IntrinsicResult; use crate::traits::*; use crate::{MemFlags, meth}; diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index d4747c1cbafc9..7d35d4b72bd1e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, mir, span_bug}; use super::FunctionCx; -use crate::errors; +use crate::diagnostics; use crate::mir::operand::OperandRef; use crate::traits::*; @@ -98,7 +98,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.const_vector(&values) }) .unwrap_or_else(|| { - bx.tcx().dcx().emit_err(errors::ShuffleIndicesEvaluation { span: constant.span }); + bx.tcx() + .dcx() + .emit_err(diagnostics::ShuffleIndicesEvaluation { span: constant.span }); // We've errored, so we don't have to produce working code. let llty = bx.backend_type(bx.layout_of(ty)); bx.const_undef(llty) diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 6116c0fa9eb98..284b7d3f14fed 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -10,7 +10,7 @@ use super::operand::{OperandRef, OperandValue}; use super::place::PlaceValue; use super::{FunctionCx, IntrinsicResult}; use crate::common::{AtomicRmwBinOp, SynchronizationScope}; -use crate::errors::InvalidMonomorphization; +use crate::diagnostics::InvalidMonomorphization; use crate::mir::operand::OperandRefBuilder; use crate::traits::*; use crate::{MemFlags, meth, size_of_val}; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b23472c794b88..8f459e5a218d2 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -14,8 +14,8 @@ use rustc_target::spec::{Arch, SanitizerSet}; use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; use smallvec::SmallVec; -use crate::errors::{CrossArchFeatureNote, FeatureNotValid, FeatureNotValidHint}; -use crate::{errors, target_features}; +use crate::diagnostics::{CrossArchFeatureNote, FeatureNotValid, FeatureNotValidHint}; +use crate::{diagnostics, target_features}; /// Compute the enabled target features from the `#[target_feature]` function attribute. /// Enabled target features are added to `target_features`. @@ -72,7 +72,7 @@ pub(crate) fn from_target_feature_attr( // Only allow target features whose feature gates have been enabled // and which are permitted to be toggled. if let Err(reason) = stability.toggle_allowed() { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + tcx.dcx().emit_err(diagnostics::ForbiddenTargetFeatureAttr { span: feature_span, feature: feature_str, reason, @@ -104,10 +104,10 @@ pub(crate) fn from_target_feature_attr( AARCH64_SOFTFLOAT_NEON, tcx.local_def_id_to_hir_id(did), feature_span, - errors::Aarch64SoftfloatNeon, + diagnostics::Aarch64SoftfloatNeon, ); } else { - tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr { + tcx.dcx().emit_err(diagnostics::ForbiddenTargetFeatureAttr { span: feature_span, feature: name.as_str(), reason: "this feature is incompatible with the target ABI", @@ -156,7 +156,7 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, if let DefKind::AssocFn = tcx.def_kind(id) { let parent_id = tcx.local_parent(id); if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { - tcx.dcx().emit_err(errors::TargetFeatureSafeTrait { + tcx.dcx().emit_err(diagnostics::TargetFeatureSafeTrait { span: attr_span, def: tcx.def_span(id), }); @@ -275,7 +275,7 @@ pub fn cfg_target_feature<'a, const N: usize>( &sess.opts.cg.target_feature, /* err_callback */ |feature| { - sess.dcx().emit_warn(errors::UnknownCTargetFeaturePrefix { feature }); + sess.dcx().emit_warn(diagnostics::UnknownCTargetFeaturePrefix { feature }); }, |base_feature, new_features, enable| { // Iteration order is irrelevant since this only influences an `FxHashMap`. @@ -310,21 +310,21 @@ pub fn cfg_target_feature<'a, const N: usize>( } }); let unknown_feature = if let Some(rust_feature) = rust_feature { - errors::UnknownCTargetFeature { + diagnostics::UnknownCTargetFeature { feature: base_feature, - rust_feature: errors::PossibleFeature::Some { rust_feature }, + rust_feature: diagnostics::PossibleFeature::Some { rust_feature }, } } else { - errors::UnknownCTargetFeature { + diagnostics::UnknownCTargetFeature { feature: base_feature, - rust_feature: errors::PossibleFeature::None, + rust_feature: diagnostics::PossibleFeature::None, } }; sess.dcx().emit_warn(unknown_feature); } Some((_, stability, _)) => { if let Stability::Forbidden { reason, hard_error } = stability { - let diag = errors::ForbiddenCTargetFeature { + let diag = diagnostics::ForbiddenCTargetFeature { feature: base_feature, enabled: if enable { "enabled" } else { "disabled" }, reason, @@ -345,7 +345,7 @@ pub fn cfg_target_feature<'a, const N: usize>( } else { "this feature is not stably supported" }; - sess.dcx().emit_warn(errors::UnstableCTargetFeature { + sess.dcx().emit_warn(diagnostics::UnstableCTargetFeature { feature: base_feature, note, }); @@ -356,7 +356,7 @@ pub fn cfg_target_feature<'a, const N: usize>( ); if let Some(f) = check_tied_features(sess, &enabled_disabled_features) { - sess.dcx().emit_err(errors::TargetFeatureDisableOrEnable { + sess.dcx().emit_err(diagnostics::TargetFeatureDisableOrEnable { features: f, span: None, missing_features: None, diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index 3ed1ea7543f40..6f275d106d640 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -1,19 +1,16 @@ use std::sync::{Arc, LazyLock, OnceLock}; -pub use jobserver_crate::{Acquired, Client, HelperThread}; -use jobserver_crate::{FromEnv, FromEnvErrorKind}; +pub use jobserver_crate::Acquired; +use jobserver_crate::{Client, FromEnv, FromEnvErrorKind, HelperThread}; use parking_lot::{Condvar, Mutex}; -// We can only call `from_env_ext` once per process - -// We stick this in a global because there could be multiple rustc instances -// in this process, and the jobserver is per-process. +// We stick the jobserver client into a global and initialize it once, because there could be +// multiple compiler instances in this process, and the jobserver is per-process. static GLOBAL_CLIENT: LazyLock> = LazyLock::new(|| { - // Note that this is unsafe because it may misinterpret file descriptors - // on Unix as jobserver file descriptors. We hopefully execute this near - // the beginning of the process though to ensure we don't get false - // positives, or in other words we try to execute this before we open - // any file descriptors ourselves. + // Safety: the checked client construction ensures that the jobserver file descriptors + // (if any) are open and valid. We also try to initialize the jobserver as early as possible + // to avoid unrelated file descriptors with matching values becoming open and valid between + // the process start and the jobserver initialization. let FromEnv { client, var } = unsafe { Client::from_env_ext(true) }; let error = match client { @@ -40,14 +37,17 @@ static GLOBAL_CLIENT: LazyLock> = LazyLock::new(|| { )) }); -// Create a new jobserver if there's no inherited one. +// Creates a new jobserver if there's no inherited one. fn default_client() -> Client { // Pick a "reasonable maximum" capping out at 32 // so we don't take everything down by hogging the process run queue. // The fixed number is used to have deterministic compilation across machines. let client = Client::new(32).expect("failed to create jobserver"); - // Acquire a token for the main thread which we can release later + // Acquire the single token that is always held by the rustc process. + // This is an equivalent of the single token held by a higher level build tool while running + // this instance of rustc. This token is never released - if we are here, then rustc owns the + // jobserver, it is teared down when rustc exits, and there's no one to return the token to. client.acquire_raw().ok(); client @@ -55,47 +55,75 @@ fn default_client() -> Client { static GLOBAL_CLIENT_CHECKED: OnceLock = OnceLock::new(); -pub fn initialize_checked(report_warning: impl FnOnce(&'static str)) { +/// Initializes a jobserver client for the current rustc process. +/// If inheriting jobserver from the environment fails for some reason, an new jobserver owned by +/// the current rustc process will be created. If the inheritance failure reason is non-benign, +/// the passed callback will be used to report the error. +pub fn initialize_checked(report: impl FnOnce(&'static str)) { let client_checked = match &*GLOBAL_CLIENT { Ok(client) => client.clone(), Err(e) => { - report_warning(e); + report(e); default_client() } }; GLOBAL_CLIENT_CHECKED.set(client_checked).ok(); } -const ACCESS_ERROR: &str = "jobserver check should have been called earlier"; - +/// Returns the jobserver client previously initialized by `initialize_checked`. +/// +/// # Assumptions about holding jobserver tokens +/// +/// Rustc process must always hold a single token to avoid being permanently starved and blocked. +/// - If the jobserver is inherited from a higher level build tool, the assumption is that the tool +/// will hold the token and not release it until the rustc process exits. +/// - If the jobserver is owned by the current rustc, the token is acquired by `default_client`. +/// +/// To avoid releasing the last token, users of the client returned by this function must ensure +/// that they never release more tokens than was previously explicitly acquired. +/// Example of a sequence that can accidentally release the last token: +/// `release_raw` -> `wait` -> `acquire_raw`. +/// To avoid situations like this use the `jobserver::Proxy` wrapper instead, +/// it will ensure that the last token is never released. pub fn client() -> Client { - GLOBAL_CLIENT_CHECKED.get().expect(ACCESS_ERROR).clone() + GLOBAL_CLIENT_CHECKED.get().expect("uninitialized jobserver client").clone() } struct ProxyData { - /// The number of tokens assigned to threads. - /// If this is 0, a single token is still assigned to this process, but is unused. + /// The number of tokens assigned to actively working threads, + /// possibly including the single permanently held token. + /// If this number is 0, the single token is still held by the process, + /// but is not currently used for active CPU work. + /// This can happen, for example, if the main thread is waiting for something, + /// in that case some other thread can start using this token to do work. used: u16, - - /// The number of threads requesting a token + /// The number of threads currently requesting a token and waiting. + /// If the proxy releases a token it can immediately give it to one of these threads + /// without going through the real jobserver. pending: u16, } -/// This is a jobserver proxy used to ensure that we hold on to at least one token. +/// A wrapper around jobserver client used for two purposes: +/// - Ensuring that the single token that must be permanently held by the rustc process +/// cannot be accidentally released. +/// - "Token buffering", immediately acquiring freshly released tokens if necessary, +/// without going through the real jobserver. pub struct Proxy { + /// The wrapped jobserver client. client: Client, + /// Helper thread associated with the wrapped client. + helper: OnceLock, + /// The proxy's own data. data: Mutex, - - /// Threads which are waiting on a token will wait on this. + /// Threads which are currently waiting for a token will wait on this condvar. wake_pending: Condvar, - - helper: OnceLock, } impl Proxy { pub fn new() -> Arc { let proxy = Arc::new(Proxy { client: client(), + // Assume that the main thread is actively doing work when it creates the proxy. data: Mutex::new(ProxyData { used: 1, pending: 0 }), wake_pending: Condvar::new(), helper: OnceLock::new(), @@ -105,56 +133,60 @@ impl Proxy { .client .clone() .into_helper_thread(move |token| { + // Reminder: this callback runs when the helper acquires a token. if let Ok(token) = token { let mut data = proxy_.data.lock(); if data.pending > 0 { - // Give the token to a waiting thread + // The token is still needed, give it to one of the waiting threads. token.drop_without_releasing(); assert!(data.used > 0); data.used += 1; data.pending -= 1; proxy_.wake_pending.notify_one(); } else { - // The token is no longer needed, drop it. + // The token is no longer needed, release it by dropping. drop(data); drop(token); } } }) - .expect("failed to create helper thread"); + .expect("failed to spawn helper thread"); proxy.helper.set(helper).unwrap(); proxy } + /// Acquires a token, possibly using some buffered tokens as an optimization. + /// May block and wait until the token is available. pub fn acquire_thread(&self) { let mut data = self.data.lock(); if data.used == 0 { - // There was a free token around. This can - // happen when all threads release their token. + // No threads are doing any active work, but we are still holding the last token. + // Give that token to the current thread. assert_eq!(data.pending, 0); data.used += 1; } else { - // Request a token from the helper thread. We can't directly use `acquire_raw` - // as we also need to be able to wait for the final token in the process which - // does not get a corresponding `release_raw` call. + // Request a token from the helper thread, this is a non-blocking operation. + // Then wait until this or some other request succeeds. self.helper.get().unwrap().request_token(); data.pending += 1; self.wake_pending.wait(&mut data); } } + /// Releases a token, possibly immediately giving it to some other thread as an optimization. + /// Makes sure that the last token is never actually released to the wrapped jobserver. pub fn release_thread(&self) { let mut data = self.data.lock(); if data.pending > 0 { - // Give the token to a waiting thread + // Immediately give the released token to one of the waiting threads. data.pending -= 1; self.wake_pending.notify_one(); } else { data.used -= 1; - // Release the token unless it's the last one in the process + // Release the token to the wrapped jobserver, unless it's the last one in the process. if data.used > 0 { drop(data); self.client.release_raw().ok(); diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 2910ba7c46851..797e929c304ce 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1287,11 +1287,22 @@ impl<'a, T: Idx> Iterator for MixedBitIter<'a, T> { /// /// All operations that involve an element will panic if the element is equal /// to or greater than the domain size. -#[derive(Clone, Debug, PartialEq)] +#[derive(Debug, PartialEq)] pub struct GrowableBitSet { bit_set: DenseBitSet, } +// Manually implemented to forward `clone_from`, and to avoid the `T: Clone` bound. +impl Clone for GrowableBitSet { + fn clone(&self) -> Self { + Self { bit_set: self.bit_set.clone() } + } + + fn clone_from(&mut self, source: &Self) { + self.bit_set.clone_from(&source.bit_set); + } +} + impl Default for GrowableBitSet { fn default() -> Self { GrowableBitSet::new_empty() diff --git a/compiler/rustc_interface/src/diagnostics.rs b/compiler/rustc_interface/src/diagnostics.rs index 7cae1aa54d2e7..44d6073b93037 100644 --- a/compiler/rustc_interface/src/diagnostics.rs +++ b/compiler/rustc_interface/src/diagnostics.rs @@ -84,7 +84,7 @@ pub(crate) struct TempsDirError; pub(crate) struct OutDirError; #[derive(Diagnostic)] -#[diag("failed to write file {$path}: {$error}\"")] +#[diag("failed to write file {$path}: {$error}")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 95aeb1f7a234f..c7ea358f08170 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -369,16 +369,6 @@ pub struct Config { pub using_internal_features: &'static std::sync::atomic::AtomicBool, } -/// Initialize jobserver before getting `jobserver::client` and `build_session`. -pub(crate) fn initialize_checked_jobserver(early_dcx: &EarlyDiagCtxt) { - jobserver::initialize_checked(|err| { - early_dcx - .early_struct_warn(err) - .with_note("the build environment is likely misconfigured") - .emit() - }); -} - // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { @@ -389,9 +379,14 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.opts.unstable_opts.threads.is_some(), ); - // Check jobserver before run_in_thread_pool_with_globals, which call jobserver::acquire_thread + // Initialize jobserver as early as possible. let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); - initialize_checked_jobserver(&early_dcx); + jobserver::initialize_checked(|err| { + early_dcx + .early_struct_warn(err) + .with_note("the build environment is likely misconfigured") + .emit() + }); crate::callbacks::setup_callbacks(); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index ca983db29bcf7..a40c477b3a441 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -881,9 +881,11 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) { &tcx.sess.psess.attr_id_generator, ); let export_output = tcx.output_filenames(()).interface_path(); - let mut file = fs::File::create_buffered(export_output).unwrap(); - if let Err(err) = write!(file, "{}", krate) { - tcx.dcx().fatal(format!("error writing interface file: {}", err)); + let mut file = fs::File::create_buffered(&export_output).unwrap_or_else(|error| { + tcx.dcx().emit_fatal(diagnostics::FailedWritingFile { path: &export_output, error }) + }); + if let Err(error) = write!(file, "{}", krate) { + tcx.dcx().emit_fatal(diagnostics::FailedWritingFile { path: &export_output, error }); } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 71d1829f76584..22b643e74e582 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -31,15 +31,13 @@ use rustc_target::spec::{ RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel, }; -use crate::interface::{initialize_checked_jobserver, parse_cfg}; +use crate::interface::parse_cfg; fn sess_and_cfg(args: &[&'static str], f: F) where F: FnOnce(Session, Cfg), { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); - initialize_checked_jobserver(&early_dcx); - let matches = optgroups().parse(args).unwrap(); let sessopts = build_session_options(&mut early_dcx, &matches); let target = rustc_session::config::build_target_config( diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index b8eb4910df248..227bff83cabbf 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -198,7 +198,6 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas } fn visit_variant_data(&mut self, s: &'tcx hir::VariantData<'tcx>) { - lint_callback!(self, check_struct_def, s); hir_visit::walk_struct_def(self, s); } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index e3653c55f53a4..f7f5708bd424e 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -211,7 +211,7 @@ impl EarlyLintPass for NonCamelCaseTypes { declare_lint! { /// The `non_snake_case` lint detects variables, methods, functions, - /// lifetime parameters and modules that don't have snake case names. + /// lifetime parameters, named fields and modules that don't have snake case names. /// /// ### Example /// @@ -452,10 +452,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } } - fn check_struct_def(&mut self, cx: &LateContext<'_>, s: &hir::VariantData<'_>) { - for sf in s.fields() { - self.check_snake_case(cx, "structure field", &sf.ident); - } + fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { + self.check_snake_case(cx, "structure field", &field.ident); } } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index a1133a9a6ec29..d4d410d85c124 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -37,7 +37,6 @@ macro_rules! late_lint_methods { fn check_trait_item(a: &'tcx rustc_hir::TraitItem<'tcx>); fn check_impl_item(a: &'tcx rustc_hir::ImplItem<'tcx>); fn check_impl_item_post(a: &'tcx rustc_hir::ImplItem<'tcx>); - fn check_struct_def(a: &'tcx rustc_hir::VariantData<'tcx>); fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>); fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>); fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId); diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 78bb57745e41f..0d199e0d06655 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -18,7 +18,7 @@ pub(crate) struct DropCheckOverflow<'tcx> { } #[derive(Diagnostic)] -#[diag("failed to write file {$path}: {$error}\"")] +#[diag("failed to write file {$path}: {$error}")] pub(crate) struct FailedWritingFile<'a> { pub path: &'a Path, pub error: io::Error, diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7c80201f4f07f..519e32baae75f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1068,6 +1068,8 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { // so this would otherwise not get filled). body.set_mentioned_items(Vec::new()); + // We don't pass any passes here, we just force a phase change to `Optimized`. + // Otherwise this bit of MIR will trigger assertions trying to detect MIR with an invalid phase. pm::run_passes_no_validate( tcx, &mut body, diff --git a/compiler/rustc_target/src/callconv/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs index ec2c30756ddc0..0162aa838cb6b 100644 --- a/compiler/rustc_target/src/callconv/aarch64.rs +++ b/compiler/rustc_target/src/callconv/aarch64.rs @@ -3,7 +3,7 @@ use std::iter; use rustc_abi::{BackendRepr, HasDataLayout, Primitive, TyAbiInterface}; use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; -use crate::spec::{HasTargetSpec, RustcAbi, Target}; +use crate::spec::{Arch, HasTargetSpec, RustcAbi, Target}; /// Indicates the variant of the AArch64 ABI we are compiling for. /// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI. @@ -166,10 +166,26 @@ where classify_ret(cx, &mut fn_abi.ret, kind); } - for arg in fn_abi.args.iter_mut() { + // On Arm64EC the variadic portion of a c-variadic call follows the MS x64 ABI: + // "Any argument that doesn't fit in 8 bytes, or is not 1, 2, 4, or 8 bytes, must + // be passed by reference". + let c_variadic = fn_abi.c_variadic; + let fixed_count = fn_abi.fixed_count as usize; + let is_arm64ec = cx.target_spec().arch == Arch::Arm64EC; + + for (idx, arg) in fn_abi.args.iter_mut().enumerate() { if arg.is_ignore() { continue; } + + if is_arm64ec && c_variadic && idx >= fixed_count { + let size = arg.layout.size.bytes(); + if size > 8 || !size.is_power_of_two() { + arg.make_indirect(); + continue; + } + } + classify_arg(cx, arg, kind); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ff823594ce1c0..2a1f0e7935ea0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4487,6 +4487,29 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { tcx.disabled_nightly_features(err, [(String::new(), sym::trivial_bounds)]); } ObligationCauseCode::OpaqueReturnType(expr_info) => { + // Point at the method call in the returned expression's chain where an + // associated type diverged from what the signature's opaque type expects, + // regardless of how the failed predicate was derived from that expectation. + if let Some(typeck_results) = self.typeck_results.as_deref() { + let chain_expr = match expr_info { + Some((_, hir_id)) => Some(tcx.hir_expect_expr(hir_id)), + None => tcx.hir_node_by_def_id(body_def_id).body_id().and_then(|body_id| { + match tcx.hir_body(body_id).value.kind { + hir::ExprKind::Block(block, _) => block.expr, + _ => None, + } + }), + }; + if let Some(chain_expr) = chain_expr { + self.point_at_chain_in_return_position( + body_def_id, + chain_expr, + typeck_results, + param_env, + err, + ); + } + } let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info { let expr = tcx.hir_expect_expr(hir_id); (expr_ty, expr) @@ -5438,6 +5461,109 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { assocs_in_this_method } + /// When a `-> impl Trait` return type obligation fails, walk the method call + /// chain in the returned expression to point at where the associated type diverged from + /// what the signature expects. + /// + /// ```text + /// note: the method call chain might not have had the expected associated types + /// --> $DIR/invalid-iterator-chain-in-return-position.rs:16:18 + /// | + /// LL | x.iter_mut().map(foo) + /// | - ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here + /// | | | + /// | | `Iterator::Item` is `&mut Vec` here + /// | this expression has type `Vec>` + /// ``` + fn point_at_chain_in_return_position( + &self, + body_def_id: LocalDefId, + expr: &hir::Expr<'_>, + typeck_results: &TypeckResults<'tcx>, + param_env: ty::ParamEnv<'tcx>, + err: &mut Diag<'_, G>, + ) { + let tcx = self.tcx; + if !matches!(tcx.def_kind(body_def_id), DefKind::Fn | DefKind::AssocFn) { + return; + } + let output = + tcx.fn_sig(body_def_id).instantiate_identity().skip_norm_wip().output().skip_binder(); + let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, args, .. }) = + output.kind() + else { + return; + }; + + // The predicate that reaches here has been rewritten through the impls it was + // derived from (e.g. `Iterator for Map` turns `Iterator::Item` requirements + // into requirements on `F`'s return type), so the associated types the user wrote + // in the signature are recovered from the opaque's bounds instead. + let mut probe_diffs = vec![]; + for clause in tcx.item_bounds(opaque_def_id).instantiate(tcx, args).skip_norm_wip() { + let Some(proj) = clause.as_projection_clause() else { continue }; + let proj = self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + proj, + ); + let Some(expected_term) = proj.term.as_type() else { continue }; + // Only the projection (for its `DefId`) is used when probing the chain; the + // bound's own term is carried in `found` for the divergence check below and + // is replaced with the probed type afterwards. + probe_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { + expected: proj.projection_term.expect_ty().to_ty(tcx, ty::IsRigid::No), + found: expected_term, + })); + } + if probe_diffs.is_empty() { + return; + } + + // If the returned expression is a binding, walk the chain that created it instead. + let expr = if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::Path { res: Res::Local(hir_id), .. } = path + && let hir::Node::Pat(binding) = tcx.hir_node(*hir_id) + && let hir::Node::LetStmt(local) = tcx.parent_hir_node(binding.hir_id) + && let Some(binding_expr) = local.init + { + binding_expr + } else { + expr + }; + + // Resolve what each bound associated type actually is for the returned expression, + // and keep only the ones that diverged from the signature. + let expr_ty = self.resolve_vars_if_possible( + typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)), + ); + let assocs = self.probe_assoc_types_at_expr( + &probe_diffs, + expr.span, + expr_ty, + expr.hir_id, + param_env, + ); + let mut type_diffs = vec![]; + for (probe_diff, assoc) in iter::zip(probe_diffs, assocs) { + let TypeError::Sorts(ty::error::ExpectedFound { expected, found: expected_term }) = + probe_diff + else { + continue; + }; + let Some((_, (_, actual_ty))) = assoc else { continue }; + if !self.can_eq(param_env, expected_term, actual_ty) { + type_diffs.push(TypeError::Sorts(ty::error::ExpectedFound { + expected, + found: actual_ty, + })); + } + } + if !type_diffs.is_empty() { + self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); + } + } + /// If the type that failed selection is an array or a reference to an array, /// but the trait is implemented for slices, suggest that the user converts /// the array into a slice. diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 19dd13967fdd6..ceec98c8659fb 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] +use crate::cell::Cell; use crate::fmt::{self, Debug, Formatter}; struct PadAdapter<'buf, 'state> { @@ -50,6 +51,29 @@ impl fmt::Write for PadAdapter<'_, '_> { } } +/// Wraps an `FnOnce` formatting closure in a type that implements [`fmt::Debug`] by calling the +/// closure, allowing the `*_with` builder methods to forward to their `&dyn fmt::Debug` +/// counterparts. +/// +/// By doing this, the builder logic is monomorphized only once and not for every closure type +/// (see #149745). +/// +/// Formatting a `DebugOnce` consumes the closure, so attempting to format it more than once +/// panics. This never happens because the debug builders format each value exactly once. +struct DebugOnce(Cell>); + +impl fmt::Debug for DebugOnce +where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.0.take() { + Some(value_fmt) => value_fmt(f), + None => panic!("formatting closure called more than once"), + } + } +} + /// A struct to help with [`fmt::Debug`](Debug) implementations. /// /// This is useful when you wish to output a formatted struct as a part of your @@ -130,18 +154,6 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self { - self.field_with(name, |f| value.fmt(f)) - } - - /// Adds a new field to the generated struct output. - /// - /// This method is equivalent to [`DebugStruct::field`], but formats the - /// value using a provided closure rather than by calling [`Debug::fmt`]. - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -152,14 +164,14 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); writer.write_str(name)?; writer.write_str(": ")?; - value_fmt(&mut writer)?; + value.fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.has_fields { ", " } else { " { " }; self.fmt.write_str(prefix)?; self.fmt.write_str(name)?; self.fmt.write_str(": ")?; - value_fmt(self.fmt) + value.fmt(self.fmt) } }); @@ -167,6 +179,18 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { self } + /// Adds a new field to the generated struct output. + /// + /// This method is equivalent to [`DebugStruct::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.field(name, &DebugOnce(Cell::new(Some(value_fmt)))) + } + /// Marks the struct as non-exhaustive, indicating to the reader that there are some other /// fields that are not shown in the debug representation. /// @@ -327,18 +351,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self { - self.field_with(|f| value.fmt(f)) - } - - /// Adds a new field to the generated tuple struct output. - /// - /// This method is equivalent to [`DebugTuple::field`], but formats the - /// value using a provided closure rather than by calling [`Debug::fmt`]. - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { self.result = self.result.and_then(|_| { if self.is_pretty() { if self.fields == 0 { @@ -347,12 +359,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - value_fmt(&mut writer)?; + value.fmt(&mut writer)?; writer.write_str(",\n") } else { let prefix = if self.fields == 0 { "(" } else { ", " }; self.fmt.write_str(prefix)?; - value_fmt(self.fmt) + value.fmt(self.fmt) } }); @@ -360,6 +372,18 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { self } + /// Adds a new field to the generated tuple struct output. + /// + /// This method is equivalent to [`DebugTuple::field`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn field_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.field(&DebugOnce(Cell::new(Some(value_fmt)))) + } + /// Marks the tuple struct as non-exhaustive, indicating to the reader that there are some /// other fields that are not shown in the debug representation. /// @@ -453,10 +477,7 @@ struct DebugInner<'a, 'b: 'a> { } impl<'a, 'b: 'a> DebugInner<'a, 'b> { - fn entry_with(&mut self, entry_fmt: F) - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + fn entry(&mut self, entry: &dyn fmt::Debug) { self.result = self.result.and_then(|_| { if self.is_pretty() { if !self.has_fields { @@ -465,19 +486,26 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { let mut slot = None; let mut state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut state); - entry_fmt(&mut writer)?; + entry.fmt(&mut writer)?; writer.write_str(",\n") } else { if self.has_fields { self.fmt.write_str(", ")? } - entry_fmt(self.fmt) + entry.fmt(self.fmt) } }); self.has_fields = true; } + fn entry_with(&mut self, entry_fmt: F) + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.entry(&DebugOnce(Cell::new(Some(entry_fmt)))); + } + fn is_pretty(&self) -> bool { self.fmt.alternate() } @@ -546,7 +574,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry_with(|f| entry.fmt(f)); + self.inner.entry(entry); self } @@ -738,7 +766,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self { - self.inner.entry_with(|f| entry.fmt(f)); + self.inner.entry(entry); self } @@ -969,18 +997,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self { - self.key_with(|f| key.fmt(f)) - } - - /// Adds the key part of a new entry to the map output. - /// - /// This method is equivalent to [`DebugMap::key`], but formats the - /// key using a provided closure rather than by calling [`Debug::fmt`]. - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn key_with(&mut self, key_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { self.result = self.result.and_then(|_| { assert!( !self.has_key, @@ -995,13 +1011,13 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { let mut slot = None; self.state = Default::default(); let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - key_fmt(&mut writer)?; + key.fmt(&mut writer)?; writer.write_str(": ")?; } else { if self.has_fields { self.fmt.write_str(", ")? } - key_fmt(self.fmt)?; + key.fmt(self.fmt)?; self.fmt.write_str(": ")?; } @@ -1012,6 +1028,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self } + /// Adds the key part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::key`], but formats the + /// key using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn key_with(&mut self, key_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.key(&DebugOnce(Cell::new(Some(key_fmt)))) + } + /// Adds the value part of a new entry to the map output. /// /// This method, together with `key`, is an alternative to `entry` that @@ -1045,28 +1073,16 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_map_key_value", since = "1.42.0")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self { - self.value_with(|f| value.fmt(f)) - } - - /// Adds the value part of a new entry to the map output. - /// - /// This method is equivalent to [`DebugMap::value`], but formats the - /// value using a provided closure rather than by calling [`Debug::fmt`]. - #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn value_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { self.result = self.result.and_then(|_| { assert!(self.has_key, "attempted to format a map value before its key"); if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(self.fmt, &mut slot, &mut self.state); - value_fmt(&mut writer)?; + value.fmt(&mut writer)?; writer.write_str(",\n")?; } else { - value_fmt(self.fmt)?; + value.fmt(self.fmt)?; } self.has_key = false; @@ -1077,6 +1093,18 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { self } + /// Adds the value part of a new entry to the map output. + /// + /// This method is equivalent to [`DebugMap::value`], but formats the + /// value using a provided closure rather than by calling [`Debug::fmt`]. + #[unstable(feature = "debug_closure_helpers", issue = "117729")] + pub fn value_with(&mut self, value_fmt: F) -> &mut Self + where + F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + { + self.value(&DebugOnce(Cell::new(Some(value_fmt)))) + } + /// Adds the contents of an iterator of entries to the map output. /// /// # Examples diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 58c68408e6a80..c5da5055e16d9 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1432,7 +1432,7 @@ pub fn log2f128(x: f128) -> f128 { libm::maybe_available::log2f128(x) } -/// Returns `a * b + c` for `f16` values. +/// Returns `a * b + c` without rounding the intermediate result for `f16` values. /// /// The stabilized version of this intrinsic is /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) @@ -1440,7 +1440,7 @@ pub fn log2f128(x: f128) -> f128 { #[rustc_intrinsic] #[rustc_nounwind] pub const fn fmaf16(a: f16, b: f16, c: f16) -> f16; -/// Returns `a * b + c` for `f32` values. +/// Returns `a * b + c` without rounding the intermediate result for `f32` values. /// /// The stabilized version of this intrinsic is /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) @@ -1448,7 +1448,7 @@ pub const fn fmaf16(a: f16, b: f16, c: f16) -> f16; #[rustc_intrinsic] #[rustc_nounwind] pub const fn fmaf32(a: f32, b: f32, c: f32) -> f32; -/// Returns `a * b + c` for `f64` values. +/// Returns `a * b + c` without rounding the intermediate result for `f64` values. /// /// The stabilized version of this intrinsic is /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) @@ -1456,7 +1456,7 @@ pub const fn fmaf32(a: f32, b: f32, c: f32) -> f32; #[rustc_intrinsic] #[rustc_nounwind] pub const fn fmaf64(a: f64, b: f64, c: f64) -> f64; -/// Returns `a * b + c` for `f128` values. +/// Returns `a * b + c` without rounding the intermediate result for `f128` values. /// /// The stabilized version of this intrinsic is /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) @@ -1475,9 +1475,12 @@ pub const fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +#[inline] #[rustc_intrinsic] #[rustc_nounwind] -pub const fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; +pub const fn fmuladdf16(a: f16, b: f16, c: f16) -> f16 { + a * b + c +} /// Returns `a * b + c` for `f32` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1488,9 +1491,12 @@ pub const fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +#[inline] #[rustc_intrinsic] #[rustc_nounwind] -pub const fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; +pub const fn fmuladdf32(a: f32, b: f32, c: f32) -> f32 { + a * b + c +} /// Returns `a * b + c` for `f64` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1501,9 +1507,12 @@ pub const fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +#[inline] #[rustc_intrinsic] #[rustc_nounwind] -pub const fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; +pub const fn fmuladdf64(a: f64, b: f64, c: f64) -> f64 { + a * b + c +} /// Returns `a * b + c` for `f128` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1514,9 +1523,12 @@ pub const fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +#[inline] #[rustc_intrinsic] #[rustc_nounwind] -pub const fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; +pub const fn fmuladdf128(a: f128, b: f128, c: f128) -> f128 { + a * b + c +} /// Returns the largest integer less than or equal to an `f16`. /// diff --git a/library/core/src/intrinsics/simd/mod.rs b/library/core/src/intrinsics/simd/mod.rs index 903fd77661b2d..e9488a6bdb263 100644 --- a/library/core/src/intrinsics/simd/mod.rs +++ b/library/core/src/intrinsics/simd/mod.rs @@ -109,13 +109,13 @@ pub const unsafe fn simd_rem(lhs: T, rhs: T) -> T; /// Shifts vector left elementwise, with UB on overflow. /// -/// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types. +/// Shifts `lhs` left by `rhs`, shifting in zeros. /// /// `T` must be a vector of integers. /// /// # Safety /// -/// Each element of `rhs` must be less than `::BITS`. +/// Each element of `rhs` must be in `0..::BITS`. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_shl(lhs: T, rhs: T) -> T; @@ -128,7 +128,7 @@ pub const unsafe fn simd_shl(lhs: T, rhs: T) -> T; /// /// # Safety /// -/// Each element of `rhs` must be less than `::BITS`. +/// Each element of `rhs` must be in `0..::BITS`. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_shr(lhs: T, rhs: T) -> T; @@ -145,7 +145,7 @@ pub const unsafe fn simd_shr(lhs: T, rhs: T) -> T; /// /// # Safety /// -/// Each element of `shift` must be less than `::BITS`. +/// Each element of `shift` must be in `0..::BITS`. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_funnel_shl(a: T, b: T, shift: T) -> T; @@ -162,7 +162,7 @@ pub const unsafe fn simd_funnel_shl(a: T, b: T, shift: T) -> T; /// /// # Safety /// -/// Each element of `shift` must be less than `::BITS`. +/// Each element of `shift` must be in `0..::BITS`. #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn simd_funnel_shr(a: T, b: T, shift: T) -> T; @@ -433,6 +433,9 @@ pub enum SimdAlign { /// # Safety /// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details. /// +/// Each pointer offset from `ptr` whose corresponding value in `mask` is `!0` must be readable as if +/// by [`ptr::read`][crate::ptr::read]. +/// /// `mask` must only contain `0` or `!0` values. #[rustc_intrinsic] #[rustc_nounwind] @@ -455,6 +458,9 @@ pub const unsafe fn simd_masked_load(mask: V, p /// # Safety /// `ptr` must be aligned according to the `ALIGN` parameter, see [`SimdAlign`] for details. /// +/// Each pointer offset from `ptr` whose corresponding value in `mask` is `!0` must be writable as if +/// by [`ptr::write`][crate::ptr::write]. +/// /// `mask` must only contain `0` or `!0` values. #[rustc_intrinsic] #[rustc_nounwind] diff --git a/src/doc/book b/src/doc/book index dd7ab4f4f4541..917544888a55e 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit dd7ab4f4f4541adf4aa2a872cdac06c206b73288 +Subproject commit 917544888a55e4da7109bdba8c88c893c0da70f4 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 53686db907c45..5a14f7276ebc0 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 53686db907c45268d1b323afd9a3545a37abbced +Subproject commit 5a14f7276ebc0bd100974f02b918f30472c782fc diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index cc6cf2f8a648c..26985e67abb6e 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -197,15 +197,26 @@ themselves marked as unstable. To use any of these options, pass `-Z unstable-op the flag in question to Rustdoc on the command-line. To do this from Cargo, you can either use the `RUSTDOCFLAGS` environment variable or the `cargo rustdoc` command. -### `--merge`, `--parts-out-dir`, and `--include-parts-dir` +### `--write-doc-meta-dir`, and `--read-doc-meta-dir` These options control how rustdoc handles files that combine data from multiple crates. -By default, they act like `--merge=shared` is set, and `--parts-out-dir` and `--include-parts-dir` -are turned off. The `--merge=shared` mode causes rustdoc to load the existing data in the out-dir, -combine the new crate data into it, and write the result. This is very easy to use in scripts that -manually invoke rustdoc, but it's also slow, because it performs O(crates) work on -every crate, meaning it performs O(crates2) work. +By default, rustdoc will read the doc meta from the doc output dir itself and merge them together. +This is very easy to use in scripts that manually invoke rustdoc, but it's also slow, because it +performs O(crates) work on every crate, meaning it performs O(crates2) work. When +`--write-doc-meta-dir` and/or `--read-doc-meta-dir` are supplied, this is turned off. + +When `--write-doc-meta-dir` is supplied, rustdoc will write the crate's metadata to that directory. +If this parameter is supplied but `--read-doc-meta-dir` isn't, it runs in *intermediate mode*: +some pages may be written to the output dir, but there is a lot of functionality that won't work +until rustdoc is run in *finalize mode*. + +When `--read-doc-meta-dir` is supplied, rustdoc runs in *finalize mode*. It will read the data from +the supplied directory, and will write it to the doc output directory in the form that the web +frontend will use. + +If both `--write-doc-meta-dir` and `--read-doc-meta-dir` are specified, the crate metadata will be +written to both the HTML `--out-dir` and to the supplied `--write-doc-meta-dir`. ```console $ rustdoc crate1.rs --out-dir=doc @@ -217,13 +228,13 @@ rd_("fcrate1fcrate2") ``` To delay shared-data merging until the end of a build, so that you only have to perform O(crates) -work, use `--merge=none` on every crate except the last one, which will use `--merge=finalize`. +work, use `--write-doc-meta-dir` on every crate, and the last will use `--read-doc-meta-dir`. ```console -$ rustdoc +nightly crate1.rs --merge=none --parts-out-dir=crate1.d -Zunstable-options +$ rustdoc +nightly crate1.rs --write-doc-meta=crate1.d -Zunstable-options $ cat doc/search.index/crateNames/* cat: 'doc/search.index/crateNames/*': No such file or directory -$ rustdoc +nightly crate2.rs --merge=finalize --include-parts-dir=crate1.d -Zunstable-options +$ rustdoc +nightly crate2.rs --read-doc-meta=crate1.d -Zunstable-options $ cat doc/search.index/crateNames/* rd_("fcrate1fcrate2") ``` diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index a8c27c5615007..840f9d025c3cf 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -336,9 +336,6 @@ impl FromStr for EmitType { fn from_str(s: &str) -> Result { match s { - // old nightly-only choices that are going away soon - "toolchain-shared-resources" => Ok(Self::HtmlStaticFiles), - "invocation-specific" => Ok(Self::HtmlNonStaticFiles), // modern choices "html-static-files" => Ok(Self::HtmlStaticFiles), "html-non-static-files" => Ok(Self::HtmlNonStaticFiles), @@ -601,34 +598,66 @@ impl Options { let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); - let input = if describe_lints { - InputMode::HasFile(make_input(early_dcx, "")) - } else { - match matches.free.as_slice() { - [] if matches.opt_str("merge").as_deref() == Some("finalize") => { - InputMode::NoInputMergeFinalize - } - [] => dcx.fatal("missing file operand"), - [input] => InputMode::HasFile(make_input(early_dcx, input)), - _ => dcx.fatal("too many file operands"), - } - }; - let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, Err(err) => dcx.fatal(err), }; - let parts_out_dir = - match matches.opt_str("parts-out-dir").map(PathToParts::from_flag).transpose() { + let mut parts_out_dir = + match matches.opt_str("write-doc-meta-dir").map(PathToParts::from_flag).transpose() { Ok(parts_out_dir) => parts_out_dir, Err(e) => dcx.fatal(e), }; - let include_parts_dir = match parse_include_parts_dir(matches) { + let mut include_parts_dir = match parse_read_doc_meta(matches, "read-doc-meta-dir") { Ok(include_parts_dir) => include_parts_dir, Err(e) => dcx.fatal(e), }; + let mut should_merge = compute_should_merge(matches); + if parts_out_dir.is_none() && include_parts_dir.is_empty() { + // we'll need to get rid of this stuff once Cargo stops using them + parts_out_dir = + match matches.opt_str("parts-out-dir").map(PathToParts::from_flag).transpose() { + Ok(parts_out_dir) => parts_out_dir, + Err(e) => dcx.fatal(e), + }; + include_parts_dir = match parse_read_doc_meta(matches, "include-parts-dir") { + Ok(include_parts_dir) => include_parts_dir, + Err(e) => dcx.fatal(e), + }; + should_merge = match matches.opt_str("merge").as_deref() { + None => ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }, + Some("none") => ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }, + Some("shared") => ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }, + Some("finalize") => { + ShouldMerge { read_rendered_cci: false, write_rendered_cci: true } + } + Some(_) => dcx.fatal("argument to --merge must be `none`, `shared`, or `finalize`"), + }; + } else if matches.opt_str("parts-out-dir").is_some() { + dcx.fatal( + "deprecated version of write-doc-meta-dir is used with new doc-meta-dir stuff", + ); + } else if matches.opt_str("include-parts-dir").is_some() { + dcx.fatal( + "deprecated version of read-doc-meta-dir is used with new doc-meta-dir stuff", + ); + } else if matches.opt_str("merge").is_some() { + dcx.fatal("deprecated parameter merge is used with new doc-meta-dir stuff"); + } + + let input = if describe_lints { + InputMode::HasFile(make_input(early_dcx, "")) + } else { + match matches.free.as_slice() { + [] if !include_parts_dir.is_empty() && should_merge.write_rendered_cci => { + InputMode::NoInputMergeFinalize + } + [] => dcx.fatal("missing file operand"), + [input] => InputMode::HasFile(make_input(early_dcx, input)), + _ => dcx.fatal("too many file operands"), + } + }; let default_settings: Vec> = vec![ matches @@ -853,10 +882,6 @@ impl Options { let extern_html_root_takes_precedence = matches.opt_present("extern-html-root-takes-precedence"); let html_no_source = matches.opt_present("html-no-source"); - let should_merge = match parse_merge(matches) { - Ok(result) => result, - Err(e) => dcx.fatal(format!("--merge option error: {e}")), - }; let merge_doctests = parse_merge_doctests(matches, edition, dcx); tracing::debug!("merge_doctests: {merge_doctests:?}"); @@ -1051,7 +1076,7 @@ impl PathToParts { // check here is for diagnostics if path.exists() && !path.is_dir() { Err(format!( - "--parts-out-dir and --include-parts-dir expect directories, found: {}", + "--write-doc-meta-dir and --read-doc-meta-dir expect directories, found: {}", path.display(), )) } else { @@ -1061,15 +1086,15 @@ impl PathToParts { } } -/// Reports error if --include-parts-dir is not a directory -fn parse_include_parts_dir(m: &getopts::Matches) -> Result, String> { +/// Reports error if --read-doc-meta-dir is not a directory +fn parse_read_doc_meta(m: &getopts::Matches, name: &str) -> Result, String> { let mut ret = Vec::new(); - for p in m.opt_strs("include-parts-dir") { + for p in m.opt_strs(name) { let p = PathToParts::from_flag(p)?; // this is just for diagnostic if !p.0.is_dir() { return Err(format!( - "--include-parts-dir expected {} to be a directory", + "--read-doc-meta-dir expected {} to be a directory", p.0.display() )); } @@ -1089,23 +1114,15 @@ pub(crate) struct ShouldMerge { /// Extracts read_rendered_cci and write_rendered_cci from command line arguments, or /// reports an error if an invalid option was provided -fn parse_merge(m: &getopts::Matches) -> Result { - match m.opt_str("merge").as_deref() { - // default = read-write - None => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), - Some("none") if m.opt_present("include-parts-dir") => { - Err("--include-parts-dir not allowed if --merge=none") - } - Some("none") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }), - Some("shared") if m.opt_present("parts-out-dir") || m.opt_present("include-parts-dir") => { - Err("--parts-out-dir and --include-parts-dir not allowed if --merge=shared") - } - Some("shared") => Ok(ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }), - Some("finalize") if m.opt_present("parts-out-dir") => { - Err("--parts-out-dir not allowed if --merge=finalize") - } - Some("finalize") => Ok(ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }), - Some(_) => Err("argument to --merge must be `none`, `shared`, or `finalize`"), +fn compute_should_merge(m: &getopts::Matches) -> ShouldMerge { + match (m.opt_present("read-doc-meta-dir"), m.opt_present("write-doc-meta-dir")) { + // shared mode + (false, false) => ShouldMerge { read_rendered_cci: true, write_rendered_cci: true }, + // intermediate mode + (false, true) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: false }, + // finalize mode + (true, false) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }, + (true, true) => ShouldMerge { read_rendered_cci: false, write_rendered_cci: true }, } } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index ad3c41bdd2180..56059c6619954 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -11,7 +11,7 @@ //! contents, so they do not include a hash in their filename and are not safe to //! cache with `Cache-Control: immutable`. They include the contents of the //! --resource-suffix flag and are emitted when --emit-type is empty (default) -//! or contains "invocation-specific". +//! or contains "html-non-static-files". use std::cell::RefCell; use std::ffi::{OsStr, OsString}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 17f5af024ac7f..be830cad6c735 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -613,28 +613,41 @@ fn opts() -> Vec { Unstable, Opt, "", - "merge", - "Controls how rustdoc handles files from previously documented crates in the doc root\n\ - none = Do not write cross-crate information to the --out-dir\n\ - shared = Append current crate's info to files found in the --out-dir\n\ - finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", - "none|shared|finalize", + "write-doc-meta-dir", + "Writes trait implementations and other info for the current crate to provided path", + "path/to/doc.meta", + ), + opt( + Unstable, + Multi, + "", + "read-doc-meta-dir", + "Includes trait implementations and other crate info from provided path", + "path/to/doc.meta", ), opt( Unstable, Opt, "", "parts-out-dir", - "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", - "path/to/doc.parts/", + "Deprecated synonym of write-doc-meta-dir", + "path/to/doc.meta", ), opt( Unstable, Multi, "", "include-parts-dir", - "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", - "path/to/doc.parts/", + "Deprecated synonym of read-doc-meta-dir", + "path/to/doc.meta", + ), + opt( + Unstable, + Opt, + "", + "merge", + "Deprecated option to specify read/write-doc-meta-dir mode", + "none, shared, finalize", ), opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""), opt( @@ -758,7 +771,7 @@ fn run_renderer< /// Renders and writes cross-crate info files, like the search index. This function exists so that /// we can run rustdoc without a crate root in the `--merge=finalize` mode. Cross-crate info files -/// discovered via `--include-parts-dir` are combined and written to the doc root. +/// discovered via `--read-doc-meta-dir` are combined and written to the doc root. fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { assert!( opt.should_merge.write_rendered_cci, diff --git a/src/tools/enzyme b/src/tools/enzyme index a8668c7ca3579..6882b799d5aac 160000 --- a/src/tools/enzyme +++ b/src/tools/enzyme @@ -1 +1 @@ -Subproject commit a8668c7ca3579c3304d628bca518bafc0fcc62d1 +Subproject commit 6882b799d5aac80c5da7a4ef4e1b199e49509508 diff --git a/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs b/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs index 40d16886c6d7d..d3698fda5fe85 100644 --- a/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly-llvm/simd-intrinsic-mask-reduce.rs @@ -1,12 +1,16 @@ // verify that simd mask reductions do not introduce additional bit shift operations //@ add-minicore -//@ revisions: x86 aarch64 +//@ revisions: x86 aarch64-llvm22 aarch64 //@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel // Set the base cpu explicitly, in case the default has been changed. //@ [x86] compile-flags: -C target-cpu=x86-64 //@ [x86] needs-llvm-components: x86 +//@ [aarch64-llvm22] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [aarch64-llvm22] needs-llvm-components: aarch64 +//@ [aarch64-llvm22] max-llvm-major-version: 22 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu //@ [aarch64] needs-llvm-components: aarch64 +//@ [aarch64] min-llvm-version: 23 //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -Copt-level=3 -C panic=abort @@ -33,12 +37,19 @@ pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool { // x86-NEXT: {{cmp ax, -1|cmp eax, 65535|xor eax, 65535}} // x86-NEXT: sete al // + // aarch64-llvm22-NOT: shl + // aarch64-llvm22: cmge v0.16b, v0.16b, #0 + // aarch64-llvm22-DAG: mov [[REG1:[a-z0-9]+]], #1 + // aarch64-llvm22-DAG: umaxv b0, v0.16b + // aarch64-llvm22-NEXT: fmov [[REG2:[a-z0-9]+]], s0 + // aarch64-llvm22-NEXT: bic w0, [[REG1]], [[REG2]] + // // aarch64-NOT: shl // aarch64: cmge v0.16b, v0.16b, #0 - // aarch64-DAG: mov [[REG1:[a-z0-9]+]], #1 - // aarch64-DAG: umaxv b0, v0.16b - // aarch64-NEXT: fmov [[REG2:[a-z0-9]+]], s0 - // aarch64-NEXT: bic w0, [[REG1]], [[REG2]] + // aarch64-NEXT: addp [[REG1:d[0-9]+]], v0.2d + // aarch64-NEXT: fmov [[REG2:x[0-9]+]], [[REG1]] + // aarch64-NEXT: cmp [[REG2]], #0 + // aarch64-NEXT: cset w0, eq simd_reduce_all(m) } @@ -50,10 +61,17 @@ pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool { // x86-NEXT: test eax, eax // x86-NEXT: setne al // + // aarch64-llvm22-NOT: shl + // aarch64-llvm22: cmlt v0.16b, v0.16b, #0 + // aarch64-llvm22-NEXT: umaxv b0, v0.16b + // aarch64-llvm22-NEXT: fmov [[REG:[a-z0-9]+]], s0 + // aarch64-llvm22-NEXT: and w0, [[REG]], #0x1 + // // aarch64-NOT: shl // aarch64: cmlt v0.16b, v0.16b, #0 - // aarch64-NEXT: umaxv b0, v0.16b - // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 - // aarch64-NEXT: and w0, [[REG]], #0x1 + // aarch64-NEXT: addp [[REG1:d[0-9]+]], v0.2d + // aarch64-NEXT: fmov [[REG2:x[0-9]+]], [[REG1]] + // aarch64-NEXT: cmp [[REG2]], #0 + // aarch64-NEXT: cset w0, ne simd_reduce_any(m) } diff --git a/tests/assembly-llvm/slice-is_ascii.rs b/tests/assembly-llvm/slice-is_ascii.rs index e53cd5160cf56..6d660e78147c2 100644 --- a/tests/assembly-llvm/slice-is_ascii.rs +++ b/tests/assembly-llvm/slice-is_ascii.rs @@ -6,6 +6,11 @@ //@ only-x86_64 //@ ignore-sgx +// No longer optimizes as desired, tracked at: +// https://github.com/rust-lang/rust/issues/154141 +// https://github.com/llvm/llvm-project/issues/209216 +//@ max-llvm-major-version: 22 + #![feature(str_internals)] // CHECK-LABEL: is_ascii_simple_demo: diff --git a/tests/codegen-llvm/arm64ec-c-variadic-i128.rs b/tests/codegen-llvm/arm64ec-c-variadic-i128.rs new file mode 100644 index 0000000000000..b98463469eee3 --- /dev/null +++ b/tests/codegen-llvm/arm64ec-c-variadic-i128.rs @@ -0,0 +1,39 @@ +//! Verify the arm64ec calling convention for `i128` passed through the variadic +//! portion of a C-variadic call. +//! +//! On arm64ec the variadic tail follows the MS x64 ABI: any argument that does not +//! fit in 8 bytes, or is not 1/2/4/8 bytes, is passed by reference. So a variadic +//! `i128`/`u128` is passed indirectly (as a pointer), which must stay in sync with +//! how `va_arg` reads it back. A *fixed* `i128` argument is still passed by value. + +//@ add-minicore +//@ compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core)] + +extern crate minicore; + +extern "C" { + fn variadic(fixed: u32, ...); + fn fixed(arg: i128); +} + +// A variadic `i128` argument is passed by reference (as a pointer). +#[no_mangle] +pub unsafe extern "C" fn pass_variadic_i128(x: i128) { + // CHECK-LABEL: @pass_variadic_i128( + // CHECK: call void (i32, ...) @variadic(i32 {{.*}}, ptr {{.*}}) + variadic(0, x); +} + +// A fixed `i128` argument is still passed by value. +#[no_mangle] +pub unsafe extern "C" fn pass_fixed_i128(x: i128) { + // CHECK-LABEL: @pass_fixed_i128( + // CHECK: call void @fixed(i128 + fixed(x); +} diff --git a/tests/codegen-llvm/asm/global_asm.rs b/tests/codegen-llvm/asm/global_asm.rs index 32075daa3cf23..8c1c4a3b5881f 100644 --- a/tests/codegen-llvm/asm/global_asm.rs +++ b/tests/codegen-llvm/asm/global_asm.rs @@ -7,10 +7,10 @@ use std::arch::global_asm; -// CHECK-LABEL: foo // CHECK: module asm +// CHECK-LABEL: foo // this regex will capture the correct unconditional branch inst. -// CHECK: module asm "{{[[:space:]]+}}jmp baz" +// CHECK: "{{[[:space:]]+}}jmp baz" global_asm!( r#" .global foo diff --git a/tests/codegen-llvm/asm/global_asm_include.rs b/tests/codegen-llvm/asm/global_asm_include.rs index 98be9c3e33322..cad9901336bf3 100644 --- a/tests/codegen-llvm/asm/global_asm_include.rs +++ b/tests/codegen-llvm/asm/global_asm_include.rs @@ -7,9 +7,9 @@ use std::arch::global_asm; -// CHECK-LABEL: foo // CHECK: module asm -// CHECK: module asm "{{[[:space:]]+}}jmp baz" +// CHECK-LABEL: foo +// CHECK: "{{[[:space:]]+}}jmp baz" global_asm!(include_str!("foo.s")); extern "C" { diff --git a/tests/codegen-llvm/asm/global_asm_x2.rs b/tests/codegen-llvm/asm/global_asm_x2.rs index 9e3a00f068053..8c6f38289de33 100644 --- a/tests/codegen-llvm/asm/global_asm_x2.rs +++ b/tests/codegen-llvm/asm/global_asm_x2.rs @@ -8,12 +8,12 @@ use core::arch::global_asm; -// CHECK-LABEL: foo // CHECK: module asm -// CHECK: module asm "{{[[:space:]]+}}jmp baz" +// CHECK-LABEL: foo +// CHECK: "{{[[:space:]]+}}jmp baz" // any other global_asm will be appended to this first block, so: // CHECK-LABEL: bar -// CHECK: module asm "{{[[:space:]]+}}jmp quux" +// CHECK: "{{[[:space:]]+}}jmp quux" global_asm!( r#" .global foo diff --git a/tests/codegen-llvm/issues/issue-107681-unwrap_unchecked.rs b/tests/codegen-llvm/issues/issue-107681-unwrap_unchecked.rs index 5834255f3d313..c3090a20e4d14 100644 --- a/tests/codegen-llvm/issues/issue-107681-unwrap_unchecked.rs +++ b/tests/codegen-llvm/issues/issue-107681-unwrap_unchecked.rs @@ -14,7 +14,6 @@ pub unsafe fn foo(x: &mut Copied>) -> u32 { // CHECK-NOT: br {{.*}} // CHECK-NOT: select // CHECK: [[RET:%.*]] = load i32, ptr - // CHECK-NEXT: assume - // CHECK-NEXT: ret i32 [[RET]] + // CHECK: ret i32 [[RET]] x.next().unwrap_unchecked() } diff --git a/tests/debuginfo/function-call.rs b/tests/debuginfo/function-call.rs index 37eda165d99ca..104b43012a83e 100644 --- a/tests/debuginfo/function-call.rs +++ b/tests/debuginfo/function-call.rs @@ -1,5 +1,9 @@ // This test does not passed with gdb < 8.0. See #53497. -//@ min-gdb-version: 10.1 +// +// This test seems to have become very flaky with "Couldn't write extended state status: Bad +// address." since around June 2026, where CI typically uses GDB 12.1 on Ubuntu 22.04. I tried +// running this locally with GDB 15.1 and could not reproduce the flakiness. See #159073. +//@ min-gdb-version: 15.1 //@ compile-flags:-g //@ ignore-backends: gcc diff --git a/tests/run-make/emit-shared-files/rmake.rs b/tests/run-make/emit-shared-files/rmake.rs index 9841dce27fa2f..326aaa54bbc03 100644 --- a/tests/run-make/emit-shared-files/rmake.rs +++ b/tests/run-make/emit-shared-files/rmake.rs @@ -12,7 +12,7 @@ use run_make_support::{has_extension, has_prefix, path, rustdoc, shallow_find_fi fn main() { rustdoc() .arg("-Zunstable-options") - .arg("--emit=invocation-specific") + .arg("--emit=html-non-static-files") .out_dir("invocation-only") .arg("--resource-suffix=-xxx") .args(&["--theme", "y.css"]) diff --git a/tests/run-make/export/write-interface-nonexistent-dir/libr.rs b/tests/run-make/export/write-interface-nonexistent-dir/libr.rs new file mode 100644 index 0000000000000..c6aeabf3228f0 --- /dev/null +++ b/tests/run-make/export/write-interface-nonexistent-dir/libr.rs @@ -0,0 +1,13 @@ +#![feature(export_stable)] +#![crate_type = "sdylib"] + +pub mod m { + #[repr(C)] + pub struct S { + pub x: i32, + } + + pub extern "C" fn foo1(x: S) -> i32 { + x.x + } +} diff --git a/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs b/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs new file mode 100644 index 0000000000000..636a8ab7ed9b4 --- /dev/null +++ b/tests/run-make/export/write-interface-nonexistent-dir/rmake.rs @@ -0,0 +1,18 @@ +// Regression test for . + +//@ ignore-cross-compile + +// NOTE: `sdylib`'s platform support is basically that of `dylib`. +//@ needs-crate-type: dylib + +use run_make_support::rustc; + +fn main() { + rustc() + .input("libr.rs") + .output("does-not-exist/output") + .run_fail() + .assert_exit_code(1) + .assert_stderr_contains("failed to write file") + .assert_not_ice(); +} diff --git a/tests/run-make/pgo-branch-weights/filecheck-patterns.txt b/tests/run-make/pgo-branch-weights/filecheck-patterns.txt index 70d5a645c1454..ac9de0b16e49d 100644 --- a/tests/run-make/pgo-branch-weights/filecheck-patterns.txt +++ b/tests/run-make/pgo-branch-weights/filecheck-patterns.txt @@ -2,16 +2,16 @@ # First, establish that certain !prof labels are attached to the expected # functions and branching instructions. -CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] { +CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !prof [[branch_weights0:![0-9]+]] -CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] { +CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] CHECK: switch i32 %c, label {{.*}} [ CHECK-NEXT: i32 97, label {{.*}} CHECK-NEXT: i32 98, label {{.*}} CHECK-NEXT: ], !prof [[branch_weights1:![0-9]+]] -CHECK: define void @function_called_never(i32 {{.*}} !prof [[function_called_never_id:![0-9]+]] { +CHECK: define void @function_called_never(i32 {{.*}} !prof [[function_called_never_id:![0-9]+]] diff --git a/tests/run-make/pgo-embed-bc-lto/interesting.rs b/tests/run-make/pgo-embed-bc-lto/interesting.rs index 13105c17e126d..94c7621457917 100644 --- a/tests/run-make/pgo-embed-bc-lto/interesting.rs +++ b/tests/run-make/pgo-embed-bc-lto/interesting.rs @@ -10,7 +10,7 @@ pub fn function_called_once() { } // CHECK-LABEL: @function_called_once -// CHECK-SAME: !prof [[function_called_once_id:![0-9]+]] { +// CHECK-SAME: !prof [[function_called_once_id:![0-9]+]] // CHECK: "CG Profile" // CHECK-NOT: "CG Profile" // CHECK-DAG: [[function_called_once_id]] = !{!"function_entry_count", i64 1} diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 0a2da1099b820..78dfbf03c1b10 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -176,23 +176,19 @@ Options: --scrape-tests Include test code when scraping examples --with-examples path to function call information (for displaying examples in the documentation) - --merge none|shared|finalize - Controls how rustdoc handles files from previously - documented crates in the doc root - none = Do not write cross-crate information to the - --out-dir - shared = Append current crate's info to files found in - the --out-dir - finalize = Write current crate's info and - --include-parts-dir info to the --out-dir, overwriting - conflicting files - --parts-out-dir path/to/doc.parts/ + --write-doc-meta-dir path/to/doc.meta Writes trait implementations and other info for the - current crate to provided path. Only use with - --merge=none - --include-parts-dir path/to/doc.parts/ + current crate to provided path + --read-doc-meta-dir path/to/doc.meta Includes trait implementations and other crate info - from provided path. Only use with --merge=finalize + from provided path + --parts-out-dir path/to/doc.meta + Deprecated synonym of write-doc-meta-dir + --include-parts-dir path/to/doc.meta + Deprecated synonym of read-doc-meta-dir + --merge none, shared, finalize + Deprecated option to specify read/write-doc-meta-dir + mode --html-no-source Disable HTML source code pages generation --doctest-build-arg ARG diff --git a/tests/run-make/rustdoc-merge-directory-alias/rmake.rs b/tests/run-make/rustdoc-merge-directory-alias/rmake.rs index 096eb4a487c15..8a5c1aa2af723 100644 --- a/tests/run-make/rustdoc-merge-directory-alias/rmake.rs +++ b/tests/run-make/rustdoc-merge-directory-alias/rmake.rs @@ -1,4 +1,4 @@ -// Running --merge=finalize without an input crate root should not trigger ICE. +// Running --read-doc-meta-dir without an input crate root should not trigger ICE. // Issue: https://github.com/rust-lang/rust/issues/146646 //@ needs-target-std @@ -14,16 +14,14 @@ fn main() { .input("dep1.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep1.json").exists()); let output = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); @@ -31,16 +29,14 @@ fn main() { .input("dep2.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep2.json").exists()); let output2 = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output2.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); @@ -48,20 +44,18 @@ fn main() { .input("dep1.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep1.json").exists()); let output3 = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output3.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); - // dep_missing is different, because --parts-out-dir is not supplied + // dep_missing is different, because --write-doc-meta-dir is not supplied rustdoc().input("dep_missing.rs").out_dir(&out_dir).run(); assert!(parts_out_dir.join("dep2.json").exists()); @@ -69,16 +63,14 @@ fn main() { .input("dep1.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep1.json").exists()); let output4 = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output4.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); diff --git a/tests/run-make/rustdoc-merge-directory/rmake.rs b/tests/run-make/rustdoc-merge-directory/rmake.rs index e4695ddad0b48..d2d31138bf3c6 100644 --- a/tests/run-make/rustdoc-merge-directory/rmake.rs +++ b/tests/run-make/rustdoc-merge-directory/rmake.rs @@ -1,4 +1,4 @@ -// Running --merge=finalize without an input crate root should not trigger ICE. +// Running --read-doc-meta without an input crate root should not trigger ICE. // Issue: https://github.com/rust-lang/rust/issues/146646 //@ needs-target-std @@ -14,8 +14,7 @@ fn main() { .input("dep1.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep1.json").exists()); @@ -23,20 +22,18 @@ fn main() { .input("dep2.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("dep2.json").exists()); - // dep_missing is different, because --parts-out-dir is not supplied + // dep_missing is different, because --write-doc-meta-dir is not supplied rustdoc().input("dep_missing.rs").out_dir(&out_dir).run(); assert!(parts_out_dir.join("dep2.json").exists()); let output = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); diff --git a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs index 4dad01f341fef..6f7028bfbfbc1 100644 --- a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs +++ b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs @@ -1,4 +1,4 @@ -// Running --merge=finalize without an input crate root should not trigger ICE. +// Running --write-doc-meta-dir without an input crate root should not trigger ICE. // Issue: https://github.com/rust-lang/rust/issues/146646 //@ needs-target-std @@ -13,16 +13,14 @@ fn main() { .input("sierra.rs") .out_dir(&out_dir) .arg("-Zunstable-options") - .arg(format!("--parts-out-dir={}", parts_out_dir.display())) - .arg("--merge=none") + .arg(format!("--write-doc-meta-dir={}", parts_out_dir.display())) .run(); assert!(parts_out_dir.join("sierra.json").exists()); let output = rustdoc() .arg("-Zunstable-options") .out_dir(&out_dir) - .arg(format!("--include-parts-dir={}", parts_out_dir.display())) - .arg("--merge=finalize") + .arg(format!("--read-doc-meta-dir={}", parts_out_dir.display())) .run(); output.assert_not_ice(); } diff --git a/tests/run-make/rustdoc-scrape-examples-dep-info/rmake.rs b/tests/run-make/rustdoc-scrape-examples-dep-info/rmake.rs index 5a612fd130052..13c62906f1687 100644 --- a/tests/run-make/rustdoc-scrape-examples-dep-info/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-dep-info/rmake.rs @@ -9,7 +9,7 @@ fn main() { scrape::scrape( &["--scrape-tests", "--emit=dep-info"], - &["--emit=dep-info,invocation-specific"], + &["--emit=dep-info,html-non-static-files"], ); let content = rfs::read_to_string("rustdoc/foobar.d").replace(r"\", "/"); diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs index fdafb3b7ac341..c4b3ce498576c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/quebec.rs @@ -1,4 +1,3 @@ -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs index ff12fe98d82c2..299a673418713 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/auxiliary/tango.rs @@ -1,6 +1,5 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs index 26292c50d35e6..10f12ad8d1184 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/cargo-transitive-read-write/sierra.rs @@ -1,6 +1,5 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -18,7 +17,7 @@ //@ hasraw search.index/name/*.js 'Sierra' //@ hasraw search.index/name/*.js 'Quebec' -// similar to cargo-workflow-transitive, but we use --merge=read-write, +// similar to cargo-workflow-transitive, but we use shared mode, // which is the default. extern crate tango; pub struct Sierra; diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs index d10bc0316ccad..d2af9af496bc3 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/quebec.rs @@ -1,6 +1,5 @@ //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs index 6d0c8651db53f..bcccc05299a79 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/romeo.rs @@ -1,8 +1,7 @@ //@ aux-build:sierra.rs //@ build-aux-docs //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/romeo +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/romeo //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs index 10898f3886477..9d5e564720169 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/sierra.rs @@ -1,8 +1,7 @@ //@ aux-build:tango.rs //@ build-aux-docs //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs index 3c3721ee6eb7d..577c486a3adfb 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/auxiliary/tango.rs @@ -1,8 +1,7 @@ //@ aux-build:quebec.rs //@ build-aux-docs //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs index fd6ee0cbf2407..986c58deb5d6b 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/kitchen-sink-separate-dirs/indigo.rs @@ -3,11 +3,10 @@ //@ aux-build:quebec.rs //@ aux-build:sierra.rs //@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--include-parts-dir=info/doc.parts/tango -//@ doc-flags:--include-parts-dir=info/doc.parts/romeo -//@ doc-flags:--include-parts-dir=info/doc.parts/quebec -//@ doc-flags:--include-parts-dir=info/doc.parts/sierra +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/romeo +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/sierra //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs index 61210529fa6bc..d2af9af496bc3 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/quebec.rs @@ -1,5 +1,5 @@ //@ unique-doc-out-dir -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs index 70d8a4b91f549..577c486a3adfb 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/auxiliary/tango.rs @@ -1,7 +1,7 @@ //@ aux-build:quebec.rs //@ build-aux-docs //@ unique-doc-out-dir -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs index c3b8200f15107..9a6ca3c6dd41c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-separate/sierra.rs @@ -1,6 +1,6 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -10,7 +10,7 @@ //@ !has trait.impl/tango/trait.Tango.js //@ !has search.index/name/*.js -// we don't generate any cross-crate info if --merge=none, even if we +// we don't generate any cross-crate info if --write-doc-meta-dir, even if we // document crates separately extern crate tango; pub struct Sierra; diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs index 6ab921533b037..442eacb91f480 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/quebec.rs @@ -1,5 +1,4 @@ -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs index 9fa99d3be8af4..e10bab806ea0c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/auxiliary/tango.rs @@ -1,7 +1,6 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs index 2e47d42daff94..9d5a1a3c17bfa 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/no-merge-write-anyway/sierra.rs @@ -1,7 +1,6 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/sierra +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -12,7 +11,7 @@ //@ !has trait.impl/tango/trait.Tango.js //@ !has search.index/name/*.js -// we --merge=none, so --parts-out-dir doesn't do anything +// we don't use --read-doc-meta-dir, so no metadata is loaded extern crate tango; pub struct Sierra; impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs index 6ab921533b037..442eacb91f480 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/quebec.rs @@ -1,5 +1,4 @@ -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs index 9fa99d3be8af4..e10bab806ea0c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/auxiliary/tango.rs @@ -1,7 +1,6 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs index 337dc558f35d8..2d94321ed7465 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-include/sierra.rs @@ -1,7 +1,6 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--include-parts-dir=info/doc.parts/tango +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs index d10bc0316ccad..d2af9af496bc3 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/quebec.rs @@ -1,6 +1,5 @@ //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs index 3c3721ee6eb7d..577c486a3adfb 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/auxiliary/tango.rs @@ -1,8 +1,7 @@ //@ aux-build:quebec.rs //@ build-aux-docs //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs index c07b30d2aa0cd..6a2dbb1c31ccc 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite-but-separate/sierra.rs @@ -1,8 +1,7 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--include-parts-dir=info/doc.parts/tango -//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs index 0e28d8e646647..35098e62cede9 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/quebec.rs @@ -1,4 +1,4 @@ -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec.d //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs index 363b2d5508e63..dcb7965dde86e 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite/auxiliary/tango.rs @@ -1,6 +1,6 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=finalize +//@ doc-flags:--read-doc-meta-dir=info/doc.parts //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs index cac978f3bb272..57c9732ba8dd7 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/overwrite/sierra.rs @@ -1,6 +1,5 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -13,7 +12,7 @@ //@ hasraw search.index/name/*.js 'Sierra' //@ !hasraw search.index/name/*.js 'Quebec' -// since tango is documented with --merge=finalize, we overwrite q's +// since tango is documented with "finalize mode", we overwrite q's // cross-crate information extern crate tango; pub struct Sierra; diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs index 2ab08c112a18c..c157380edf1f9 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/single-crate-finalize/quebec.rs @@ -1,4 +1,3 @@ -//@ doc-flags:--merge=finalize //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs index 1b9e8a3db08da..4fd510e31227c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/single-crate-read-write/quebec.rs @@ -1,4 +1,3 @@ -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs index 6b72615eb9dec..fde3635e62250 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/single-crate-write-anyway/quebec.rs @@ -1,4 +1,4 @@ -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--read-doc-meta-dir=. //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -8,6 +8,6 @@ //@ has quebec/struct.Quebec.html //@ hasraw search.index/name/*.js 'Quebec' -// we can --parts-out-dir, but that doesn't do anything other than create +// we can --write-doc-meta-dir, but that doesn't do anything other than create // the file pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs deleted file mode 100644 index bfde21c9ed3c9..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/single-merge-none-useless-write/quebec.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -//@ !has index.html -//@ has quebec/struct.Quebec.html -//@ !has search.index/name/*.js - -// --merge=none doesn't write anything, despite --parts-out-dir -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs deleted file mode 100644 index 1beca543f814f..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/quebec.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ doc-flags:--merge=finalize -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -pub struct Quebec; diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs deleted file mode 100644 index 363b2d5508e63..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/auxiliary/tango.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ aux-build:quebec.rs -//@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -extern crate quebec; -pub trait Tango {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/sierra.rs deleted file mode 100644 index b45895a40a1b6..0000000000000 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-finalize/sierra.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ aux-build:tango.rs -//@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--enable-index-page -//@ doc-flags:-Zunstable-options - -//@ has index.html -//@ has index.html '//h1' 'List of all crates' -//@ has index.html '//ul[@class="all-items"]//a[@href="sierra/index.html"]' 'sierra' -//@ has index.html '//ul[@class="all-items"]//a[@href="tango/index.html"]' 'tango' -//@ has sierra/struct.Sierra.html -//@ has tango/trait.Tango.html -//@ hasraw sierra/struct.Sierra.html 'Tango' -//@ hasraw trait.impl/tango/trait.Tango.js 'struct.Sierra.html' -//@ hasraw search.index/name/*.js 'Sierra' - -// write only overwrites stuff in the output directory -extern crate tango; -pub struct Sierra; -impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs index 6ab921533b037..442eacb91f480 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/quebec.rs @@ -1,5 +1,4 @@ -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/quebec +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs index 9fa99d3be8af4..e10bab806ea0c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/auxiliary/tango.rs @@ -1,7 +1,6 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/tango +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs index be37137617936..945e8cf84dc7d 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-none/sierra.rs @@ -1,8 +1,7 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=finalize -//@ doc-flags:--include-parts-dir=info/doc.parts/tango -//@ doc-flags:--include-parts-dir=info/doc.parts/quebec +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/tango +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -21,7 +20,7 @@ //@ hasraw search.index/name/*.js 'Quebec' // We avoid writing any cross-crate information, preferring to include it -// with --include-parts-dir. +// with --read-doc-meta-dir. extern crate tango; pub struct Sierra; impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs index 1beca543f814f..c4b3ce498576c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/quebec.rs @@ -1,4 +1,3 @@ -//@ doc-flags:--merge=finalize //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs index ff12fe98d82c2..299a673418713 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/auxiliary/tango.rs @@ -1,6 +1,5 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs index dc10ec3de35b0..67ce91d1e225a 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-merge-read-write/sierra.rs @@ -1,6 +1,5 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=shared //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -19,7 +18,7 @@ //@ hasraw search.index/name/*.js 'Quebec' // We can use read-write to emulate the default behavior of rustdoc, when -// --merge is left out. +// --read-doc-meta-dir is left out. extern crate tango; pub struct Sierra; impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs index 0e28d8e646647..442eacb91f480 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/quebec.rs @@ -1,4 +1,4 @@ -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/quebec //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs index 3827119f696f5..e10bab806ea0c 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/auxiliary/tango.rs @@ -1,6 +1,6 @@ //@ aux-build:quebec.rs //@ build-aux-docs -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/tango //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options diff --git a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs index 9eaa627419bb4..61c60cf7c9e15 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/transitive-no-info/sierra.rs @@ -1,6 +1,6 @@ //@ aux-build:tango.rs //@ build-aux-docs -//@ doc-flags:--merge=none +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/sierra //@ doc-flags:--enable-index-page //@ doc-flags:-Zunstable-options @@ -11,7 +11,8 @@ //@ !has trait.impl/tango/trait.Tango.js //@ !has search.index/name/*.js -// --merge=none on all crates does not generate any cross-crate info +// --write-doc-meta-dir on all crates does not write the search index +// in the actual output folder extern crate tango; pub struct Sierra; impl tango::Tango for Sierra {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs b/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs index e492b700dbc2b..713f8812a55a6 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/auxiliary/foxtrot.rs @@ -1,5 +1,5 @@ //@ unique-doc-out-dir -//@ doc-flags:--parts-out-dir=info/doc.parts/foxtrot +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/foxtrot //@ doc-flags:-Zunstable-options pub trait Foxtrot {} diff --git a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs b/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs index d79302e62cdc3..998bb559df8c1 100644 --- a/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs +++ b/tests/rustdoc-html/merge-cross-crate-info/two-separate-out-dir/echo.rs @@ -1,6 +1,6 @@ //@ aux-build:foxtrot.rs //@ build-aux-docs -//@ doc-flags:--include-parts-dir=info/doc.parts/foxtrot +//@ doc-flags:--read-doc-meta-dir=info/doc.parts/foxtrot //@ doc-flags:-Zunstable-options //@ has echo/enum.Echo.html diff --git a/tests/rustdoc-js/auxiliary/merged-dep.rs b/tests/rustdoc-js/auxiliary/merged-dep.rs index fadeb6c65270e..0a3216ee5c03f 100644 --- a/tests/rustdoc-js/auxiliary/merged-dep.rs +++ b/tests/rustdoc-js/auxiliary/merged-dep.rs @@ -1,6 +1,5 @@ //@ unique-doc-out-dir -//@ doc-flags:--merge=none -//@ doc-flags:--parts-out-dir=info/doc.parts/merged-dep +//@ doc-flags:--write-doc-meta-dir=info/doc.parts/merged-dep //@ doc-flags:-Zunstable-options pub struct Dep; diff --git a/tests/rustdoc-js/merged-doc.rs b/tests/rustdoc-js/merged-doc.rs index ef7ce4b1fd365..7fc18f2e8bb4a 100644 --- a/tests/rustdoc-js/merged-doc.rs +++ b/tests/rustdoc-js/merged-doc.rs @@ -1,8 +1,7 @@ //@ revisions: merge nomerge //@ aux-build:merged-dep.rs //@ build-aux-docs -//@[merge] doc-flags:--merge=finalize -//@[merge] doc-flags:--include-parts-dir=info/doc.parts/merged-dep +//@[merge] doc-flags:--read-doc-meta-dir=info/doc.parts/merged-dep //@[merge] doc-flags:-Zunstable-options extern crate merged_dep; diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr index 8b172cd5ca133..f685b01cd8cc3 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.stderr +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.stderr @@ -107,6 +107,14 @@ LL | fn foo() -> impl Iterator { ... LL | [2u32].into_iter() | ------------------ return type was inferred to be `std::array::IntoIter` here + | +note: the method call chain might not have had the expected associated types + --> $DIR/duplicate-bound-err.rs:110:16 + | +LL | [2u32].into_iter() + | ------ ^^^^^^^^^^^ `Iterator::Item` is `u32` here + | | + | this expression has type `[u32; 1]` error[E0271]: expected `impl Iterator` to be an iterator that yields `i32`, but it yields `u32` --> $DIR/duplicate-bound-err.rs:107:17 diff --git a/tests/ui/iterators/invalid-iterator-chain-in-return-position.rs b/tests/ui/iterators/invalid-iterator-chain-in-return-position.rs new file mode 100644 index 0000000000000..c87438818e17d --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-in-return-position.rs @@ -0,0 +1,39 @@ +//! Check that a `-> impl Iterator` return type mismatch points at the +//! method call in the returned expression's chain where `Iterator::Item` diverged +//! from the signature's expectation, instead of only pointing at the signature. +//! Regression test for . + +fn foo(items: &mut Vec) { + items.sort(); +} + +fn bar() -> impl Iterator { + //~^ ERROR expected `foo` to return `i32`, but it returns `()` + let mut x: Vec> = vec![ + vec![0, 2, 1], + vec![5, 4, 3], + ]; + x.iter_mut().map(foo) +} + +fn baz() -> impl Iterator { + //~^ ERROR expected `foo` to return `i32`, but it returns `()` + let mut x: Vec> = vec![ + vec![0, 2, 1], + vec![5, 4, 3], + ]; + let it = x.iter_mut().map(foo); + it +} + +fn chained() -> impl Iterator { + //~^ ERROR expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` + let x = vec![0u32, 1, 2]; + x.into_iter().filter(|x| *x > 0).map(|x| x.checked_add(1)).flatten() +} + +fn main() { + bar(); + baz(); + chained(); +} diff --git a/tests/ui/iterators/invalid-iterator-chain-in-return-position.stderr b/tests/ui/iterators/invalid-iterator-chain-in-return-position.stderr new file mode 100644 index 0000000000000..a21acc3dd84b3 --- /dev/null +++ b/tests/ui/iterators/invalid-iterator-chain-in-return-position.stderr @@ -0,0 +1,69 @@ +error[E0271]: expected `foo` to return `i32`, but it returns `()` + --> $DIR/invalid-iterator-chain-in-return-position.rs:10:13 + | +LL | fn bar() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()` +... +LL | x.iter_mut().map(foo) + | --------------------- return type was inferred to be `Map>, for<'a> fn(&'a mut Vec) {foo}>` here + | + = note: required for `Map>, for<'a> fn(&'a mut Vec) {foo}>` to implement `Iterator` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-in-return-position.rs:16:18 + | +LL | let mut x: Vec> = vec![ + | _______________________________- +LL | | vec![0, 2, 1], +LL | | vec![5, 4, 3], +LL | | ]; + | |_____- this expression has type `Vec>` +LL | x.iter_mut().map(foo) + | ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here + | | + | `Iterator::Item` is `&mut Vec` here + +error[E0271]: expected `foo` to return `i32`, but it returns `()` + --> $DIR/invalid-iterator-chain-in-return-position.rs:19:13 + | +LL | fn baz() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()` +... +LL | it + | -- return type was inferred to be `Map>, for<'a> fn(&'a mut Vec) {foo}>` here + | + = note: required for `Map>, for<'a> fn(&'a mut Vec) {foo}>` to implement `Iterator` +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-in-return-position.rs:25:27 + | +LL | let mut x: Vec> = vec![ + | _______________________________- +LL | | vec![0, 2, 1], +LL | | vec![5, 4, 3], +LL | | ]; + | |_____- this expression has type `Vec>` +LL | let it = x.iter_mut().map(foo); + | ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here + | | + | `Iterator::Item` is `&mut Vec` here + +error[E0271]: expected `IntoIter` to be an iterator that yields `i32`, but it yields `u32` + --> $DIR/invalid-iterator-chain-in-return-position.rs:29:17 + | +LL | fn chained() -> impl Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` + | +note: the method call chain might not have had the expected associated types + --> $DIR/invalid-iterator-chain-in-return-position.rs:32:7 + | +LL | let x = vec![0u32, 1, 2]; + | ---------------- this expression has type `Vec` +LL | x.into_iter().filter(|x| *x > 0).map(|x| x.checked_add(1)).flatten() + | ^^^^^^^^^^^ ------------------ ------------------------- ^^^^^^^^^ `Iterator::Item` changed to `u32` here + | | | | + | | | `Iterator::Item` changed to `Option` here + | | `Iterator::Item` remains `u32` here + | `Iterator::Item` is `u32` here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr index 15e0ba5337f14..5c31c240dfff5 100644 --- a/tests/ui/lint/issue-106991.stderr +++ b/tests/ui/lint/issue-106991.stderr @@ -8,6 +8,15 @@ LL | x.iter_mut().map(foo) | --------------------- return type was inferred to be `Map>, for<'a> fn(&'a mut Vec) {foo}>` here | = note: required for `Map>, for<'a> fn(&'a mut Vec) {foo}>` to implement `Iterator` +note: the method call chain might not have had the expected associated types + --> $DIR/issue-106991.rs:8:18 + | +LL | let mut x: Vec> = vec![vec![0, 2, 1], vec![5, 4, 3]]; + | ---------------------------------- this expression has type `Vec>` +LL | x.iter_mut().map(foo) + | ---------- ^^^^^^^^ `Iterator::Item` changed to `()` here + | | + | `Iterator::Item` is `&mut Vec` here error: aborting due to 1 previous error diff --git a/tests/ui/lint/non-snake-case/field-lint-expectation-issue-159323.rs b/tests/ui/lint/non-snake-case/field-lint-expectation-issue-159323.rs new file mode 100644 index 0000000000000..ca7aa97475a07 --- /dev/null +++ b/tests/ui/lint/non-snake-case/field-lint-expectation-issue-159323.rs @@ -0,0 +1,33 @@ +//@ check-pass + +// Regression test for issue #159323 +// Field-level lint attributes must control `non_snake_case` diagnostics for that field. + +#![deny(non_snake_case, unfulfilled_lint_expectations)] + +pub struct Struct { + #[expect(non_snake_case)] + pub expected_Field: bool, + + #[allow(non_snake_case)] + pub allowed_Field: bool, +} + +#[expect(non_snake_case)] +pub struct ParentExpectation { + pub expected_Field: bool, +} + +pub enum Enum { + Variant { + #[expect(non_snake_case)] + expected_Field: bool, + }, +} + +pub union Union { + #[expect(non_snake_case)] + pub expected_Field: bool, +} + +fn main() {}