diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 87af7959a884d..65784af92c7ca 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } if let Some(asm_arch) = asm_arch { // Inline assembly is currently only stable for these architectures. + // (See also compiletest's `has_asm_support`.) let is_stable = matches!( asm_arch, asm::InlineAsmArch::X86 diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 946f2cafa15f2..efc1fa05c5f92 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -190,14 +190,19 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FnSig<'hir> { let header = if let Some(local_sig_id) = sig_id.as_local() { match self.resolver.delegation_fn_sigs.get(&local_sig_id) { - Some(sig) => self.lower_fn_header( - sig.header, + Some(sig) => { + let parent = self.tcx.parent(sig_id); // HACK: we override the default safety instead of generating attributes from the ether. // We are not forwarding the attributes, as the delegation fn sigs are collected on the ast, // and here we need the hir attributes. - if sig.target_feature { hir::Safety::Unsafe } else { hir::Safety::Safe }, - &[], - ), + let default_safety = + if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod { + hir::Safety::Unsafe + } else { + hir::Safety::Safe + }; + self.lower_fn_header(sig.header, default_safety, &[]) + } None => self.generate_header_error(), } } else { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7d9971c021db3..62ed880478b5e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1286,8 +1286,7 @@ fn link_sanitizer_runtime( if path.exists() { sess.target_tlib_path.dir.clone() } else { - let default_sysroot = - filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); + let default_sysroot = filesearch::get_or_default_sysroot(); let default_tlib = filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.tuple()); default_tlib diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 96d1ab018f60d..26468b6a047ae 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -125,7 +125,8 @@ fn prefix_and_suffix<'tcx>( // the alignment from a `#[repr(align())]` is used if it specifies a higher alignment. // if no alignment is specified, an alignment of 4 bytes is used. let min_function_alignment = tcx.sess.opts.unstable_opts.min_function_alignment; - let align = Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4); + let align_bytes = + Ord::max(min_function_alignment, attrs.alignment).map(|a| a.bytes()).unwrap_or(4); // In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`. let (arch_prefix, arch_suffix) = if is_arm { @@ -157,12 +158,16 @@ fn prefix_and_suffix<'tcx>( } Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => { match asm_binary_format { - BinaryFormat::Elf - | BinaryFormat::Coff - | BinaryFormat::Wasm - | BinaryFormat::Xcoff => { + BinaryFormat::Elf | BinaryFormat::Coff | BinaryFormat::Wasm => { writeln!(w, ".weak {asm_name}")?; } + BinaryFormat::Xcoff => { + // FIXME: there is currently no way of defining a weak symbol in inline assembly + // for AIX. See https://github.com/llvm/llvm-project/issues/130269 + emit_fatal( + "cannot create weak symbols from inline assembly for this target", + ) + } BinaryFormat::MachO => { writeln!(w, ".globl {asm_name}")?; writeln!(w, ".weak_definition {asm_name}")?; @@ -189,7 +194,7 @@ fn prefix_and_suffix<'tcx>( let mut begin = String::new(); let mut end = String::new(); match asm_binary_format { - BinaryFormat::Elf | BinaryFormat::Xcoff => { + BinaryFormat::Elf => { let section = link_section.unwrap_or(format!(".text.{asm_name}")); let progbits = match is_arm { @@ -203,7 +208,7 @@ fn prefix_and_suffix<'tcx>( }; writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); - writeln!(begin, ".balign {align}").unwrap(); + writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); if let Visibility::Hidden = item_data.visibility { writeln!(begin, ".hidden {asm_name}").unwrap(); @@ -224,7 +229,7 @@ fn prefix_and_suffix<'tcx>( BinaryFormat::MachO => { let section = link_section.unwrap_or("__TEXT,__text".to_string()); writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); - writeln!(begin, ".balign {align}").unwrap(); + writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); if let Visibility::Hidden = item_data.visibility { writeln!(begin, ".private_extern {asm_name}").unwrap(); @@ -240,7 +245,7 @@ fn prefix_and_suffix<'tcx>( BinaryFormat::Coff => { let section = link_section.unwrap_or(format!(".text.{asm_name}")); writeln!(begin, ".pushsection {},\"xr\"", section).unwrap(); - writeln!(begin, ".balign {align}").unwrap(); + writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); writeln!(begin, ".def {asm_name}").unwrap(); writeln!(begin, ".scl 2").unwrap(); @@ -279,6 +284,33 @@ fn prefix_and_suffix<'tcx>( // .size is ignored for function symbols, so we can skip it writeln!(end, "end_function").unwrap(); } + BinaryFormat::Xcoff => { + // the LLVM XCOFFAsmParser is extremely incomplete and does not implement many of the + // documented directives. + // + // - https://github.com/llvm/llvm-project/blob/1b25c0c4da968fe78921ce77736e5baef4db75e3/llvm/lib/MC/MCParser/XCOFFAsmParser.cpp + // - https://www.ibm.com/docs/en/ssw_aix_71/assembler/assembler_pdf.pdf + // + // Consequently, we try our best here but cannot do as good a job as for other binary + // formats. + + // FIXME: start a section. `.csect` is not currently implemented in LLVM + + // fun fact: according to the assembler documentation, .align takes an exponent, + // but LLVM only accepts powers of 2 (but does emit the exponent) + // so when we hand `.align 32` to LLVM, the assembly output will contain `.align 5` + writeln!(begin, ".align {}", align_bytes).unwrap(); + + write_linkage(&mut begin).unwrap(); + if let Visibility::Hidden = item_data.visibility { + // FIXME apparently `.globl {asm_name}, hidden` is valid + // but due to limitations with `.weak` (see above) we can't really use that in general yet + } + writeln!(begin, "{asm_name}:").unwrap(); + + writeln!(end).unwrap(); + // FIXME: end the section? + } } (begin, end) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 066546ecf7406..39e78ae88416e 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -106,8 +106,8 @@ impl From> for TranslationBundleError { /// (overriding any conflicting messages). #[instrument(level = "trace")] pub fn fluent_bundle( - mut user_provided_sysroot: Option, - mut sysroot_candidates: Vec, + sysroot: PathBuf, + sysroot_candidates: Vec, requested_locale: Option, additional_ftl_path: Option<&Path>, with_directionality_markers: bool, @@ -141,7 +141,7 @@ pub fn fluent_bundle( // If the user requests the default locale then don't try to load anything. if let Some(requested_locale) = requested_locale { let mut found_resources = false; - for sysroot in user_provided_sysroot.iter_mut().chain(sysroot_candidates.iter_mut()) { + for mut sysroot in Some(sysroot).into_iter().chain(sysroot_candidates.into_iter()) { sysroot.push("share"); sysroot.push("locale"); sysroot.push(requested_locale.to_string()); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d4dfb9f29736c..5cf231d566828 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3373,13 +3373,16 @@ pub struct OpaqueTy<'hir> { pub span: Span, } -#[derive(Debug, Clone, Copy, HashStable_Generic)] -pub enum PreciseCapturingArg<'hir> { - Lifetime(&'hir Lifetime), +#[derive(Debug, Clone, Copy, HashStable_Generic, Encodable, Decodable)] +pub enum PreciseCapturingArgKind { + Lifetime(T), /// Non-lifetime argument (type or const) - Param(PreciseCapturingNonLifetimeArg), + Param(U), } +pub type PreciseCapturingArg<'hir> = + PreciseCapturingArgKind<&'hir Lifetime, PreciseCapturingNonLifetimeArg>; + impl PreciseCapturingArg<'_> { pub fn hir_id(self) -> HirId { match self { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index cfb6cf8a28792..e0e435dd6f0e7 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -28,7 +28,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics}; -use rustc_hir::{self as hir, GenericParamKind, HirId, Node}; +use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; @@ -1791,7 +1791,7 @@ fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueT fn rendered_precise_capturing_args<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, -) -> Option<&'tcx [Symbol]> { +) -> Option<&'tcx [PreciseCapturingArgKind]> { if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) = tcx.opt_rpitit_info(def_id.to_def_id()) { @@ -1800,7 +1800,12 @@ fn rendered_precise_capturing_args<'tcx>( tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound { hir::GenericBound::Use(args, ..) => { - Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| arg.name()))) + Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg { + PreciseCapturingArgKind::Lifetime(_) => { + PreciseCapturingArgKind::Lifetime(arg.name()) + } + PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()), + }))) } _ => None, }) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index b35703d8e737b..3f87b1a547be5 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -18,7 +18,7 @@ use rustc_parse::parser::attr::AllowLeadingUnsafe; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; -use rustc_session::filesearch::{self, sysroot_candidates}; +use rustc_session::filesearch::sysroot_candidates; use rustc_session::parse::ParseSess; use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint}; use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs}; @@ -390,7 +390,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se crate::callbacks::setup_callbacks(); - let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone()); + let sysroot = config.opts.sysroot.clone(); let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot); let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let path_mapping = config.opts.file_path_mapping(); @@ -424,7 +424,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let bundle = match rustc_errors::fluent_bundle( - config.opts.maybe_sysroot.clone(), + config.opts.sysroot.clone(), sysroot_candidates().to_vec(), config.opts.unstable_opts.translate_lang.clone(), config.opts.unstable_opts.translate_additional_ftl.as_deref(), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index aabd235bcabed..b44be1710edf7 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -21,7 +21,7 @@ use rustc_session::config::{ use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, filesearch, getopts}; +use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts}; use rustc_span::edition::{DEFAULT_EDITION, Edition}; use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::{FileName, SourceFileHashAlgorithm, sym}; @@ -41,7 +41,7 @@ where let matches = optgroups().parse(args).unwrap(); let sessopts = build_session_options(&mut early_dcx, &matches); - let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone()); + let sysroot = sessopts.sysroot.clone(); let target = rustc_session::config::build_target_config(&early_dcx, &sessopts.target_triple, &sysroot); let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 7b34e605c5307..5536c93f84a43 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -10,6 +10,7 @@ use rustc_abi::{FieldIdx, ReprOptions, VariantIdx}; use rustc_ast::expand::StrippedCfgItem; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; +use rustc_hir::PreciseCapturingArgKind; use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; @@ -440,7 +441,7 @@ define_tables! { coerce_unsized_info: Table>, mir_const_qualif: Table>, rendered_const: Table>, - rendered_precise_capturing_args: Table>, + rendered_precise_capturing_args: Table>>, asyncness: Table, fn_arg_names: Table>, coroutine_kind: Table, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 781a898a6e997..94a5a3769a322 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -25,7 +25,7 @@ use rustc_hir::def_id::{ CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, }; use rustc_hir::lang_items::{LangItem, LanguageItems}; -use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate}; +use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, PreciseCapturingArgKind, TraitCandidate}; use rustc_index::IndexVec; use rustc_lint_defs::LintId; use rustc_macros::rustc_queries; @@ -1424,7 +1424,7 @@ rustc_queries! { } /// Gets the rendered precise capturing args for an opaque for use in rustdoc. - query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [Symbol]> { + query rendered_precise_capturing_args(def_id: DefId) -> Option<&'tcx [PreciseCapturingArgKind]> { desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 71fc38cb7edb4..19e2b57456327 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -3,6 +3,7 @@ use std::hash::Hash; use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::DefIndex; use rustc_index::{Idx, IndexVec}; +use rustc_span::Symbol; use crate::ty; @@ -96,6 +97,7 @@ trivially_parameterized_over_tcx! { rustc_hir::def_id::DefIndex, rustc_hir::definitions::DefKey, rustc_hir::OpaqueTyOrigin, + rustc_hir::PreciseCapturingArgKind, rustc_index::bit_set::DenseBitSet, rustc_index::bit_set::FiniteBitSet, rustc_session::cstore::ForeignModule, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index d78c874c76607..915889b7b1acd 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -753,6 +753,11 @@ impl UnsafeOpKind { span: Span, suggest_unsafe_block: bool, ) { + if tcx.hir().opt_delegation_sig_id(hir_id.owner.def_id).is_some() { + // The body of the delegation item is synthesized, so it makes no sense + // to emit this lint. + return; + } let parent_id = tcx.hir_get_parent_item(hir_id); let parent_owner = tcx.hir_owner_node(parent_id); let should_suggest = parent_owner.fn_sig().is_some_and(|sig| { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d28988cd74f10..f3f6c55158068 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5117,12 +5117,18 @@ struct ItemInfoCollector<'a, 'ra, 'tcx> { } impl ItemInfoCollector<'_, '_, '_> { - fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId, attrs: &[Attribute]) { + fn collect_fn_info( + &mut self, + header: FnHeader, + decl: &FnDecl, + id: NodeId, + attrs: &[Attribute], + ) { let sig = DelegationFnSig { - header: sig.header, - param_count: sig.decl.inputs.len(), - has_self: sig.decl.has_self(), - c_variadic: sig.decl.c_variadic(), + header, + param_count: decl.inputs.len(), + has_self: decl.has_self(), + c_variadic: decl.c_variadic(), target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)), }; self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig); @@ -5142,7 +5148,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Trait(box Trait { generics, .. }) | ItemKind::TraitAlias(generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } let def_id = self.r.local_def_id(item.id); @@ -5154,8 +5160,17 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { self.r.item_generics_num_lifetimes.insert(def_id, count); } + ItemKind::ForeignMod(ForeignMod { extern_span, safety: _, abi, items }) => { + for foreign_item in items { + if let ForeignItemKind::Fn(box Fn { sig, .. }) = &foreign_item.kind { + let new_header = + FnHeader { ext: Extern::from_abi(*abi, *extern_span), ..sig.header }; + self.collect_fn_info(new_header, &sig.decl, foreign_item.id, &item.attrs); + } + } + } + ItemKind::Mod(..) - | ItemKind::ForeignMod(..) | ItemKind::Static(..) | ItemKind::Use(..) | ItemKind::ExternCrate(..) @@ -5175,7 +5190,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind { - self.collect_fn_info(sig, item.id, &item.attrs); + self.collect_fn_info(sig.header, &sig.decl, item.id, &item.attrs); } visit::walk_assoc_item(self, item, ctxt); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 7af221c960757..dcdb7fa9c1054 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1214,7 +1214,7 @@ impl Default for Options { describe_lints: false, output_types: OutputTypes(BTreeMap::new()), search_paths: vec![], - maybe_sysroot: None, + sysroot: filesearch::materialize_sysroot(None), target_triple: TargetTuple::from_tuple(host_tuple()), test: false, incremental: None, @@ -2618,7 +2618,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M describe_lints, output_types, search_paths, - maybe_sysroot: Some(sysroot), + sysroot, target_triple, test, incremental, diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index cc2decc2fe4b3..50f09c57107e6 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -160,8 +160,7 @@ fn current_dll_path() -> Result { pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { let target = crate::config::host_tuple(); - let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = - smallvec![get_or_default_sysroot().expect("Failed finding sysroot")]; + let mut sysroot_candidates: SmallVec<[PathBuf; 2]> = smallvec![get_or_default_sysroot()]; let path = current_dll_path().and_then(|s| try_canonicalize(s).map_err(|e| e.to_string())); if let Ok(dll) = path { // use `parent` twice to chop off the file name and then also the @@ -195,12 +194,12 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { /// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none. /// Panics if [`get_or_default_sysroot`] returns an error. pub fn materialize_sysroot(maybe_sysroot: Option) -> PathBuf { - maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot().expect("Failed finding sysroot")) + maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot()) } /// This function checks if sysroot is found using env::args().next(), and if it /// is not found, finds sysroot from current rustc_driver dll. -pub fn get_or_default_sysroot() -> Result { +pub fn get_or_default_sysroot() -> PathBuf { // Follow symlinks. If the resolved path is relative, make it absolute. fn canonicalize(path: PathBuf) -> PathBuf { let path = try_canonicalize(&path).unwrap_or(path); @@ -255,30 +254,25 @@ pub fn get_or_default_sysroot() -> Result { // binary able to locate Rust libraries in systems using content-addressable // storage (CAS). fn from_env_args_next() -> Option { - match env::args_os().next() { - Some(first_arg) => { - let mut p = PathBuf::from(first_arg); - - // Check if sysroot is found using env::args().next() only if the rustc in argv[0] - // is a symlink (see #79253). We might want to change/remove it to conform with - // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the - // future. - if fs::read_link(&p).is_err() { - // Path is not a symbolic link or does not exist. - return None; - } - - // Pop off `bin/rustc`, obtaining the suspected sysroot. - p.pop(); - p.pop(); - // Look for the target rustlib directory in the suspected sysroot. - let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy"); - rustlib_path.pop(); // pop off the dummy target. - rustlib_path.exists().then_some(p) - } - None => None, + let mut p = PathBuf::from(env::args_os().next()?); + + // Check if sysroot is found using env::args().next() only if the rustc in argv[0] + // is a symlink (see #79253). We might want to change/remove it to conform with + // https://www.gnu.org/prep/standards/standards.html#Finding-Program-Files in the + // future. + if fs::read_link(&p).is_err() { + // Path is not a symbolic link or does not exist. + return None; } + + // Pop off `bin/rustc`, obtaining the suspected sysroot. + p.pop(); + p.pop(); + // Look for the target rustlib directory in the suspected sysroot. + let mut rustlib_path = rustc_target::relative_target_rustlib_path(&p, "dummy"); + rustlib_path.pop(); // pop off the dummy target. + rustlib_path.exists().then_some(p) } - Ok(from_env_args_next().unwrap_or(default_from_rustc_driver_dll()?)) + from_env_args_next().unwrap_or(default_from_rustc_driver_dll().expect("Failed finding sysroot")) } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 8977365ee73d9..804b46a9bec41 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -333,7 +333,7 @@ top_level_options!( output_types: OutputTypes [TRACKED], search_paths: Vec [UNTRACKED], libs: Vec [TRACKED], - maybe_sysroot: Option [UNTRACKED], + sysroot: PathBuf [UNTRACKED], target_triple: TargetTuple [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index bcd9a73d9d30a..1c9adea281dc7 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -143,7 +143,6 @@ pub struct Session { pub target: Target, pub host: Target, pub opts: config::Options, - pub host_tlib_path: Arc, pub target_tlib_path: Arc, pub psess: ParseSess, pub sysroot: PathBuf, @@ -1042,6 +1041,7 @@ pub fn build_session( let host_triple = config::host_tuple(); let target_triple = sopts.target_triple.tuple(); + // FIXME use host sysroot? let host_tlib_path = Arc::new(SearchPath::from_sysroot_and_triple(&sysroot, host_triple)); let target_tlib_path = if host_triple == target_triple { // Use the same `SearchPath` if host and target triple are identical to avoid unnecessary @@ -1070,7 +1070,6 @@ pub fn build_session( target, host, opts: sopts, - host_tlib_path, target_tlib_path, psess, sysroot, diff --git a/library/Cargo.lock b/library/Cargo.lock index 8f174f284724f..104e0a3d01079 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -157,9 +157,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.170" +version = "0.2.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index f7379c413f15e..b4d4a61768b5b 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ miniz_oxide = { version = "0.8.0", optional = true, default-features = false } addr2line = { version = "0.24.0", optional = true, default-features = false } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] -libc = { version = "0.2.170", default-features = false, features = [ +libc = { version = "0.2.171", default-features = false, features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs index 5180f3d40f3a7..19389a9178e91 100644 --- a/library/std/tests/floats/f16.rs +++ b/library/std/tests/floats/f16.rs @@ -461,18 +461,16 @@ fn test_recip() { #[test] #[cfg(reliable_f16_math)] fn test_powi() { - // FIXME(llvm19): LLVM misoptimizes `powi.f16` - // - // let nan: f16 = f16::NAN; - // let inf: f16 = f16::INFINITY; - // let neg_inf: f16 = f16::NEG_INFINITY; - // assert_eq!(1.0f16.powi(1), 1.0); - // assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0); - // assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2); - // assert_eq!(8.3f16.powi(0), 1.0); - // assert!(nan.powi(2).is_nan()); - // assert_eq!(inf.powi(3), inf); - // assert_eq!(neg_inf.powi(2), inf); + let nan: f16 = f16::NAN; + let inf: f16 = f16::INFINITY; + let neg_inf: f16 = f16::NEG_INFINITY; + assert_eq!(1.0f16.powi(1), 1.0); + assert_approx_eq!((-3.1f16).powi(2), 9.61, TOL_0); + assert_approx_eq!(5.9f16.powi(-2), 0.028727, TOL_N2); + assert_eq!(8.3f16.powi(0), 1.0); + assert!(nan.powi(2).is_nan()); + assert_eq!(inf.powi(3), inf); + assert_eq!(neg_inf.powi(2), inf); } #[test] @@ -813,6 +811,7 @@ fn test_clamp_max_is_nan() { } #[test] +#[cfg(reliable_f16_math)] fn test_total_cmp() { use core::cmp::Ordering; @@ -820,14 +819,13 @@ fn test_total_cmp() { 1 << (f16::MANTISSA_DIGITS - 2) } - // FIXME(f16_f128): test subnormals when powf is available - // fn min_subnorm() -> f16 { - // f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0) - // } + fn min_subnorm() -> f16 { + f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0) + } - // fn max_subnorm() -> f16 { - // f16::MIN_POSITIVE - min_subnorm() - // } + fn max_subnorm() -> f16 { + f16::MIN_POSITIVE - min_subnorm() + } fn q_nan() -> f16 { f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask()) @@ -846,12 +844,12 @@ fn test_total_cmp() { assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5)); assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5)); assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE)); - // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm())); - // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm())); + assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm())); assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0)); assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0)); - // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm())); - // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm())); + assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm())); + assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm())); assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE)); assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5)); assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0)); @@ -870,13 +868,13 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0)); assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5)); assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE)); - // assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm())); - // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm())); - // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0)); + assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm())); + assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0)); assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0)); - // assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm())); - // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm())); - // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE)); + assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm())); + assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE)); assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5)); assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0)); assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5)); @@ -894,13 +892,13 @@ fn test_total_cmp() { assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5)); assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0)); assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5)); - // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE)); - // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm())); - // assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE)); + assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm())); + assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm())); assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0)); - // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0)); - // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm())); - // assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm())); + assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0)); + assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm())); + assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm())); assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE)); assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5)); assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0)); @@ -918,12 +916,12 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0)); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5)); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE)); - // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm())); - // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm())); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0)); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0)); - // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm())); - // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm())); + assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm())); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE)); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5)); assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0)); @@ -940,12 +938,12 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE)); - // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm())); - // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm())); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0)); - // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm())); - // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm())); + assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm())); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0)); diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile index e0ed2e227f810..be235f648b527 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile @@ -3,6 +3,7 @@ FROM ubuntu:24.10 ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y --no-install-recommends \ + bzip2 \ g++ \ gcc-multilib \ make \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile new file mode 100644 index 0000000000000..408b87125e0c6 --- /dev/null +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-20/Dockerfile @@ -0,0 +1,69 @@ +FROM ubuntu:25.04 + +ARG DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + bzip2 \ + g++ \ + gcc-multilib \ + make \ + ninja-build \ + file \ + curl \ + ca-certificates \ + python3 \ + git \ + cmake \ + sudo \ + gdb \ + llvm-20-tools \ + llvm-20-dev \ + libedit-dev \ + libssl-dev \ + pkg-config \ + zlib1g-dev \ + xz-utils \ + nodejs \ + mingw-w64 \ + # libgccjit dependencies + flex \ + libmpfr-dev \ + libgmp-dev \ + libmpc3 \ + libmpc-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install powershell (universal package) so we can test x.ps1 on Linux +# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. +RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ + dpkg --ignore-depends=libicu72 -i powershell.deb && \ + rm -f powershell.deb + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# We are disabling CI LLVM since this builder is intentionally using a host +# LLVM, rather than the typical src/llvm-project LLVM. +ENV NO_DOWNLOAD_CI_LLVM 1 +ENV EXTERNAL_LLVM 1 + +# Using llvm-link-shared due to libffi issues -- see #34486 +ENV RUST_CONFIGURE_ARGS \ + --build=x86_64-unknown-linux-gnu \ + --llvm-root=/usr/lib/llvm-20 \ + --enable-llvm-link-shared \ + --set rust.randomize-layout=true \ + --set rust.thin-lto-import-instr-limit=10 + +COPY scripts/shared.sh /scripts/ + +ARG SCRIPT_ARG + +COPY scripts/add_dummy_commit.sh /tmp/ +COPY scripts/x86_64-gnu-llvm.sh /tmp/ +COPY scripts/x86_64-gnu-llvm2.sh /tmp/ +COPY scripts/x86_64-gnu-llvm3.sh /tmp/ +COPY scripts/stage_2_test_set1.sh /tmp/ +COPY scripts/stage_2_test_set2.sh /tmp/ + +ENV SCRIPT "/tmp/add_dummy_commit.sh && /tmp/${SCRIPT_ARG}" diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index eba55338ff826..ac1cca4bf5ee7 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -301,6 +301,31 @@ auto: - name: x86_64-gnu-distcheck <<: *job-linux-8c + # The x86_64-gnu-llvm-20 job is split into multiple jobs to run tests in parallel. + # x86_64-gnu-llvm-20-1 skips tests that run in x86_64-gnu-llvm-20-{2,3}. + - name: x86_64-gnu-llvm-20-1 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: stage_2_test_set1.sh + <<: *job-linux-4c + + # Skip tests that run in x86_64-gnu-llvm-20-{1,3} + - name: x86_64-gnu-llvm-20-2 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: x86_64-gnu-llvm2.sh + <<: *job-linux-4c + + # Skip tests that run in x86_64-gnu-llvm-20-{1,2} + - name: x86_64-gnu-llvm-20-3 + env: + RUST_BACKTRACE: 1 + IMAGE: x86_64-gnu-llvm-20 + DOCKER_SCRIPT: x86_64-gnu-llvm3.sh + <<: *job-linux-4c + # The x86_64-gnu-llvm-19 job is split into multiple jobs to run tests in parallel. # x86_64-gnu-llvm-19-1 skips tests that run in x86_64-gnu-llvm-19-{2,3}. - name: x86_64-gnu-llvm-19-1 diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b213be5747beb..0f476c8c9ffd2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -231,7 +231,7 @@ fn clean_generic_bound<'tcx>( GenericBound::TraitBound(clean_poly_trait_ref(t, cx), t.modifiers) } hir::GenericBound::Use(args, ..) => { - GenericBound::Use(args.iter().map(|arg| arg.name()).collect()) + GenericBound::Use(args.iter().map(|arg| clean_precise_capturing_arg(arg, cx)).collect()) } }) } @@ -286,6 +286,18 @@ fn clean_lifetime(lifetime: &hir::Lifetime, cx: &DocContext<'_>) -> Lifetime { Lifetime(lifetime.ident.name) } +pub(crate) fn clean_precise_capturing_arg( + arg: &hir::PreciseCapturingArg<'_>, + cx: &DocContext<'_>, +) -> PreciseCapturingArg { + match arg { + hir::PreciseCapturingArg::Lifetime(lt) => { + PreciseCapturingArg::Lifetime(clean_lifetime(lt, cx)) + } + hir::PreciseCapturingArg::Param(param) => PreciseCapturingArg::Param(param.ident.name), + } +} + pub(crate) fn clean_const<'tcx>( constant: &hir::ConstArg<'tcx>, _cx: &mut DocContext<'tcx>, @@ -2364,7 +2376,18 @@ fn clean_middle_opaque_bounds<'tcx>( } if let Some(args) = cx.tcx.rendered_precise_capturing_args(impl_trait_def_id) { - bounds.push(GenericBound::Use(args.to_vec())); + bounds.push(GenericBound::Use( + args.iter() + .map(|arg| match arg { + hir::PreciseCapturingArgKind::Lifetime(lt) => { + PreciseCapturingArg::Lifetime(Lifetime(*lt)) + } + hir::PreciseCapturingArgKind::Param(param) => { + PreciseCapturingArg::Param(*param) + } + }) + .collect(), + )); } ImplTrait(bounds) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 9e9cd52883491..228d9108e4eb6 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1240,7 +1240,7 @@ pub(crate) enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifiers), Outlives(Lifetime), /// `use<'a, T>` precise-capturing bound syntax - Use(Vec), + Use(Vec), } impl GenericBound { @@ -1304,6 +1304,21 @@ impl Lifetime { } } +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub(crate) enum PreciseCapturingArg { + Lifetime(Lifetime), + Param(Symbol), +} + +impl PreciseCapturingArg { + pub(crate) fn name(self) -> Symbol { + match self { + PreciseCapturingArg::Lifetime(lt) => lt.0, + PreciseCapturingArg::Param(param) => param, + } + } +} + #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) enum WherePredicate { BoundPredicate { ty: Type, bounds: Vec, bound_params: Vec }, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 9cf471733f94a..23a2bcd9011ee 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -103,6 +103,8 @@ pub(crate) struct Options { /// compiling doctests from the crate. pub(crate) edition: Edition, /// The path to the sysroot. Used during the compilation process. + pub(crate) sysroot: PathBuf, + /// Has the same value as `sysroot` except is `None` when the user didn't pass `---sysroot`. pub(crate) maybe_sysroot: Option, /// Lint information passed over the command-line. pub(crate) lint_opts: Vec<(String, Level)>, @@ -202,6 +204,7 @@ impl fmt::Debug for Options { .field("unstable_options", &"...") .field("target", &self.target) .field("edition", &self.edition) + .field("sysroot", &self.sysroot) .field("maybe_sysroot", &self.maybe_sysroot) .field("lint_opts", &self.lint_opts) .field("describe_lints", &self.describe_lints) @@ -729,12 +732,7 @@ impl Options { let target = parse_target_triple(early_dcx, matches); let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from); - let sysroot = match &maybe_sysroot { - Some(s) => s.clone(), - None => { - rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot") - } - }; + let sysroot = rustc_session::filesearch::materialize_sysroot(maybe_sysroot.clone()); let libs = matches .opt_strs("L") @@ -834,6 +832,7 @@ impl Options { unstable_opts_strs, target, edition, + sysroot, maybe_sysroot, lint_opts, describe_lints, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 719f1f978feca..c47e42670c909 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -210,7 +210,7 @@ pub(crate) fn create_config( unstable_opts, target, edition, - maybe_sysroot, + sysroot, lint_opts, describe_lints, lint_cap, @@ -253,7 +253,7 @@ pub(crate) fn create_config( let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false); // plays with error output here! let sessopts = config::Options { - maybe_sysroot, + sysroot, search_paths: libs, crate_types, lint_opts, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f7f0c9766e2f6..a2808bddb3acc 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -158,7 +158,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions if options.proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] }; let sessopts = config::Options { - maybe_sysroot: options.maybe_sysroot.clone(), + sysroot: options.sysroot.clone(), search_paths: options.libs.clone(), crate_types, lint_opts, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 8b8439a253527..e93b9eb272a47 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -283,7 +283,7 @@ impl clean::GenericBound { } else { f.write_str("use<")?; } - args.iter().joined(", ", f)?; + args.iter().map(|arg| arg.name()).joined(", ", f)?; if f.alternate() { f.write_str(">") } else { f.write_str(">") } } }) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 9606ba76991a7..d65c13b2b6313 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -548,7 +548,18 @@ impl FromClean for GenericBound { } } Outlives(lifetime) => GenericBound::Outlives(convert_lifetime(lifetime)), - Use(args) => GenericBound::Use(args.into_iter().map(|arg| arg.to_string()).collect()), + Use(args) => GenericBound::Use( + args.iter() + .map(|arg| match arg { + clean::PreciseCapturingArg::Lifetime(lt) => { + PreciseCapturingArg::Lifetime(convert_lifetime(*lt)) + } + clean::PreciseCapturingArg::Param(param) => { + PreciseCapturingArg::Param(param.to_string()) + } + }) + .collect(), + ), } } } diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 8f6496e9626c8..8ec7cffe06620 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap = HashMap; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 40; +pub const FORMAT_VERSION: u32 = 41; /// The root of the emitted JSON blob. /// @@ -909,7 +909,7 @@ pub enum GenericBound { /// ``` Outlives(String), /// `use<'a, T>` precise-capturing bound syntax - Use(Vec), + Use(Vec), } /// A set of modifiers applied to a trait. @@ -927,6 +927,22 @@ pub enum TraitBoundModifier { MaybeConst, } +/// One precise capturing argument. See [the rust reference](https://doc.rust-lang.org/reference/types/impl-trait.html#precise-capturing). +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum PreciseCapturingArg { + /// A lifetime. + /// ```rust + /// pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} + /// // ^^ + Lifetime(String), + /// A type or constant parameter. + /// ```rust + /// pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} + /// // ^ ^ + Param(String), +} + /// Either a type or a constant, usually stored as the right-hand side of an equation in places like /// [`AssocItemConstraint`] #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 978836cb6636a..08d3c1c343e08 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -481,9 +481,17 @@ impl Config { } pub fn has_asm_support(&self) -> bool { + // This should match the stable list in `LoweringContext::lower_inline_asm`. static ASM_SUPPORTED_ARCHS: &[&str] = &[ - "x86", "x86_64", "arm", "aarch64", "riscv32", + "x86", + "x86_64", + "arm", + "aarch64", + "arm64ec", + "riscv32", "riscv64", + "loongarch64", + "s390x", // These targets require an additional asm_experimental_arch feature. // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32", ]; diff --git a/tests/assembly/aarch64-naked-fn-no-bti-prolog.rs b/tests/assembly/naked-functions/aarch64-naked-fn-no-bti-prolog.rs similarity index 100% rename from tests/assembly/aarch64-naked-fn-no-bti-prolog.rs rename to tests/assembly/naked-functions/aarch64-naked-fn-no-bti-prolog.rs diff --git a/tests/assembly/naked-functions/aix.rs b/tests/assembly/naked-functions/aix.rs new file mode 100644 index 0000000000000..cc0825b37387c --- /dev/null +++ b/tests/assembly/naked-functions/aix.rs @@ -0,0 +1,35 @@ +//@ revisions: elfv1-be aix +//@ add-core-stubs +//@ assembly-output: emit-asm +// +//@[elfv1-be] compile-flags: --target powerpc64-unknown-linux-gnu +//@[elfv1-be] needs-llvm-components: powerpc +// +//@[aix] compile-flags: --target powerpc64-ibm-aix +//@[aix] needs-llvm-components: powerpc + +#![crate_type = "lib"] +#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)] +#![no_core] + +// tests that naked functions work for the `powerpc64-ibm-aix` target. +// +// This target is special because it uses the XCOFF binary format +// It is tested alongside an elf powerpc target to pin down commonalities and differences. +// +// https://doc.rust-lang.org/rustc/platform-support/aix.html +// https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format + +extern crate minicore; +use minicore::*; + +// elfv1-be: .p2align 2 +// aix: .align 2 +// CHECK: .globl blr +// CHECK-LABEL: blr: +// CHECK: blr +#[no_mangle] +#[naked] +unsafe extern "C" fn blr() { + naked_asm!("blr") +} diff --git a/tests/assembly/wasm32-naked-fn.rs b/tests/assembly/naked-functions/wasm32.rs similarity index 100% rename from tests/assembly/wasm32-naked-fn.rs rename to tests/assembly/naked-functions/wasm32.rs diff --git a/tests/assembly/x86_64-naked-fn-no-cet-prolog.rs b/tests/assembly/naked-functions/x86_64-naked-fn-no-cet-prolog.rs similarity index 100% rename from tests/assembly/x86_64-naked-fn-no-cet-prolog.rs rename to tests/assembly/naked-functions/x86_64-naked-fn-no-cet-prolog.rs diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs index 52252560e6fda..06be95099b4d5 100644 --- a/tests/rustdoc-json/impl-trait-precise-capturing.rs +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0]" \"\'a\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1]" \"T\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2]" \"N\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0].lifetime" \"\'a\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1].param" \"T\" +//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2].param" \"N\" pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index f414c961627dd..ffc19b138a573 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -46,7 +46,7 @@ fn main() { fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) { let mut opts = Options::default(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); - opts.maybe_sysroot = Some(sysroot); + opts.sysroot = sysroot; if let Some(linker) = linker { opts.cg.linker = Some(linker.to_owned()); diff --git a/tests/ui/delegation/foreign-fn.rs b/tests/ui/delegation/foreign-fn.rs new file mode 100644 index 0000000000000..1d221da29ceb2 --- /dev/null +++ b/tests/ui/delegation/foreign-fn.rs @@ -0,0 +1,22 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] +#![deny(unsafe_op_in_unsafe_fn)] +#![deny(unused_unsafe)] + +mod to_reuse { + unsafe extern "C" { + pub fn default_unsafe_foo(); + pub unsafe fn unsafe_foo(); + pub safe fn safe_foo(); + } +} + +reuse to_reuse::{default_unsafe_foo, unsafe_foo, safe_foo}; + +fn main() { + let _: extern "C" fn() = default_unsafe_foo; + //~^ ERROR mismatched types + let _: extern "C" fn() = unsafe_foo; + //~^ ERROR mismatched types + let _: extern "C" fn() = safe_foo; +} diff --git a/tests/ui/delegation/foreign-fn.stderr b/tests/ui/delegation/foreign-fn.stderr new file mode 100644 index 0000000000000..f7d3dba4bb1c0 --- /dev/null +++ b/tests/ui/delegation/foreign-fn.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/foreign-fn.rs:17:30 + | +LL | let _: extern "C" fn() = default_unsafe_foo; + | --------------- ^^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn + | | + | expected due to this + | + = note: expected fn pointer `extern "C" fn()` + found fn item `unsafe extern "C" fn() {default_unsafe_foo}` + = note: unsafe functions cannot be coerced into safe function pointers + +error[E0308]: mismatched types + --> $DIR/foreign-fn.rs:19:30 + | +LL | let _: extern "C" fn() = unsafe_foo; + | --------------- ^^^^^^^^^^ expected safe fn, found unsafe fn + | | + | expected due to this + | + = note: expected fn pointer `extern "C" fn()` + found fn item `unsafe extern "C" fn() {unsafe_foo}` + = note: unsafe functions cannot be coerced into safe function pointers + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.