Skip to content

Rollup of 7 pull requests #137903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b6f2240
rustdoc: disable forbidden #[target_feature] check
RalfJung Feb 25, 2025
039af88
also fix potential issues with mixed stable/unstable target features …
RalfJung Feb 25, 2025
745297e
Use helper function instead of reimplementing the logic to check if r…
GuillaumeGomez Feb 26, 2025
98eb2e3
Add rustdoc support for `--emit=dep-info[=path]`
GuillaumeGomez Feb 26, 2025
46a39f0
Add new `Rustdoc::emit` method in `run-make-support`
GuillaumeGomez Feb 26, 2025
b97310c
Add run-make test for rustdoc `--emit=dep-info` option
GuillaumeGomez Feb 26, 2025
1bf15c2
compiletest: change `TEST_BUILD_DIR` to maximally normalize
jieyouxu Feb 11, 2025
a9b1ff9
tests: remove explicit long type filename hash normalization from som…
jieyouxu Feb 11, 2025
d3222cc
tests: rebless some tests as a side-effect of `TEST_BUILD_DIR` changes
jieyouxu Feb 11, 2025
39c7107
tests: manually rebless `tests/ui-fulldeps/codegen-backend/hotplug.rs`
jieyouxu Feb 11, 2025
e66bf08
sort list
tshepang Feb 28, 2025
f8091c4
qnx: avoid test failure
tshepang Feb 28, 2025
7fdd193
tests: Unignore target modifier tests on all platforms
petrochenkov Feb 28, 2025
dc04c0c
add test
RalfJung Feb 28, 2025
107d7ef
test(codegen): add looping_over_ne_bytes test for #133528
karolzwolak Feb 28, 2025
11e7aaf
jsondocck: minor cleanups
yotamofek Feb 15, 2025
94645f6
jsondocck: catch and error on deprecated syntax
yotamofek Feb 15, 2025
797ef64
htmldocck: catch and error on deprecated syntax
yotamofek Feb 15, 2025
4c939db
also skip abi_required_features check in rustdoc
RalfJung Feb 28, 2025
dd620a5
Rollup merge of #136865 - jieyouxu:long-type-path-compare-mode, r=lqd
matthiaskrgr Mar 2, 2025
7b9ce1d
Rollup merge of #137103 - yotamofek:pr/jsonhtmldocck-deprecated-synta…
matthiaskrgr Mar 2, 2025
79422e0
Rollup merge of #137632 - RalfJung:rustdoc-target-features, r=working…
matthiaskrgr Mar 2, 2025
bd5b672
Rollup merge of #137684 - GuillaumeGomez:rustdoc-dep-info, r=notriddle
matthiaskrgr Mar 2, 2025
fc8d302
Rollup merge of #137794 - tshepang:make-qnx-pass, r=pietroalbini
matthiaskrgr Mar 2, 2025
b543e74
Rollup merge of #137801 - petrochenkov:tarmod, r=compiler-errors
matthiaskrgr Mar 2, 2025
eac4731
Rollup merge of #137826 - karolzwolak:looping_over_ne_bytes_133528, r…
matthiaskrgr Mar 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions compiler/rustc_codegen_ssa/src/target_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
use rustc_target::target_features;
use rustc_target::target_features::{self, Stability};

use crate::errors;

Expand Down Expand Up @@ -87,12 +87,17 @@ pub(crate) fn from_target_feature_attr(
// But ensure the ABI does not forbid enabling this.
// Here we do assume that LLVM doesn't add even more implied features
// we don't know about, at least no features that would have ABI effects!
if abi_feature_constraints.incompatible.contains(&name.as_str()) {
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
span: item.span(),
feature: name.as_str(),
reason: "this feature is incompatible with the target ABI",
});
// We skip this logic in rustdoc, where we want to allow all target features of
// all targets, so we can't check their ABI compatibility and anyway we are not
// generating code so "it's fine".
if !tcx.sess.opts.actually_rustdoc {
if abi_feature_constraints.incompatible.contains(&name.as_str()) {
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
span: item.span(),
feature: name.as_str(),
reason: "this feature is incompatible with the target ABI",
});
}
}
target_features.push(TargetFeature { name, implied: name != feature_sym })
}
Expand Down Expand Up @@ -142,11 +147,38 @@ pub(crate) fn provide(providers: &mut Providers) {
rust_target_features: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
if tcx.sess.opts.actually_rustdoc {
// rustdoc needs to be able to document functions that use all the features, so
// whitelist them all
rustc_target::target_features::all_rust_features()
.map(|(a, b)| (a.to_string(), b))
.collect()
// HACK: rustdoc would like to pretend that we have all the target features, so we
// have to merge all the lists into one. To ensure an unstable target never prevents
// a stable one from working, we merge the stability info of all instances of the
// same target feature name, with the "most stable" taking precedence. And then we
// hope that this doesn't cause issues anywhere else in the compiler...
let mut result: UnordMap<String, Stability> = Default::default();
for (name, stability) in rustc_target::target_features::all_rust_features() {
use std::collections::hash_map::Entry;
match result.entry(name.to_owned()) {
Entry::Vacant(vacant_entry) => {
vacant_entry.insert(stability);
}
Entry::Occupied(mut occupied_entry) => {
// Merge the two stabilities, "more stable" taking precedence.
match (occupied_entry.get(), stability) {
(Stability::Stable, _)
| (
Stability::Unstable { .. },
Stability::Unstable { .. } | Stability::Forbidden { .. },
)
| (Stability::Forbidden { .. }, Stability::Forbidden { .. }) => {
// The stability in the entry is at least as good as the new one, just keep it.
}
_ => {
// Overwrite stabilite.
occupied_entry.insert(stability);
}
}
}
}
}
result
} else {
tcx.sess
.target
Expand Down
14 changes: 14 additions & 0 deletions src/etc/htmldocck.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,24 @@ def filter_line(line):
re.X | re.UNICODE,
)

DEPRECATED_LINE_PATTERN = re.compile(
r"""
//\s+@
""",
re.X | re.UNICODE,
)


def get_commands(template):
with io.open(template, encoding="utf-8") as f:
for lineno, line in concat_multi_lines(f):
if DEPRECATED_LINE_PATTERN.search(line):
print_err(
lineno,
line,
"Deprecated command syntax, replace `// @` with `//@ `",
)
continue
m = LINE_PATTERN.search(line)
if not m:
continue
Expand Down
28 changes: 22 additions & 6 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,23 +315,30 @@ pub(crate) enum ModuleSorting {
Alphabetical,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum EmitType {
Unversioned,
Toolchain,
InvocationSpecific,
DepInfo(Option<PathBuf>),
}

impl FromStr for EmitType {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
use EmitType::*;
match s {
"unversioned-shared-resources" => Ok(Unversioned),
"toolchain-shared-resources" => Ok(Toolchain),
"invocation-specific" => Ok(InvocationSpecific),
_ => Err(()),
"unversioned-shared-resources" => Ok(Self::Unversioned),
"toolchain-shared-resources" => Ok(Self::Toolchain),
"invocation-specific" => Ok(Self::InvocationSpecific),
"dep-info" => Ok(Self::DepInfo(None)),
option => {
if let Some(file) = option.strip_prefix("dep-info=") {
Ok(Self::DepInfo(Some(Path::new(file).into())))
} else {
Err(())
}
}
}
}
}
Expand All @@ -340,6 +347,15 @@ impl RenderOptions {
pub(crate) fn should_emit_crate(&self) -> bool {
self.emit.is_empty() || self.emit.contains(&EmitType::InvocationSpecific)
}

pub(crate) fn dep_info(&self) -> Option<Option<&Path>> {
for emit in &self.emit {
if let EmitType::DepInfo(file) = emit {
return Some(file.as_deref());
}
}
None
}
}

/// Create the input (string or file path)
Expand Down
24 changes: 18 additions & 6 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path};
use rustc_interface::interface;
use rustc_lint::{MissingDoc, late_lint_mod};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
use rustc_session::config::{
self, CrateType, ErrorOutputType, Input, OutFileName, OutputType, OutputTypes, ResolveDocLinks,
};
pub(crate) use rustc_session::config::{Options, UnstableOptions};
use rustc_session::{Session, lint};
use rustc_span::source_map;
Expand Down Expand Up @@ -219,7 +220,7 @@ pub(crate) fn create_config(
remap_path_prefix,
..
}: RustdocOptions,
RenderOptions { document_private, .. }: &RenderOptions,
render_options: &RenderOptions,
) -> rustc_interface::Config {
// Add the doc cfg into the doc build.
cfgs.push("doc".to_string());
Expand All @@ -245,8 +246,11 @@ pub(crate) fn create_config(

let crate_types =
if proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
let resolve_doc_links =
if *document_private { ResolveDocLinks::All } else { ResolveDocLinks::Exported };
let resolve_doc_links = if render_options.document_private {
ResolveDocLinks::All
} else {
ResolveDocLinks::Exported
};
let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
// plays with error output here!
let sessopts = config::Options {
Expand All @@ -269,10 +273,18 @@ pub(crate) fn create_config(
crate_name,
test,
remap_path_prefix,
output_types: if let Some(file) = render_options.dep_info() {
OutputTypes::new(&[(
OutputType::DepInfo,
file.map(|f| OutFileName::Real(f.to_path_buf())),
)])
} else {
OutputTypes::new(&[])
},
..Options::default()
};

interface::Config {
rustc_interface::Config {
opts: sessopts,
crate_cfg: cfgs,
crate_check_cfg: check_cfgs,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/render/write_shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fn write_rendered_cross_crate_info(
include_sources: bool,
) -> Result<(), Error> {
let m = &opt.should_merge;
if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
if opt.should_emit_crate() {
if include_sources {
write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, crates, m)?;
}
Expand Down
10 changes: 8 additions & 2 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ fn opts() -> Vec<RustcOptGroup> {
"",
"emit",
"Comma separated list of types of output for rustdoc to emit",
"[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]",
"[unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]",
),
opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""),
opt(
Expand Down Expand Up @@ -890,7 +890,13 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
// if we ran coverage, bail early, we don't need to also generate docs at this point
// (also we didn't load in any of the useful passes)
return;
} else if run_check {
}

if render_opts.dep_info().is_some() {
rustc_interface::passes::write_dep_info(tcx);
}

if run_check {
// Since we're in "check" mode, no need to generate anything beyond this point.
return;
}
Expand Down
16 changes: 14 additions & 2 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2412,8 +2412,9 @@ impl<'test> TestCx<'test> {
let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf());
normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");

// eg. /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui
normalize_path(&self.config.build_test_suite_root, "$TEST_BUILD_DIR");
// eg.
// /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui/<test_dir>/$name.$revision.$mode/
normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR");
// eg. /home/user/rust/build
normalize_path(&self.config.build_root, "$BUILD_DIR");

Expand All @@ -2433,6 +2434,17 @@ impl<'test> TestCx<'test> {
.replace_all(&normalized, "SRC_DIR$1:LL:COL")
.into_owned();

// Normalize long type name hash.
normalized =
static_regex!(r"\$TEST_BUILD_DIR/(?P<filename>[^\.]+).long-type-(?P<hash>\d+).txt")
.replace_all(&normalized, |caps: &Captures<'_>| {
format!(
"$TEST_BUILD_DIR/{filename}.long-type-$LONG_TYPE_HASH.txt",
filename = &caps["filename"]
)
})
.into_owned();

normalized = Self::normalize_platform_differences(&normalized);
normalized = normalized.replace("\t", "\\t"); // makes tabs visible

Expand Down
43 changes: 28 additions & 15 deletions src/tools/jsondocck/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;
use std::process::ExitCode;
use std::sync::OnceLock;
use std::sync::LazyLock;
use std::{env, fs};

use regex::{Regex, RegexBuilder};
Expand Down Expand Up @@ -151,8 +151,7 @@ impl CommandKind {
}
}

static LINE_PATTERN: OnceLock<Regex> = OnceLock::new();
fn line_pattern() -> Regex {
static LINE_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
RegexBuilder::new(
r#"
//@\s+
Expand All @@ -165,7 +164,19 @@ fn line_pattern() -> Regex {
.unicode(true)
.build()
.unwrap()
}
});

static DEPRECATED_LINE_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
RegexBuilder::new(
r#"
//\s+@
"#,
)
.ignore_whitespace(true)
.unicode(true)
.build()
.unwrap()
});

fn print_err(msg: &str, lineno: usize) {
eprintln!("Invalid command: {} on line {}", msg, lineno)
Expand All @@ -184,21 +195,23 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
for (lineno, line) in file.split('\n').enumerate() {
let lineno = lineno + 1;

let cap = match LINE_PATTERN.get_or_init(line_pattern).captures(line) {
Some(c) => c,
None => continue,
if DEPRECATED_LINE_PATTERN.is_match(line) {
print_err("Deprecated command syntax, replace `// @` with `//@ `", lineno);
errors = true;
continue;
}

let Some(cap) = LINE_PATTERN.captures(line) else {
continue;
};

let negated = cap.name("negated").unwrap().as_str() == "!";
let negated = &cap["negated"] == "!";

let args_str = &cap["args"];
let args = match shlex::split(args_str) {
Some(args) => args,
None => {
print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno);
errors = true;
continue;
}
let Some(args) = shlex::split(args_str) else {
print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno);
errors = true;
continue;
};

if let Some((kind, path)) = CommandKind::parse(&cap["cmd"], negated, &args) {
Expand Down
7 changes: 7 additions & 0 deletions src/tools/run-make-support/src/external_deps/rustdoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,11 @@ impl Rustdoc {
self.cmd.arg(format);
self
}

/// Specify type(s) of output files to generate.
pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
let kinds = kinds.as_ref();
self.cmd.arg(format!("--emit={kinds}"));
self
}
}
17 changes: 17 additions & 0 deletions tests/codegen/issues/looping-over-ne-bytes-133528.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//@ compile-flags: -Copt-level=3
//@ min-llvm-version: 20
#![crate_type = "lib"]

/// Ensure the function is properly optimized
/// In the issue #133528, the function was not getting optimized
/// whereas, a version with `bytes` wrapped into a `black_box` was optimized
/// It was probably a LLVM bug that was fixed in LLVM 20

// CHECK-LABEL: @looping_over_ne_bytes
// CHECK: icmp eq i64 %input, -1
// CHECK-NEXT: ret i1
#[no_mangle]
fn looping_over_ne_bytes(input: u64) -> bool {
let bytes = input.to_ne_bytes();
bytes.iter().all(|x| *x == !0)
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Options:
--generate-redirect-map
Generate JSON file at the top level instead of
generating HTML redirection files
--emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific]
--emit [unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]
Comma separated list of types of output for rustdoc to
emit
--no-run Compile doctests without running them
Expand Down
1 change: 1 addition & 0 deletions tests/run-make/rustdoc-dep-info/bar.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include!("foo.rs");
1 change: 1 addition & 0 deletions tests/run-make/rustdoc-dep-info/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
blablabla
1 change: 1 addition & 0 deletions tests/run-make/rustdoc-dep-info/foo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub fn foo() {}
Loading
Loading