From a954c512809a2d6f3e592c0287dbe41264b54808 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 18 Jan 2025 18:19:42 +0100 Subject: [PATCH 1/6] Support raw-dylib link kind on ELF raw-dylib is a link kind that allows rustc to link against a library without having any library files present. This currently only exists on Windows. rustc will take all the symbols from raw-dylib link blocks and put them in an import library, where they can then be resolved by the linker. While import libraries don't exist on ELF, it would still be convenient to have this same functionality. Not having the libraries present at build-time can be convenient for several reasons, especially cross-compilation. With raw-dylib, code linking against a library can be cross-compiled without needing to have these libraries available on the build machine. If the libc crate makes use of this, it would allow cross-compilation without having any libc available on the build machine. This is not yet possible with this implementation, at least against libc's like glibc that use symbol versioning. The raw-dylib kind could be extended with support for symbol versioning in the future. This implementation is very experimental and I have not tested it very well. I have tested it for a toy example and the lz4-sys crate, where it was able to successfully link a binary despite not having a corresponding library at build-time. --- compiler/rustc_codegen_ssa/src/back/link.rs | 218 ++++------ .../src/back/link/raw_dylib.rs | 373 ++++++++++++++++++ .../rustc_codegen_ssa/src/back/metadata.rs | 86 ++-- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_metadata/messages.ftl | 3 + compiler/rustc_metadata/src/native_libs.rs | 21 +- compiler/rustc_session/src/utils.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 55 ++- .../rustc-dev-guide/src/tests/directives.md | 1 + src/tools/compiletest/src/directive-list.rs | 2 + src/tools/compiletest/src/header/cfg.rs | 10 + tests/run-make/linker-warning/rmake.rs | 2 + tests/run-make/linker-warning/short-error.txt | 2 +- .../raw-dylib-elf-verbatim-absolute/main.rs | 11 + .../output.txt | 1 + .../raw-dylib-elf-verbatim-absolute/rmake.rs | 20 + .../run-make/raw-dylib-elf-verbatim/library.c | 3 + tests/run-make/raw-dylib-elf-verbatim/main.rs | 11 + .../raw-dylib-elf-verbatim/output.txt | 1 + .../run-make/raw-dylib-elf-verbatim/rmake.rs | 31 ++ tests/run-make/raw-dylib-elf/library.c | 3 + tests/run-make/raw-dylib-elf/main.rs | 11 + tests/run-make/raw-dylib-elf/output.txt | 1 + tests/run-make/raw-dylib-elf/rmake.rs | 29 ++ tests/run-make/reproducible-build/linker.rs | 2 + .../feature-gate-raw-dylib-elf.rs | 9 + .../feature-gate-raw-dylib-elf.stderr | 13 + .../raw-dylib/elf/multiple-libraries.rs | 37 ++ .../raw-dylib/elf/single-symbol.rs | 28 ++ .../ui/linkage-attr/raw-dylib/elf/verbatim.rs | 29 ++ .../raw-dylib/windows}/dlltool-failed.rs | 0 .../raw-dylib/windows}/dlltool-failed.stderr | 0 .../import-name-type-invalid-format.rs | 0 .../import-name-type-invalid-format.stderr | 0 .../windows}/import-name-type-multiple.rs | 0 .../windows}/import-name-type-multiple.stderr | 0 .../import-name-type-unknown-value.rs | 0 .../import-name-type-unknown-value.stderr | 0 .../import-name-type-unsupported-link-kind.rs | 0 ...ort-name-type-unsupported-link-kind.stderr | 0 .../windows}/import-name-type-x86-only.rs | 0 .../windows}/import-name-type-x86-only.stderr | 0 .../raw-dylib/windows}/invalid-dlltool.rs | 0 .../raw-dylib/windows}/invalid-dlltool.stderr | 0 .../windows}/link-ordinal-and-name.rs | 0 .../windows}/link-ordinal-and-name.stderr | 0 .../windows}/link-ordinal-invalid-format.rs | 0 .../link-ordinal-invalid-format.stderr | 0 .../windows}/link-ordinal-missing-argument.rs | 0 .../link-ordinal-missing-argument.stderr | 0 .../windows}/link-ordinal-multiple.rs | 0 .../windows}/link-ordinal-multiple.stderr | 0 .../windows}/link-ordinal-not-foreign-fn.rs | 0 .../link-ordinal-not-foreign-fn.stderr | 0 .../windows}/link-ordinal-too-large.rs | 0 .../windows}/link-ordinal-too-large.stderr | 0 .../link-ordinal-too-many-arguments.rs | 0 .../link-ordinal-too-many-arguments.stderr | 0 .../link-ordinal-unsupported-link-kind.rs | 0 .../link-ordinal-unsupported-link-kind.stderr | 0 .../windows}/multiple-declarations.rs | 0 .../windows}/multiple-declarations.stderr | 0 .../windows/raw-dylib-windows-only.elf.stderr | 13 + .../raw-dylib-windows-only.notelf.stderr} | 2 +- .../windows/raw-dylib-windows-only.rs | 9 + .../raw-dylib/windows}/unsupported-abi.rs | 0 .../raw-dylib/windows}/unsupported-abi.stderr | 0 .../raw-dylib-windows-only.rs | 5 - 69 files changed, 839 insertions(+), 207 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim/library.c create mode 100644 tests/run-make/raw-dylib-elf-verbatim/main.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim/output.txt create mode 100644 tests/run-make/raw-dylib-elf-verbatim/rmake.rs create mode 100644 tests/run-make/raw-dylib-elf/library.c create mode 100644 tests/run-make/raw-dylib-elf/main.rs create mode 100644 tests/run-make/raw-dylib-elf/output.txt create mode 100644 tests/run-make/raw-dylib-elf/rmake.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/dlltool-failed.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/dlltool-failed.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-invalid-format.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-invalid-format.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-multiple.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-multiple.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unknown-value.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unknown-value.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unsupported-link-kind.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unsupported-link-kind.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-x86-only.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-x86-only.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/invalid-dlltool.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/invalid-dlltool.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-and-name.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-and-name.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-invalid-format.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-invalid-format.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-missing-argument.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-missing-argument.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-multiple.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-multiple.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-not-foreign-fn.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-not-foreign-fn.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-large.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-large.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-many-arguments.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-many-arguments.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-unsupported-link-kind.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-unsupported-link-kind.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/multiple-declarations.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/multiple-declarations.stderr (100%) create mode 100644 tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr rename tests/ui/{rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr => linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr} (86%) create mode 100644 tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/unsupported-abi.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/unsupported-abi.stderr (100%) delete mode 100644 tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b090730ac6b51..177161461409a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,3 +1,5 @@ +mod raw_dylib; + use std::collections::BTreeSet; use std::ffi::OsString; use std::fs::{File, OpenOptions, read}; @@ -12,7 +14,7 @@ use itertools::Itertools; use regex::Regex; use rustc_arena::TypedArena; use rustc_ast::CRATE_NODE_ID; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; @@ -30,7 +32,6 @@ use rustc_session::config::{ self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames, OutputType, PrintKind, SplitDwarfKind, Strip, }; -use rustc_session::cstore::DllImport; use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; @@ -41,22 +42,21 @@ use rustc_session::{Session, filesearch}; use rustc_span::Symbol; use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ - Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures, - LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, - SplitDebuginfo, + BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, + LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, + SanitizerSet, SplitDebuginfo, }; use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; use super::{apple, versioned_llvm_target}; use crate::{ - CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, - looks_like_rust_object_file, + CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -376,16 +376,22 @@ fn link_rlib<'a>( } } - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - codegen_results.crate_info.used_libraries.iter(), - tmpdir.as_ref(), - true, - ) { - ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { - sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); - }); + // On Windows, we add the raw-dylib import libraries to the rlibs already. + // But on ELF, this is not possible, as a shared object cannot be a member of a static library. + // Instead, we add all raw-dylibs to the final link on ELF. + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + codegen_results.crate_info.used_libraries.iter(), + tmpdir.as_ref(), + true, + ) { + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { + sess.dcx() + .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); + }); + } } if let Some(trailing_metadata) = trailing_metadata { @@ -426,108 +432,6 @@ fn link_rlib<'a>( ab } -/// Extract all symbols defined in raw-dylib libraries, collated by library name. -/// -/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, -/// then the CodegenResults value contains one NativeLib instance for each block. However, the -/// linker appears to expect only a single import library for each library used, so we need to -/// collate the symbols together by library name before generating the import libraries. -fn collate_raw_dylibs<'a>( - sess: &Session, - used_libraries: impl IntoIterator, -) -> Vec<(String, Vec)> { - // Use index maps to preserve original order of imports and libraries. - let mut dylib_table = FxIndexMap::>::default(); - - for lib in used_libraries { - if lib.kind == NativeLibKind::RawDylib { - let ext = if lib.verbatim { "" } else { ".dll" }; - let name = format!("{}{}", lib.name, ext); - let imports = dylib_table.entry(name.clone()).or_default(); - for import in &lib.dll_imports { - if let Some(old_import) = imports.insert(import.name, import) { - // 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 { - span: import.span, - function: import.name, - library_name: &name, - }); - } - } - } - } - } - sess.dcx().abort_if_errors(); - dylib_table - .into_iter() - .map(|(name, imports)| { - (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) - }) - .collect() -} - -fn create_dll_import_libs<'a>( - sess: &Session, - archive_builder_builder: &dyn ArchiveBuilderBuilder, - used_libraries: impl IntoIterator, - tmpdir: &Path, - is_direct_dependency: bool, -) -> Vec { - collate_raw_dylibs(sess, used_libraries) - .into_iter() - .map(|(raw_dylib_name, raw_dylib_imports)| { - let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; - let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib")); - - let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target); - - let items: Vec = raw_dylib_imports - .iter() - .map(|import: &DllImport| { - if sess.target.arch == "x86" { - ImportLibraryItem { - name: common::i686_decorated_name( - import, - mingw_gnu_toolchain, - false, - false, - ), - ordinal: import.ordinal(), - symbol_name: import.is_missing_decorations().then(|| { - common::i686_decorated_name( - import, - mingw_gnu_toolchain, - false, - true, - ) - }), - is_data: !import.is_fn, - } - } else { - ImportLibraryItem { - name: import.name.to_string(), - ordinal: import.ordinal(), - symbol_name: None, - is_data: !import.is_fn, - } - } - }) - .collect(); - - archive_builder_builder.create_dll_import_lib( - sess, - &raw_dylib_name, - items, - &output_path, - ); - - output_path - }) - .collect() -} - /// Create a static archive. /// /// This is essentially the same thing as an rlib, but it also involves adding all of the upstream @@ -2418,15 +2322,39 @@ fn linker_with_args( link_output_kind, ); + // Raw-dylibs from all crates. + let raw_dylib_dir = tmpdir.join("raw-dylibs"); + if sess.target.binary_format == BinaryFormat::Elf { + // On ELF we can't pass the raw-dylibs stubs to the linker as a path, + // instead we need to pass them via -l. To find the stub, we need to add + // 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 }) + } + cmd.include_path(&raw_dylib_dir); + } + // Link with the import library generated for any raw-dylib functions. - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - codegen_results.crate_info.used_libraries.iter(), - tmpdir, - true, - ) { - cmd.add_object(&output_path); + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + codegen_results.crate_info.used_libraries.iter(), + tmpdir, + true, + ) { + cmd.add_object(&output_path); + } + } else { + for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects( + sess, + codegen_results.crate_info.used_libraries.iter(), + &raw_dylib_dir, + ) { + // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects. + cmd.link_dylib_by_name(&link_path, true, false); + } } // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case // they are used within inlined functions or instantiated generic functions. We do this *after* @@ -2445,19 +2373,35 @@ fn linker_with_args( .native_libraries .iter() .filter_map(|(&cnum, libraries)| { - (dependency_linkage[cnum] != Linkage::Static).then_some(libraries) + if sess.target.is_like_windows { + (dependency_linkage[cnum] != Linkage::Static).then_some(libraries) + } else { + Some(libraries) + } }) .flatten() .collect::>(); native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str())); - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - native_libraries_from_nonstatics, - tmpdir, - false, - ) { - cmd.add_object(&output_path); + + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + native_libraries_from_nonstatics, + tmpdir, + false, + ) { + cmd.add_object(&output_path); + } + } else { + for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects( + sess, + native_libraries_from_nonstatics, + &raw_dylib_dir, + ) { + // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects. + cmd.link_dylib_by_name(&link_path, true, false); + } } // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs new file mode 100644 index 0000000000000..2c24378afe13b --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs @@ -0,0 +1,373 @@ +use std::fs; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; + +use rustc_abi::Endian; +use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_hashes::Hash128; +use rustc_session::Session; +use rustc_session::cstore::DllImport; +use rustc_session::utils::NativeLibKind; +use rustc_span::Symbol; + +use crate::back::archive::ImportLibraryItem; +use crate::back::link::ArchiveBuilderBuilder; +use crate::errors::ErrorCreatingImportLibrary; +use crate::{NativeLib, common, errors}; + +/// Extract all symbols defined in raw-dylib libraries, collated by library name. +/// +/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, +/// then the CodegenResults value contains one NativeLib instance for each block. However, the +/// linker appears to expect only a single import library for each library used, so we need to +/// collate the symbols together by library name before generating the import libraries. +fn collate_raw_dylibs_windows<'a>( + sess: &Session, + used_libraries: impl IntoIterator, +) -> Vec<(String, Vec)> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); + + for lib in used_libraries { + if lib.kind == NativeLibKind::RawDylib { + let ext = if lib.verbatim { "" } else { ".dll" }; + let name = format!("{}{}", lib.name, ext); + let imports = dylib_table.entry(name.clone()).or_default(); + for import in &lib.dll_imports { + if let Some(old_import) = imports.insert(import.name, import) { + // 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 { + span: import.span, + function: import.name, + library_name: &name, + }); + } + } + } + } + } + sess.dcx().abort_if_errors(); + dylib_table + .into_iter() + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) + }) + .collect() +} + +pub(super) fn create_raw_dylib_dll_import_libs<'a>( + sess: &Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, + used_libraries: impl IntoIterator, + tmpdir: &Path, + is_direct_dependency: bool, +) -> Vec { + collate_raw_dylibs_windows(sess, used_libraries) + .into_iter() + .map(|(raw_dylib_name, raw_dylib_imports)| { + let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; + let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib")); + + let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target); + + let items: Vec = raw_dylib_imports + .iter() + .map(|import: &DllImport| { + if sess.target.arch == "x86" { + ImportLibraryItem { + name: common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + false, + ), + ordinal: import.ordinal(), + symbol_name: import.is_missing_decorations().then(|| { + common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + true, + ) + }), + is_data: !import.is_fn, + } + } else { + ImportLibraryItem { + name: import.name.to_string(), + ordinal: import.ordinal(), + symbol_name: None, + is_data: !import.is_fn, + } + } + }) + .collect(); + + archive_builder_builder.create_dll_import_lib( + sess, + &raw_dylib_name, + items, + &output_path, + ); + + output_path + }) + .collect() +} + +/// Extract all symbols defined in raw-dylib libraries, collated by library name. +/// +/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, +/// then the CodegenResults value contains one NativeLib instance for each block. However, the +/// linker appears to expect only a single import library for each library used, so we need to +/// collate the symbols together by library name before generating the import libraries. +fn collate_raw_dylibs_elf<'a>( + sess: &Session, + used_libraries: impl IntoIterator, +) -> Vec<(String, Vec)> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); + + for lib in used_libraries { + if lib.kind == NativeLibKind::RawDylib { + let filename = if lib.verbatim { + lib.name.as_str().to_owned() + } else { + let ext = sess.target.dll_suffix.as_ref(); + let prefix = sess.target.dll_prefix.as_ref(); + format!("{prefix}{}{ext}", lib.name) + }; + + let imports = dylib_table.entry(filename.clone()).or_default(); + for import in &lib.dll_imports { + imports.insert(import.name, import); + } + } + } + sess.dcx().abort_if_errors(); + dylib_table + .into_iter() + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) + }) + .collect() +} + +pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>( + sess: &Session, + used_libraries: impl IntoIterator, + raw_dylib_so_dir: &Path, +) -> Vec { + collate_raw_dylibs_elf(sess, used_libraries) + .into_iter() + .map(|(load_filename, raw_dylib_imports)| { + use std::hash::Hash; + + // `load_filename` is the *target/loader* filename that will end up in NEEDED. + // Usually this will be something like `libc.so` or `libc.so.6` but with + // verbatim it might also be an absolute path. + // To be able to support this properly, we always put this load filename + // into the SONAME of the library and link it via a temporary file with a random name. + // This also avoids naming conflicts with non-raw-dylib linkage of the same library. + + let shared_object = create_elf_raw_dylib_stub(sess, &load_filename, &raw_dylib_imports); + + let mut file_name_hasher = StableHasher::new(); + load_filename.hash(&mut file_name_hasher); + for raw_dylib in raw_dylib_imports { + raw_dylib.name.as_str().hash(&mut file_name_hasher); + } + + let library_filename: Hash128 = file_name_hasher.finish(); + let temporary_lib_name = format!( + "{}{}{}", + sess.target.dll_prefix, + library_filename.as_u128().to_base_fixed_len(CASE_INSENSITIVE), + sess.target.dll_suffix + ); + let link_path = raw_dylib_so_dir.join(&temporary_lib_name); + + let file = match fs::File::create_new(&link_path) { + Ok(file) => file, + Err(error) => sess.dcx().emit_fatal(ErrorCreatingImportLibrary { + lib_name: &load_filename, + error: error.to_string(), + }), + }; + if let Err(error) = BufWriter::new(file).write_all(&shared_object) { + sess.dcx().emit_fatal(ErrorCreatingImportLibrary { + lib_name: &load_filename, + error: error.to_string(), + }); + }; + + temporary_lib_name + }) + .collect() +} + +/// Create an ELF .so stub file for raw-dylib. +/// It exports all the provided symbols, but is otherwise empty. +fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]) -> Vec { + use object::write::elf as write; + use object::{Architecture, elf}; + + let mut stub_buf = Vec::new(); + + // Build the stub ELF using the object crate. + // The high-level portable API does not allow for the fine-grained control we need, + // so this uses the low-level object::write::elf API. + // The low-level API consists of two stages: reservation and writing. + // We first reserve space for all the things in the binary and then write them. + // It is important that the order of reservation matches the order of writing. + // The object crate contains many debug asserts that fire if you get this wrong. + + let endianness = match sess.target.options.endian { + Endian::Little => object::Endianness::Little, + Endian::Big => object::Endianness::Big, + }; + let mut stub = write::Writer::new(endianness, true, &mut stub_buf); + + // These initial reservations don't reserve any bytes in the binary yet, + // they just allocate in the internal data structures. + + // First, we crate the dynamic symbol table. It starts with a null symbol + // and then all the symbols and their dynamic strings. + stub.reserve_null_dynamic_symbol_index(); + + let dynstrs = symbols + .iter() + .map(|sym| { + stub.reserve_dynamic_symbol_index(); + (sym, stub.add_dynamic_string(sym.name.as_str().as_bytes())) + }) + .collect::>(); + + let soname = stub.add_dynamic_string(soname.as_bytes()); + + // Reserve the sections. + // We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to. + stub.reserve_shstrtab_section_index(); + let text_section_name = stub.add_section_name(".text".as_bytes()); + let text_section = stub.reserve_section_index(); + stub.reserve_dynstr_section_index(); + stub.reserve_dynsym_section_index(); + stub.reserve_dynamic_section_index(); + + // These reservations now determine the actual layout order of the object file. + stub.reserve_file_header(); + stub.reserve_shstrtab(); + stub.reserve_section_headers(); + stub.reserve_dynstr(); + stub.reserve_dynsym(); + stub.reserve_dynamic(2); // DT_SONAME, DT_NULL + + // First write the ELF header with the arch information. + let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features) + else { + sess.dcx().fatal(format!( + "raw-dylib is not supported for the architecture `{}`", + sess.target.arch + )); + }; + let e_machine = match (arch, sub_arch) { + (Architecture::Aarch64, None) => elf::EM_AARCH64, + (Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64, + (Architecture::Arm, None) => elf::EM_ARM, + (Architecture::Avr, None) => elf::EM_AVR, + (Architecture::Bpf, None) => elf::EM_BPF, + (Architecture::Csky, None) => elf::EM_CSKY, + (Architecture::E2K32, None) => elf::EM_MCST_ELBRUS, + (Architecture::E2K64, None) => elf::EM_MCST_ELBRUS, + (Architecture::I386, None) => elf::EM_386, + (Architecture::X86_64, None) => elf::EM_X86_64, + (Architecture::X86_64_X32, None) => elf::EM_X86_64, + (Architecture::Hexagon, None) => elf::EM_HEXAGON, + (Architecture::LoongArch64, None) => elf::EM_LOONGARCH, + (Architecture::M68k, None) => elf::EM_68K, + (Architecture::Mips, None) => elf::EM_MIPS, + (Architecture::Mips64, None) => elf::EM_MIPS, + (Architecture::Mips64_N32, None) => elf::EM_MIPS, + (Architecture::Msp430, None) => elf::EM_MSP430, + (Architecture::PowerPc, None) => elf::EM_PPC, + (Architecture::PowerPc64, None) => elf::EM_PPC64, + (Architecture::Riscv32, None) => elf::EM_RISCV, + (Architecture::Riscv64, None) => elf::EM_RISCV, + (Architecture::S390x, None) => elf::EM_S390, + (Architecture::Sbf, None) => elf::EM_SBF, + (Architecture::Sharc, None) => elf::EM_SHARC, + (Architecture::Sparc, None) => elf::EM_SPARC, + (Architecture::Sparc32Plus, None) => elf::EM_SPARC32PLUS, + (Architecture::Sparc64, None) => elf::EM_SPARCV9, + (Architecture::Xtensa, None) => elf::EM_XTENSA, + _ => { + sess.dcx().fatal(format!( + "raw-dylib is not supported for the architecture `{}`", + sess.target.arch + )); + } + }; + + stub.write_file_header(&write::FileHeader { + os_abi: crate::back::metadata::elf_os_abi(sess), + abi_version: 0, + e_type: object::elf::ET_DYN, + e_machine, + e_entry: 0, + e_flags: crate::back::metadata::elf_e_flags(arch, sess), + }) + .unwrap(); + + // .shstrtab + stub.write_shstrtab(); + + // Section headers + stub.write_null_section_header(); + stub.write_shstrtab_section_header(); + // Create a dummy .text section for our dummy symbols. + stub.write_section_header(&write::SectionHeader { + name: Some(text_section_name), + sh_type: elf::SHT_PROGBITS, + sh_flags: 0, + sh_addr: 0, + sh_offset: 0, + sh_size: 0, + sh_link: 0, + sh_info: 0, + sh_addralign: 1, + sh_entsize: 0, + }); + stub.write_dynstr_section_header(0); + stub.write_dynsym_section_header(0, 1); + stub.write_dynamic_section_header(0); + + // .dynstr + stub.write_dynstr(); + + // .dynsym + stub.write_null_dynamic_symbol(); + for (_, name) in dynstrs { + stub.write_dynamic_symbol(&write::Sym { + name: Some(name), + st_info: (elf::STB_GLOBAL << 4) | elf::STT_NOTYPE, + st_other: elf::STV_DEFAULT, + section: Some(text_section), + st_shndx: 0, // ignored by object in favor of the `section` field + st_value: 0, + st_size: 0, + }); + } + + // .dynamic + // the DT_SONAME will be used by the linker to populate DT_NEEDED + // which the loader uses to find the library. + // DT_NULL terminates the .dynamic table. + stub.write_dynamic_string(elf::DT_SONAME, soname); + stub.write_dynamic(elf::DT_NULL, 0); + + stub_buf +} diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 236507ac0cd28..75179a65e3426 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -9,8 +9,7 @@ use itertools::Itertools; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol, - SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe, - xcoff, + SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff, }; use rustc_abi::Endian; use rustc_data_structures::memmap::Mmap; @@ -206,51 +205,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Endianness::Little, Endian::Big => Endianness::Big, }; - let (architecture, sub_architecture) = match &sess.target.arch[..] { - "arm" => (Architecture::Arm, None), - "aarch64" => ( - if sess.target.pointer_width == 32 { - Architecture::Aarch64_Ilp32 - } else { - Architecture::Aarch64 - }, - None, - ), - "x86" => (Architecture::I386, None), - "s390x" => (Architecture::S390x, None), - "mips" | "mips32r6" => (Architecture::Mips, None), - "mips64" | "mips64r6" => (Architecture::Mips64, None), - "x86_64" => ( - if sess.target.pointer_width == 32 { - Architecture::X86_64_X32 - } else { - Architecture::X86_64 - }, - None, - ), - "powerpc" => (Architecture::PowerPc, None), - "powerpc64" => (Architecture::PowerPc64, None), - "riscv32" => (Architecture::Riscv32, None), - "riscv64" => (Architecture::Riscv64, None), - "sparc" => { - if sess.unstable_target_features.contains(&sym::v8plus) { - // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode - (Architecture::Sparc32Plus, None) - } else { - // Target uses V7 or V8, aka EM_SPARC - (Architecture::Sparc, None) - } - } - "sparc64" => (Architecture::Sparc64, None), - "avr" => (Architecture::Avr, None), - "msp430" => (Architecture::Msp430, None), - "hexagon" => (Architecture::Hexagon, None), - "bpf" => (Architecture::Bpf, None), - "loongarch64" => (Architecture::LoongArch64, None), - "csky" => (Architecture::Csky, None), - "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), - // Unsupported architecture. - _ => return None, + let Some((architecture, sub_architecture)) = + sess.target.object_architecture(&sess.unstable_target_features) + else { + return None; }; let binary_format = sess.target.binary_format.to_object(); @@ -292,7 +250,26 @@ pub(crate) fn create_object_file(sess: &Session) -> Option u8 { + match sess.target.options.os.as_ref() { + "hermit" => elf::ELFOSABI_STANDALONE, + "freebsd" => elf::ELFOSABI_FREEBSD, + "solaris" => elf::ELFOSABI_SOLARIS, + _ => elf::ELFOSABI_NONE, + } +} + +pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { + match architecture { Architecture::Mips => { let arch = match sess.target.options.cpu.as_ref() { "mips1" => elf::EF_MIPS_ARCH_1, @@ -383,18 +360,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option 0, - }; - // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` - let os_abi = match sess.target.options.os.as_ref() { - "hermit" => elf::ELFOSABI_STANDALONE, - "freebsd" => elf::ELFOSABI_FREEBSD, - "solaris" => elf::ELFOSABI_SOLARIS, - _ => elf::ELFOSABI_NONE, - }; - let abi_version = 0; - add_gnu_property_note(&mut file, architecture, binary_format, endianness); - file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; - Some(file) + } } /// Mach-O files contain information about: diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 66c26a541f17f..813a773c70e5e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -599,6 +599,8 @@ declare_features! ( (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), + /// Allows the use of raw-dylibs on ELF platforms + (incomplete, raw_dylib_elf, "CURRENT_RUSTC_VERSION", Some(135694)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index df0a25712cca4..20f66fae5c01e 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -244,6 +244,9 @@ metadata_prev_alloc_error_handler = metadata_prev_global_alloc = previous global allocator defined here +metadata_raw_dylib_elf_unstable = + link kind `raw-dylib` is unstable on ELF platforms + metadata_raw_dylib_no_nul = link name must not contain NUL characters if link kind is `raw-dylib` diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index e2d043f47c0ef..b96921a63f352 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -17,7 +17,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::LinkSelfContainedComponents; +use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents}; use crate::{errors, fluent_generated}; @@ -263,9 +263,26 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { - if !sess.target.is_like_windows { + if sess.target.is_like_windows { + // raw-dylib is stable and working on Windows + } else if sess.target.binary_format == BinaryFormat::Elf + && features.raw_dylib_elf() + { + // raw-dylib is unstable on ELF, but the user opted in + } else if sess.target.binary_format == BinaryFormat::Elf + && sess.is_nightly_build() + { + feature_err( + sess, + sym::raw_dylib_elf, + span, + fluent_generated::metadata_raw_dylib_elf_unstable, + ) + .emit(); + } else { sess.dcx().emit_err(errors::RawDylibOnlyWindows { span }); } + NativeLibKind::RawDylib } "link-arg" => { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 9182789cf0269..fcede379b893a 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -34,6 +34,7 @@ pub enum NativeLibKind { as_needed: Option, }, /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library. + /// On Linux, it refers to a generated shared library stub. RawDylib, /// A macOS-specific kind of dynamic libraries. Framework { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 501c9039f2de9..e8d47d4330a72 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1624,6 +1624,7 @@ symbols! { quote, range_inclusive_new, raw_dylib, + raw_dylib_elf, raw_eq, raw_identifiers, raw_ref_op, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index cc8162a2f27ea..72202129f5b60 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -43,7 +43,7 @@ use std::str::FromStr; use std::{fmt, io}; use rustc_abi::{Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_fs_util::try_canonicalize; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -3535,6 +3535,59 @@ impl Target { s => s.clone(), } } + + pub fn object_architecture( + &self, + unstable_target_features: &FxIndexSet, + ) -> Option<(object::Architecture, Option)> { + use object::Architecture; + Some(match self.arch.as_ref() { + "arm" => (Architecture::Arm, None), + "aarch64" => ( + if self.pointer_width == 32 { + Architecture::Aarch64_Ilp32 + } else { + Architecture::Aarch64 + }, + None, + ), + "x86" => (Architecture::I386, None), + "s390x" => (Architecture::S390x, None), + "mips" | "mips32r6" => (Architecture::Mips, None), + "mips64" | "mips64r6" => (Architecture::Mips64, None), + "x86_64" => ( + if self.pointer_width == 32 { + Architecture::X86_64_X32 + } else { + Architecture::X86_64 + }, + None, + ), + "powerpc" => (Architecture::PowerPc, None), + "powerpc64" => (Architecture::PowerPc64, None), + "riscv32" => (Architecture::Riscv32, None), + "riscv64" => (Architecture::Riscv64, None), + "sparc" => { + if unstable_target_features.contains(&sym::v8plus) { + // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode + (Architecture::Sparc32Plus, None) + } else { + // Target uses V7 or V8, aka EM_SPARC + (Architecture::Sparc, None) + } + } + "sparc64" => (Architecture::Sparc64, None), + "avr" => (Architecture::Avr, None), + "msp430" => (Architecture::Msp430, None), + "hexagon" => (Architecture::Hexagon, None), + "bpf" => (Architecture::Bpf, None), + "loongarch64" => (Architecture::LoongArch64, None), + "csky" => (Architecture::Csky, None), + "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)), + // Unsupported architecture. + _ => return None, + }) + } } /// Either a target tuple string or a path to a JSON file. diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 00bb2bc4dbb1e..af9cb85d27b53 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -142,6 +142,7 @@ Some examples of `X` in `ignore-X` or `only-X`: matches that target as well as the emscripten targets. - Pointer width: `32bit`, `64bit` - Endianness: `endian-big` +- Binary format: `elf` - Stage: `stage0`, `stage1`, `stage2` - Channel: `stable`, `beta` - When cross compiling: `cross-compile` diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 8c909bcb19527..b2ad5a3b3d0bb 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -52,6 +52,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-coverage-run", "ignore-cross-compile", "ignore-eabi", + "ignore-elf", "ignore-emscripten", "ignore-endian-big", "ignore-enzyme", @@ -182,6 +183,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-bpf", "only-cdb", "only-dist", + "only-elf", "only-emscripten", "only-gnu", "only-i686-pc-windows-gnu", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 72a3b9d85c8cf..c369fff97f4f0 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -166,6 +166,16 @@ fn parse_cfg_name_directive<'a>( message: "when the target vendor is Apple" } + condition! { + name: "elf", + condition: !config.target.contains("windows") + && !config.target.contains("wasm") + && !config.target.contains("apple") + && !config.target.contains("aix") + && !config.target.contains("uefi"), + message: "when the target binary format is ELF" + } + condition! { name: "enzyme", condition: config.has_enzyme, diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c69..73ad248b6f363 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -60,6 +60,8 @@ fn main() { regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", ) + .normalize(r#""[^"]*\/symbols.o""#, "\"/symbols.o\"") + .normalize(r#""[^"]*\/raw-dylibs""#, "\"/raw-dylibs\"") .run(); } diff --git a/tests/run-make/linker-warning/short-error.txt b/tests/run-make/linker-warning/short-error.txt index dd3b742bbfd56..a7f48af885a05 100644 --- a/tests/run-make/linker-warning/short-error.txt +++ b/tests/run-make/linker-warning/short-error.txt @@ -1,6 +1,6 @@ error: linking with `./fake-linker` failed: exit status: 1 | - = note: "./fake-linker" "-m64" "/tmp/rustc/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" + = note: "./fake-linker" "-m64" "/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" = note: some arguments are omitted. use `--verbose` to show all linker arguments = note: error: baz diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs new file mode 100644 index 0000000000000..75bd7747f4fe7 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "/absolute-path/liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs new file mode 100644 index 0000000000000..d2a9b0477e5e6 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs @@ -0,0 +1,20 @@ +//@ only-elf +//@ ignore-cross-compile: Runs a binary. +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//! Ensure ELF raw-dylib is able to link against a non-existent verbatim absolute path +//! by embedding the absolute path in the DT_SONAME and passing a different path for +//! the linker for the stub. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // The verbatim library name is an absolute path. + rustc().crate_type("bin").input("main.rs").run(); + + // FIXME(raw_dylib_elf): Read the NEEDED of the library to ensure it's the absolute path. +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/library.c b/tests/run-make/raw-dylib-elf-verbatim/library.c new file mode 100644 index 0000000000000..2e3a95b7edeca --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/library.c @@ -0,0 +1,3 @@ +int this_is_a_library_function() { + return 42; +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/main.rs b/tests/run-make/raw-dylib-elf-verbatim/main.rs new file mode 100644 index 0000000000000..044b7400a8412 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/output.txt b/tests/run-make/raw-dylib-elf-verbatim/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf-verbatim/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs new file mode 100644 index 0000000000000..319534b24c882 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs @@ -0,0 +1,31 @@ +//@ only-elf +//@ ignore-cross-compile: Runs a binary. +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//! Ensure ELF raw-dylib is able to link against the verbatim versioned library +//! without it being present, and then be executed against this library. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // We also set the rpath to the current directory so we can pick up the library at runtime. + rustc() + .crate_type("bin") + .input("main.rs") + .arg(&format!("-Wl,-rpath={}", cwd().display())) + .run(); + + // Now, *after* building the binary, we build the library... + build_native_dynamic_lib("library"); + // ... rename it to have the versioned library name... + rfs::rename("liblibrary.so", "liblibrary.so.1"); + + // ... and run with this library, ensuring it was linked correctly at runtime. + let output = run("main").stdout_utf8(); + + diff().expected_file("output.txt").actual_text("actual", output).run(); +} diff --git a/tests/run-make/raw-dylib-elf/library.c b/tests/run-make/raw-dylib-elf/library.c new file mode 100644 index 0000000000000..2e3a95b7edeca --- /dev/null +++ b/tests/run-make/raw-dylib-elf/library.c @@ -0,0 +1,3 @@ +int this_is_a_library_function() { + return 42; +} diff --git a/tests/run-make/raw-dylib-elf/main.rs b/tests/run-make/raw-dylib-elf/main.rs new file mode 100644 index 0000000000000..3be944d295148 --- /dev/null +++ b/tests/run-make/raw-dylib-elf/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "library", kind = "raw-dylib")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf/output.txt b/tests/run-make/raw-dylib-elf/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf/rmake.rs b/tests/run-make/raw-dylib-elf/rmake.rs new file mode 100644 index 0000000000000..59f901ac1ed72 --- /dev/null +++ b/tests/run-make/raw-dylib-elf/rmake.rs @@ -0,0 +1,29 @@ +//@ only-elf +//@ ignore-cross-compile: Runs a binary. +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//! Ensure ELF raw-dylib is able to link the binary without having the library present, +//! and then successfully run against the real library. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // We also set the rpath to the current directory so we can pick up the library at runtime. + rustc() + .crate_type("bin") + .input("main.rs") + .arg(&format!("-Wl,-rpath={}", cwd().display())) + .run(); + + // Now, *after* building the binary, we build the library... + build_native_dynamic_lib("library"); + + // ... and run with this library, ensuring it was linked correctly at runtime. + let output = run("main").stdout_utf8(); + + diff().expected_file("output.txt").actual_text("actual", output).run(); +} diff --git a/tests/run-make/reproducible-build/linker.rs b/tests/run-make/reproducible-build/linker.rs index ab3b4049cc321..2f57d9f9be9a4 100644 --- a/tests/run-make/reproducible-build/linker.rs +++ b/tests/run-make/reproducible-build/linker.rs @@ -17,6 +17,8 @@ fn main() { for arg in env::args().skip(1) { let path = Path::new(&arg); if !path.is_file() { + // This directory is produced during linking in a temporary directory (ELF only). + let arg = if arg.ends_with("/raw-dylibs") { "/raw-dylibs" } else { &*arg }; out.push_str(&arg); out.push_str("\n"); continue; diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs new file mode 100644 index 0000000000000..ec49e53d9b447 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs @@ -0,0 +1,9 @@ +//@ only-elf +//@ needs-dynamic-linking + +#[link(name = "meow", kind = "raw-dylib")] //~ ERROR: link kind `raw-dylib` is unstable on ELF platforms +unsafe extern "C" { + safe fn meowmeow(); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr new file mode 100644 index 0000000000000..dfbf39f5a189c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr @@ -0,0 +1,13 @@ +error[E0658]: link kind `raw-dylib` is unstable on ELF platforms + --> $DIR/feature-gate-raw-dylib-elf.rs:4:30 + | +LL | #[link(name = "meow", kind = "raw-dylib")] + | ^^^^^^^^^^^ + | + = note: see issue #135694 for more information + = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs new file mode 100644 index 0000000000000..f4715ff2d3d60 --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs @@ -0,0 +1,37 @@ +//@ only-elf +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + + +#[cfg_attr(with, link(name = "rawdylibbutfordogs", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutfordogs"))] +unsafe extern "C" { + safe fn woooooooooooooooooof(); +} + +fn main() { + meooooooooooooooow(); + woooooooooooooooooof(); +} diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs new file mode 100644 index 0000000000000..fe9c7884e54d1 --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs @@ -0,0 +1,28 @@ +//@ only-elf +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + +fn main() { + meooooooooooooooow(); +} diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs new file mode 100644 index 0000000000000..72cba18d84114 --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs @@ -0,0 +1,29 @@ +//@ only-elf +//@ needs-dynamic-linking +// FIXME(raw_dylib_elf): Debug the failures on other targets. +//@ only-gnu +//@ only-x86_64 + +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib, but with verbatim. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib", modifiers = "+verbatim"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats", modifiers = "+verbatim"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + +fn main() { + meooooooooooooooow(); +} diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs rename to tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs rename to tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs rename to tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr new file mode 100644 index 0000000000000..70945ed6fc0bc --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr @@ -0,0 +1,13 @@ +error[E0658]: link kind `raw-dylib` is unstable on ELF platforms + --> $DIR/raw-dylib-windows-only.rs:6:29 + | +LL | #[link(name = "foo", kind = "raw-dylib")] + | ^^^^^^^^^^^ + | + = note: see issue #135694 for more information + = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr similarity index 86% rename from tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr index ede20cb8c3f76..daed15d784a5d 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.notelf.stderr @@ -1,5 +1,5 @@ error[E0455]: link kind `raw-dylib` is only supported on Windows targets - --> $DIR/raw-dylib-windows-only.rs:3:29 + --> $DIR/raw-dylib-windows-only.rs:6:29 | LL | #[link(name = "foo", kind = "raw-dylib")] | ^^^^^^^^^^^ diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs new file mode 100644 index 0000000000000..935c59b5aaa5e --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs @@ -0,0 +1,9 @@ +//@ revisions: elf notelf +//@ [elf] only-elf +//@ [notelf] ignore-windows +//@ [notelf] ignore-elf +//@ compile-flags: --crate-type lib +#[link(name = "foo", kind = "raw-dylib")] +//[notelf]~^ ERROR: link kind `raw-dylib` is only supported on Windows targets +//[elf]~^^ ERROR: link kind `raw-dylib` is unstable on ELF platforms +extern "C" {} diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs rename to tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs deleted file mode 100644 index 3b982857db8dc..0000000000000 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ ignore-windows -//@ compile-flags: --crate-type lib -#[link(name = "foo", kind = "raw-dylib")] -//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets -extern "C" {} From c4d642616d8fb74d9884bdc0b8df270d13739de3 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 1 Mar 2025 04:47:36 +0100 Subject: [PATCH 2/6] Set target_vendor = "openwrt" On mips64-openwrt-linux-musl target. --- .../rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs | 1 + tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.feature.stderr | 2 +- tests/ui/check-cfg/exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs index 1300280e35b0f..71b3fbe00b2fe 100644 --- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs @@ -23,6 +23,7 @@ pub(crate) fn target() -> Target { data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(), arch: "mips64".into(), options: TargetOptions { + vendor: "openwrt".into(), abi: "abi64".into(), endian: Endian::Big, mcount: "_mcount".into(), diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index e7b8f35505761..b07d630e5f5dc 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 95af0a9092993..80f8f36c23f78 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value` LL | #[cfg(target_vendor = "value")] | ^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `unk` diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index ba1900fcddb2d..4636b6945d060 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` + = note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `openwrt`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From 53ee6968a3664c36fbc78530cb7795f2259e6a0c Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 4 Mar 2025 00:27:22 +0800 Subject: [PATCH 3/6] Update MSVC INSTALL.md instructions to recommend VS 2022 + recent Windows 10/11 SDK --- INSTALL.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 74fcc58348b43..a46d3d70093f1 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -210,9 +210,13 @@ itself back on after some time). ### MSVC -MSVC builds of Rust additionally require an installation of Visual Studio 2017 -(or later) so `rustc` can use its linker. The simplest way is to get -[Visual Studio], check the "C++ build tools" and "Windows 10 SDK" workload. +MSVC builds of Rust additionally requires an installation of: + +- Visual Studio 2022 (or later) build tools so `rustc` can use its linker. Older + Visual Studio versions such as 2019 *may* work but aren't actively tested. +- A recent Windows 10 or 11 SDK. + +The simplest way is to get [Visual Studio], check the "C++ build tools". [Visual Studio]: https://visualstudio.microsoft.com/downloads/ From a89cddb2be47b52ec8373165e0d69448df80a23f Mon Sep 17 00:00:00 2001 From: Kirill Podoprigora Date: Mon, 3 Mar 2025 22:58:03 +0200 Subject: [PATCH 4/6] Add ``dyn`` keyword --- compiler/rustc_error_codes/src/error_codes/E0373.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index d4d26007aa50e..b9db807259728 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -3,7 +3,7 @@ A captured variable in a closure may not live long enough. Erroneous code example: ```compile_fail,E0373 -fn foo() -> Box u32> { +fn foo() -> Box u32> { let x = 0u32; Box::new(|y| x + y) } @@ -42,7 +42,7 @@ This approach moves (or copies, where possible) data into the closure, rather than taking references to it. For example: ``` -fn foo() -> Box u32> { +fn foo() -> Box u32> { let x = 0u32; Box::new(move |y| x + y) } From 3e5fddc95ea2d8851def90b940030d1c97bd5b00 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Mar 2025 05:25:46 +0000 Subject: [PATCH 5/6] Allow struct field default values to reference struct's generics --- .../src/collect/generics_of.rs | 2 ++ compiler/rustc_resolve/src/late.rs | 4 ++- .../structs/default-field-values/failures.rs | 4 +-- .../default-field-values/failures.stderr | 17 +---------- .../field-references-param.rs | 29 +++++++++++++++++++ .../post-mono.direct.stderr | 23 +++++++++++++++ .../post-mono.indirect.stderr | 29 +++++++++++++++++++ .../structs/default-field-values/post-mono.rs | 23 +++++++++++++++ 8 files changed, 112 insertions(+), 19 deletions(-) create mode 100644 tests/ui/structs/default-field-values/field-references-param.rs create mode 100644 tests/ui/structs/default-field-values/post-mono.direct.stderr create mode 100644 tests/ui/structs/default-field-values/post-mono.indirect.stderr create mode 100644 tests/ui/structs/default-field-values/post-mono.rs diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index af1338e50d007..a153ce8ea902d 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -187,6 +187,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { Some(parent_did) } Node::TyPat(_) => Some(parent_did), + // Field default values inherit the ADT's generics. + Node::Field(_) => Some(parent_did), _ => None, } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f119ed55e7d1b..3e8946d9291c6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -78,6 +78,7 @@ struct IsNeverPattern; #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum AnonConstKind { EnumDiscriminant, + FieldDefaultValue, InlineConst, ConstArg(IsRepeatExpr), } @@ -1406,7 +1407,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r visit_opt!(self, visit_ident, ident); try_visit!(self.visit_ty(ty)); if let Some(v) = &default { - self.resolve_anon_const(v, AnonConstKind::ConstArg(IsRepeatExpr::No)); + self.resolve_anon_const(v, AnonConstKind::FieldDefaultValue); } } } @@ -4658,6 +4659,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::EnumDiscriminant => { ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant) } + AnonConstKind::FieldDefaultValue => ConstantHasGenerics::Yes, AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) => { if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg { diff --git a/tests/ui/structs/default-field-values/failures.rs b/tests/ui/structs/default-field-values/failures.rs index 0ac071d91d65e..1e94eecb4f870 100644 --- a/tests/ui/structs/default-field-values/failures.rs +++ b/tests/ui/structs/default-field-values/failures.rs @@ -17,9 +17,9 @@ pub struct Bar { #[derive(Default)] pub struct Qux { - bar: S = Self::S, //~ ERROR generic `Self` types are currently not permitted in anonymous constants + bar: S = Self::S, baz: i32 = foo(), - bat: i32 = as T>::K, //~ ERROR generic parameters may not be used in const operations + bat: i32 = as T>::K, bay: i32 = C, } diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr index 65ec100fe2ea3..50553816462d1 100644 --- a/tests/ui/structs/default-field-values/failures.stderr +++ b/tests/ui/structs/default-field-values/failures.stderr @@ -6,27 +6,12 @@ LL | Variant {} | = help: consider a manual implementation of `Default` -error: generic parameters may not be used in const operations - --> $DIR/failures.rs:22:23 - | -LL | bat: i32 = as T>::K, - | ^ cannot perform const operation using `C` - | - = help: const parameters may only be used as standalone arguments, i.e. `C` - = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - error: default fields are not supported in tuple structs --> $DIR/failures.rs:26:22 | LL | pub struct Rak(i32 = 42); | ^^ default fields are only supported on structs -error: generic `Self` types are currently not permitted in anonymous constants - --> $DIR/failures.rs:20:14 - | -LL | bar: S = Self::S, - | ^^^^ - error[E0277]: the trait bound `S: Default` is not satisfied --> $DIR/failures.rs:14:5 | @@ -112,7 +97,7 @@ LL - let _ = Rak(.., 0); LL + let _ = Rak(0); | -error: aborting due to 9 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0061, E0277, E0308. For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/structs/default-field-values/field-references-param.rs b/tests/ui/structs/default-field-values/field-references-param.rs new file mode 100644 index 0000000000000..ecee37edd42c0 --- /dev/null +++ b/tests/ui/structs/default-field-values/field-references-param.rs @@ -0,0 +1,29 @@ +//@ build-pass + +#![feature(default_field_values)] + +struct W; + +impl W { + const fn new() -> Self { W } +} + +struct Z { + // No inference. + one: W = W::::new(), + + // Inference works too. + two: W = W::new(), + + // An anon const that is too generic before substitution. + too_generic: usize = X + 1, +} + +fn use_generically() { + let x: Z = Z { .. }; +} + +fn main() { + let x: Z<0> = Z { .. }; + use_generically::<0>(); +} diff --git a/tests/ui/structs/default-field-values/post-mono.direct.stderr b/tests/ui/structs/default-field-values/post-mono.direct.stderr new file mode 100644 index 0000000000000..cdd80620c48a9 --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.direct.stderr @@ -0,0 +1,23 @@ +error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed + --> $DIR/post-mono.rs:7:24 + | +LL | post_mono: usize = X / 0, + | ^^^^^ attempt to divide `1_usize` by zero + +note: erroneous constant encountered + --> $DIR/post-mono.rs:17:19 + | +LL | let x: Z<1> = Z { .. }; + | ^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/post-mono.rs:17:19 + | +LL | let x: Z<1> = Z { .. }; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/structs/default-field-values/post-mono.indirect.stderr b/tests/ui/structs/default-field-values/post-mono.indirect.stderr new file mode 100644 index 0000000000000..56c27a6e5dc81 --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.indirect.stderr @@ -0,0 +1,29 @@ +error[E0080]: evaluation of `Z::<1>::post_mono::{constant#0}` failed + --> $DIR/post-mono.rs:7:24 + | +LL | post_mono: usize = X / 0, + | ^^^^^ attempt to divide `1_usize` by zero + +note: erroneous constant encountered + --> $DIR/post-mono.rs:12:19 + | +LL | let x: Z = Z { .. }; + | ^^^^^^^^ + +note: erroneous constant encountered + --> $DIR/post-mono.rs:12:19 + | +LL | let x: Z = Z { .. }; + | ^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +note: the above error was encountered while instantiating `fn indirect::<1>` + --> $DIR/post-mono.rs:22:5 + | +LL | indirect::<1>(); + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/structs/default-field-values/post-mono.rs b/tests/ui/structs/default-field-values/post-mono.rs new file mode 100644 index 0000000000000..4de31f6e2fbac --- /dev/null +++ b/tests/ui/structs/default-field-values/post-mono.rs @@ -0,0 +1,23 @@ +//@ build-fail +//@ revisions: direct indirect + +#![feature(default_field_values)] + +struct Z { + post_mono: usize = X / 0, + //~^ ERROR evaluation of `Z::<1>::post_mono::{constant#0}` failed +} + +fn indirect() { + let x: Z = Z { .. }; +} + +#[cfg(direct)] +fn main() { + let x: Z<1> = Z { .. }; +} + +#[cfg(indirect)] +fn main() { + indirect::<1>(); +} From 12cc2b969d4f45423bff1771af7dcbd2f97707ff Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 4 Mar 2025 13:23:40 +1100 Subject: [PATCH 6/6] Remove unused `PpMode::needs_hir` --- compiler/rustc_session/src/config.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7586c5766b585..671d9741e2f28 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2883,14 +2883,6 @@ impl PpMode { | StableMir => true, } } - pub fn needs_hir(&self) -> bool { - use PpMode::*; - match *self { - Source(_) | AstTree | AstTreeExpanded => false, - - Hir(_) | HirTree | ThirTree | ThirFlat | Mir | MirCFG | StableMir => true, - } - } pub fn needs_analysis(&self) -> bool { use PpMode::*;