Auto merge of #138450 - matthiaskrgr:rollup-4im25vf, r=matthiaskrgr

Rollup of 6 pull requests

Successful merges:

 - #137816 (attempt to support `BinaryFormat::Xcoff` in `naked_asm!`)
 - #138109 (make precise capturing args in rustdoc Json typed)
 - #138343 (Enable `f16` tests for `powf`)
 - #138356 (bump libc to 0.2.171 to fix xous)
 - #138371 (Update compiletest's `has_asm_support` to match rustc)
 - #138404 (Cleanup sysroot locating a bit)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-03-13 13:34:28 +00:00
commit 93257e2d20
33 changed files with 268 additions and 127 deletions

View file

@ -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

View file

@ -1288,8 +1288,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

View file

@ -125,7 +125,8 @@ fn prefix_and_suffix<'tcx>(
// the alignment from a `#[repr(align(<n>))]` 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)

View file

@ -106,8 +106,8 @@ impl From<Vec<FluentError>> for TranslationBundleError {
/// (overriding any conflicting messages).
#[instrument(level = "trace")]
pub fn fluent_bundle(
mut user_provided_sysroot: Option<PathBuf>,
mut sysroot_candidates: Vec<PathBuf>,
sysroot: PathBuf,
sysroot_candidates: Vec<PathBuf>,
requested_locale: Option<LanguageIdentifier>,
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());

View file

@ -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<T, U> {
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 {

View file

@ -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<Symbol, Symbol>]> {
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,
})

View file

@ -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<R: Send>(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<R: Send>(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(),

View file

@ -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);

View file

@ -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<DefIndex, LazyValue<ty::adjustment::CoerceUnsizedInfo>>,
mir_const_qualif: Table<DefIndex, LazyValue<mir::ConstQualifs>>,
rendered_const: Table<DefIndex, LazyValue<String>>,
rendered_precise_capturing_args: Table<DefIndex, LazyArray<Symbol>>,
rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>,
asyncness: Table<DefIndex, ty::Asyncness>,
fn_arg_names: Table<DefIndex, LazyArray<Ident>>,
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,

View file

@ -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<Symbol, Symbol>]> {
desc { |tcx| "rendering precise capturing args for `{}`", tcx.def_path_str(def_id) }
separate_provide_extern
}

View file

@ -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::def_id::DefId>,
rustc_hir::PreciseCapturingArgKind<Symbol, Symbol>,
rustc_index::bit_set::DenseBitSet<u32>,
rustc_index::bit_set::FiniteBitSet<u32>,
rustc_session::cstore::ForeignModule,

View file

@ -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,

View file

@ -160,8 +160,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
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>) -> 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<PathBuf, String> {
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<PathBuf, String> {
// binary able to locate Rust libraries in systems using content-addressable
// storage (CAS).
fn from_env_args_next() -> Option<PathBuf> {
match env::args_os().next() {
Some(first_arg) => {
let mut p = PathBuf::from(first_arg);
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)
}
None => None,
// 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"))
}

View file

@ -333,7 +333,7 @@ top_level_options!(
output_types: OutputTypes [TRACKED],
search_paths: Vec<SearchPath> [UNTRACKED],
libs: Vec<NativeLib> [TRACKED],
maybe_sysroot: Option<PathBuf> [UNTRACKED],
sysroot: PathBuf [UNTRACKED],
target_triple: TargetTuple [TRACKED],

View file

@ -143,7 +143,6 @@ pub struct Session {
pub target: Target,
pub host: Target,
pub opts: config::Options,
pub host_tlib_path: Arc<SearchPath>,
pub target_tlib_path: Arc<SearchPath>,
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,

View file

@ -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",
]

View file

@ -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 }

View file

@ -461,18 +461,16 @@ fn test_recip() {
#[test]
#[cfg(reliable_f16_math)]
fn test_powi() {
// FIXME(llvm19): LLVM misoptimizes `powi.f16`
// <https://github.com/llvm/llvm-project/issues/98665>
// 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));

View file

@ -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)

View file

@ -1240,7 +1240,7 @@ pub(crate) enum GenericBound {
TraitBound(PolyTrait, hir::TraitBoundModifiers),
Outlives(Lifetime),
/// `use<'a, T>` precise-capturing bound syntax
Use(Vec<Symbol>),
Use(Vec<PreciseCapturingArg>),
}
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<GenericBound>, bound_params: Vec<GenericParamDef> },

View file

@ -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<PathBuf>,
/// 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,

View file

@ -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,

View file

@ -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,

View file

@ -283,7 +283,7 @@ impl clean::GenericBound {
} else {
f.write_str("use&lt;")?;
}
args.iter().joined(", ", f)?;
args.iter().map(|arg| arg.name()).joined(", ", f)?;
if f.alternate() { f.write_str(">") } else { f.write_str("&gt;") }
}
})

View file

@ -486,7 +486,18 @@ impl FromClean<clean::GenericBound> 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(),
),
}
}
}

View file

@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // 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<String>),
Use(Vec<PreciseCapturingArg>),
}
/// 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)]

View file

@ -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",
];

View file

@ -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")
}

View file

@ -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> {}

View file

@ -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());