diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8aa744ce93531..64742bbb98664 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -358,9 +358,9 @@ fn link_rlib<'a>( let (data, _) = create_wrapper_file(sess, b".bundled_lib".to_vec(), &src); let wrapper_file = emit_wrapper_file(sess, &data, tmpdir, filename.as_str()); packed_bundled_libs.push(wrapper_file); - } else if let Some(name) = lib.name { + } else { let path = - find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess); + find_native_static_library(lib.name.as_str(), lib.verbatim, &lib_search_paths, sess); ab.add_archive(&path, Box::new(|_| false)).unwrap_or_else(|error| { sess.emit_fatal(errors::AddNativeLibrary { library_path: path, error })}); } @@ -436,7 +436,7 @@ fn collate_raw_dylibs<'a, 'b>( for lib in used_libraries { if lib.kind == NativeLibKind::RawDylib { let ext = if lib.verbatim { "" } else { ".dll" }; - let name = format!("{}{}", lib.name.expect("unnamed raw-dylib library"), ext); + 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) { @@ -1294,7 +1294,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { .iter() .filter(|l| relevant_lib(sess, l)) .filter_map(|lib| { - let name = lib.name?; + let name = lib.name; match lib.kind { NativeLibKind::Static { bundle: Some(false), .. } | NativeLibKind::Dylib { .. } @@ -1315,6 +1315,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { // These are included, no need to print them NativeLibKind::Static { bundle: None | Some(true), .. } | NativeLibKind::LinkArg + | NativeLibKind::WasmImportModule | NativeLibKind::RawDylib => None, } }) @@ -2273,21 +2274,18 @@ fn add_native_libs_from_crate( let mut last = (None, NativeLibKind::Unspecified, false); for lib in native_libs { - let Some(name) = lib.name else { - continue; - }; if !relevant_lib(sess, lib) { continue; } // Skip if this library is the same as the last. - last = if (lib.name, lib.kind, lib.verbatim) == last { + last = if (Some(lib.name), lib.kind, lib.verbatim) == last { continue; } else { - (lib.name, lib.kind, lib.verbatim) + (Some(lib.name), lib.kind, lib.verbatim) }; - let name = name.as_str(); + let name = lib.name.as_str(); let verbatim = lib.verbatim; match lib.kind { NativeLibKind::Static { bundle, whole_archive } => { @@ -2344,6 +2342,7 @@ fn add_native_libs_from_crate( NativeLibKind::RawDylib => { // Handled separately in `linker_with_args`. } + NativeLibKind::WasmImportModule => {} NativeLibKind::LinkArg => { if link_static { cmd.arg(name); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 7b58e55dbe84a..18d17b1a0137c 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -595,7 +595,7 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap, + pub name: Symbol, pub filename: Option, pub cfg: Option, pub verbatim: bool, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index d6f68b2e14055..b855c8e433266 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -46,7 +46,7 @@ pub fn find_native_static_library( } fn find_bundled_library( - name: Option, + name: Symbol, verbatim: Option, kind: NativeLibKind, has_cfg: bool, @@ -58,7 +58,7 @@ fn find_bundled_library( { let verbatim = verbatim.unwrap_or(false); let search_paths = &sess.target_filesearch(PathKind::Native).search_path_dirs(); - return find_native_static_library(name.unwrap().as_str(), verbatim, search_paths, sess) + return find_native_static_library(name.as_str(), verbatim, search_paths, sess) .file_name() .and_then(|s| s.to_str()) .map(Symbol::intern); @@ -336,10 +336,16 @@ impl<'tcx> Collector<'tcx> { if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() { sess.emit_err(errors::IncompatibleWasmLink { span }); } - } else if name.is_none() { - sess.emit_err(errors::LinkRequiresName { span: m.span }); } + if wasm_import_module.is_some() { + (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule)); + } + let Some((name, name_span)) = name else { + sess.emit_err(errors::LinkRequiresName { span: m.span }); + continue; + }; + // Do this outside of the loop so that `import_name_type` can be specified before `kind`. if let Some((_, span)) = import_name_type { if kind != Some(NativeLibKind::RawDylib) { @@ -349,8 +355,8 @@ impl<'tcx> Collector<'tcx> { let dll_imports = match kind { Some(NativeLibKind::RawDylib) => { - if let Some((name, span)) = name && name.as_str().contains('\0') { - sess.emit_err(errors::RawDylibNoNul { span }); + if name.as_str().contains('\0') { + sess.emit_err(errors::RawDylibNoNul { span: name_span }); } foreign_mod_items .iter() @@ -389,7 +395,6 @@ impl<'tcx> Collector<'tcx> { } }; - let name = name.map(|(name, _)| name); let kind = kind.unwrap_or(NativeLibKind::Unspecified); let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), sess); self.libs.push(NativeLib { @@ -398,7 +403,6 @@ impl<'tcx> Collector<'tcx> { kind, cfg, foreign_module: Some(it.owner_id.to_def_id()), - wasm_import_module: wasm_import_module.map(|(name, _)| name), verbatim, dll_imports, }); @@ -415,11 +419,7 @@ impl<'tcx> Collector<'tcx> { self.tcx.sess.emit_err(errors::LibFrameworkApple); } if let Some(ref new_name) = lib.new_name { - let any_duplicate = self - .libs - .iter() - .filter_map(|lib| lib.name.as_ref()) - .any(|n| n.as_str() == lib.name); + let any_duplicate = self.libs.iter().any(|n| n.name.as_str() == lib.name); if new_name.is_empty() { self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name }); } else if !any_duplicate { @@ -444,33 +444,28 @@ impl<'tcx> Collector<'tcx> { let mut existing = self .libs .drain_filter(|lib| { - if let Some(lib_name) = lib.name { - if lib_name.as_str() == passed_lib.name { - // FIXME: This whole logic is questionable, whether modifiers are - // involved or not, library reordering and kind overriding without - // explicit `:rename` in particular. - if lib.has_modifiers() || passed_lib.has_modifiers() { - match lib.foreign_module { - Some(def_id) => { - self.tcx.sess.emit_err(errors::NoLinkModOverride { - span: Some(self.tcx.def_span(def_id)), - }) - } - None => self - .tcx - .sess - .emit_err(errors::NoLinkModOverride { span: None }), - }; - } - if passed_lib.kind != NativeLibKind::Unspecified { - lib.kind = passed_lib.kind; - } - if let Some(new_name) = &passed_lib.new_name { - lib.name = Some(Symbol::intern(new_name)); - } - lib.verbatim = passed_lib.verbatim; - return true; + if lib.name.as_str() == passed_lib.name { + // FIXME: This whole logic is questionable, whether modifiers are + // involved or not, library reordering and kind overriding without + // explicit `:rename` in particular. + if lib.has_modifiers() || passed_lib.has_modifiers() { + match lib.foreign_module { + Some(def_id) => self.tcx.sess.emit_err(errors::NoLinkModOverride { + span: Some(self.tcx.def_span(def_id)), + }), + None => { + self.tcx.sess.emit_err(errors::NoLinkModOverride { span: None }) + } + }; + } + if passed_lib.kind != NativeLibKind::Unspecified { + lib.kind = passed_lib.kind; + } + if let Some(new_name) = &passed_lib.new_name { + lib.name = Symbol::intern(new_name); } + lib.verbatim = passed_lib.verbatim; + return true; } false }) @@ -478,7 +473,7 @@ impl<'tcx> Collector<'tcx> { if existing.is_empty() { // Add if not found let new_name: Option<&str> = passed_lib.new_name.as_deref(); - let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))); + let name = Symbol::intern(new_name.unwrap_or(&passed_lib.name)); let sess = self.tcx.sess; let filename = find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, false, sess); @@ -488,7 +483,6 @@ impl<'tcx> Collector<'tcx> { kind: passed_lib.kind, cfg: None, foreign_module: None, - wasm_import_module: None, verbatim: passed_lib.verbatim, dll_imports: Vec::new(), }); diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 868ffdf0f1da0..a262c06d91f03 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -67,12 +67,11 @@ pub enum LinkagePreference { #[derive(Debug, Encodable, Decodable, HashStable_Generic)] pub struct NativeLib { pub kind: NativeLibKind, - pub name: Option, + pub name: Symbol, /// If packed_bundled_libs enabled, actual filename of library is stored. pub filename: Option, pub cfg: Option, pub foreign_module: Option, - pub wasm_import_module: Option, pub verbatim: Option, pub dll_imports: Vec, } @@ -81,6 +80,10 @@ impl NativeLib { pub fn has_modifiers(&self) -> bool { self.verbatim.is_some() || self.kind.has_modifiers() } + + pub fn wasm_import_module(&self) -> Option { + if self.kind == NativeLibKind::WasmImportModule { Some(self.name) } else { None } + } } /// Different ways that the PE Format can decorate a symbol name. diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index b996d36a318c5..3b3d4ca5d6b21 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -37,6 +37,10 @@ pub enum NativeLibKind { /// Argument which is passed to linker, relative order with libraries and other arguments /// is preserved LinkArg, + + /// Module imported from WebAssembly + WasmImportModule, + /// The library kind wasn't specified, `Dylib` is currently used as a default. Unspecified, } @@ -50,7 +54,10 @@ impl NativeLibKind { NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { as_needed.is_some() } - NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false, + NativeLibKind::RawDylib + | NativeLibKind::Unspecified + | NativeLibKind::LinkArg + | NativeLibKind::WasmImportModule => false, } } diff --git a/tests/ui/linkage-attr/issue-109144.rs b/tests/ui/linkage-attr/issue-109144.rs new file mode 100644 index 0000000000000..2f740e5538973 --- /dev/null +++ b/tests/ui/linkage-attr/issue-109144.rs @@ -0,0 +1,4 @@ +#![crate_type = "lib"] +#[link(kind = "static", modifiers = "+whole-archive,+bundle")] +//~^ ERROR `#[link]` attribute requires a `name = "string"` argument +extern {} diff --git a/tests/ui/linkage-attr/issue-109144.stderr b/tests/ui/linkage-attr/issue-109144.stderr new file mode 100644 index 0000000000000..33187cfdbb636 --- /dev/null +++ b/tests/ui/linkage-attr/issue-109144.stderr @@ -0,0 +1,9 @@ +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/issue-109144.rs:2:1 + | +LL | #[link(kind = "static", modifiers = "+whole-archive,+bundle")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0459`.