Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
299213f
PassWrapper: handle LLVM 24 change in function types
durin42 Aug 14, 2026
50b867f
PassWrapper: clang-format
durin42 Aug 14, 2026
226b175
Check for missing rustfmt in the stdarch intrinsic test step sooner
Kobzol Aug 24, 2026
afcb367
Don't treat slashes as path seps after drive letters in verbatim paths
maxdexh Aug 24, 2026
7eaf48c
Pass LargeDataThreshold to LLVM module IR
jakos-sec Aug 21, 2026
97967de
Add new `unescaped_pipe_in_table_cell` rustdoc lint
GuillaumeGomez Jul 19, 2026
dbe2c8e
Add ui regression test for new rustdoc `unescaped_pipe_in_table_cell`…
GuillaumeGomez Jul 19, 2026
f74d66c
Add documentation for rustdoc `unescaped_pipe_in_table_cell` lint
GuillaumeGomez Jul 19, 2026
fe90bb2
Rename lint `unescaped_pipe_in_table_cell` into `invalid_markdown_table`
GuillaumeGomez Jul 24, 2026
67bfe3a
Also warn in case there is content after the last table cell
GuillaumeGomez Jul 24, 2026
df734af
rustdoc: clean up some unneeded table lint code
notriddle Jul 24, 2026
aeb0d4a
Update lint to new rustdoc table lint
GuillaumeGomez Aug 24, 2026
1f7f241
Fix whitespace.
durin42 Aug 24, 2026
eb1aebf
rustdoc: fix issue preventing "read more" links from generating.
lolbinarycat Aug 22, 2026
a83329a
rustdoc: Nuke `--passes=list`
fmease Aug 24, 2026
f1acecf
rustdoc: Defossilize the passes infrastructure
fmease Sep 27, 2025
b1f7d8e
bootstrap: don't LTO C dependencies on aarch64
RalfJung Aug 24, 2026
1f5e36d
rustdoc: check redundant explicit links against generated URLs
qaijuang Aug 24, 2026
e6bae81
Simply check if the large_data_threshold is set instead of unwrapping
jakos-sec Aug 24, 2026
1b6b615
Rollup merge of #161689 - RalfJung:aarch64-no-lto, r=Kobzol
GuillaumeGomez Aug 24, 2026
7d749cf
Rollup merge of #161553 - lolbinarycat:rustdoc-fix-read-more, r=Guill…
GuillaumeGomez Aug 24, 2026
0ce1db7
Rollup merge of #161670 - jakos-sec:large-data-threshold, r=nagisa
GuillaumeGomez Aug 24, 2026
c270415
Rollup merge of #146529 - fmease:rustdoc-nuke-passes-list, r=Guillaum…
GuillaumeGomez Aug 24, 2026
e1fdd1e
Rollup merge of #156009 - qaijuang:rustdoc-redundant-explicit-links-u…
GuillaumeGomez Aug 24, 2026
3e5db1a
Rollup merge of #159583 - GuillaumeGomez:unescaped_pipe_in_table_cell…
GuillaumeGomez Aug 24, 2026
4de5370
Rollup merge of #161098 - durin42:llvm-24-llvm-any-change, r=cuviper
GuillaumeGomez Aug 24, 2026
a7026e0
Rollup merge of #161641 - Kobzol:intrinsic-test-rustfmt-check-fix, r=…
GuillaumeGomez Aug 24, 2026
21b4ef6
Rollup merge of #161661 - maxdexh:least-cursed-windows-feature, r=Chr…
GuillaumeGomez Aug 24, 2026
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
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,12 @@ pub(crate) unsafe fn create_module<'ll>(
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
}

if let Some(large_data_threshold) = sess.opts.unstable_opts.large_data_threshold {
unsafe {
llvm::LLVMRustSetModuleLargeDataThreshold(llmod, large_data_threshold);
}
}

// If skipping the PLT is enabled, we need to add some module metadata
// to ensure intrinsic calls don't use it.
if !sess.needs_plt() {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,7 @@ unsafe extern "C" {
pub(crate) fn LLVMRustSetModulePICLevel(M: &Module);
pub(crate) fn LLVMRustSetModulePIELevel(M: &Module);
pub(crate) fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel);
pub(crate) fn LLVMRustSetModuleLargeDataThreshold(M: &Module, Threshold: u64);
pub(crate) fn LLVMRustBufferPtr(p: &Buffer) -> *const u8;
pub(crate) fn LLVMRustBufferLen(p: &Buffer) -> usize;
pub(crate) fn LLVMRustBufferFree(p: &'static mut Buffer);
Expand Down
50 changes: 44 additions & 6 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,17 @@ extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(
extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(
void *); // LlvmSelfProfiler

#if LLVM_VERSION_GE(24, 0)
std::string LLVMRustwrappedIrGetName(const llvm::IRUnitRef &WrappedIr) {
if (const auto *Cast = dyn_cast<Module>(WrappedIr))
return Cast->getName().str();
if (const auto *Cast = dyn_cast<Function>(WrappedIr))
return Cast->getName().str();
if (const auto *Cast = dyn_cast<Loop>(WrappedIr))
return Cast->getName().str();
if (const auto *Cast = dyn_cast<LazyCallGraph::SCC>(WrappedIr))
return Cast->getName();
#else
std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
if (const auto *Cast = any_cast<const Module *>(&WrappedIr))
return (*Cast)->getName().str();
Expand All @@ -538,6 +549,7 @@ std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) {
return (*Cast)->getName().str();
if (const auto *Cast = any_cast<const LazyCallGraph::SCC *>(&WrappedIr))
return (*Cast)->getName();
#endif
return "<UNKNOWN>";
}

Expand All @@ -546,15 +558,26 @@ void LLVMSelfProfileInitializeCallbacks(
LLVMRustSelfProfileBeforePassCallback BeforePassCallback,
LLVMRustSelfProfileAfterPassCallback AfterPassCallback) {
PIC.registerBeforeNonSkippedPassCallback(
#if LLVM_VERSION_GE(24, 0)
[LlvmSelfProfiler, BeforePassCallback](StringRef Pass,
llvm::IRUnitRef Ir) {
#else
[LlvmSelfProfiler, BeforePassCallback](StringRef Pass, llvm::Any Ir) {
#endif
std::string PassName = Pass.str();
std::string IrName = LLVMRustwrappedIrGetName(Ir);
BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
});

PIC.registerAfterPassCallback(
#if LLVM_VERSION_GE(24, 0)
[LlvmSelfProfiler,
AfterPassCallback](StringRef Pass, llvm::IRUnitRef IR,
const PreservedAnalyses &Preserved) {
#else
[LlvmSelfProfiler, AfterPassCallback](
StringRef Pass, llvm::Any IR, const PreservedAnalyses &Preserved) {
#endif
AfterPassCallback(LlvmSelfProfiler);
});

Expand All @@ -564,17 +587,27 @@ void LLVMSelfProfileInitializeCallbacks(
AfterPassCallback(LlvmSelfProfiler);
});

#if LLVM_VERSION_GE(24, 0)
PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback](
StringRef Pass, llvm::IRUnitRef Ir) {
#else
PIC.registerBeforeAnalysisCallback(
[LlvmSelfProfiler, BeforePassCallback](StringRef Pass, llvm::Any Ir) {
std::string PassName = Pass.str();
std::string IrName = LLVMRustwrappedIrGetName(Ir);
BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
});
#endif
std::string PassName = Pass.str();
std::string IrName = LLVMRustwrappedIrGetName(Ir);
BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str());
});

#if LLVM_VERSION_GE(24, 0)
PIC.registerAfterAnalysisCallback([LlvmSelfProfiler, AfterPassCallback](
StringRef Pass, llvm::IRUnitRef Ir) {
#else
PIC.registerAfterAnalysisCallback(
[LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) {
AfterPassCallback(LlvmSelfProfiler);
});
#endif
AfterPassCallback(LlvmSelfProfiler);
});
}

enum class LLVMRustOptStage {
Expand Down Expand Up @@ -1185,6 +1218,11 @@ extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
unwrap(M)->setCodeModel(*CM);
}

extern "C" void LLVMRustSetModuleLargeDataThreshold(LLVMModuleRef M,
uint64_t Threshold) {
unwrap(M)->setLargeDataThreshold(Threshold);
}

// Here you'll find an implementation of ThinLTO as used by the Rust compiler
// right now. This ThinLTO support is only enabled on "recent ish" versions of
// LLVM, and otherwise it's just blanket rejected from other compilers.
Expand Down
23 changes: 20 additions & 3 deletions library/std/src/sys/path/windows/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ fn verbatim() {
// Make sure opening a drive will work.
check("Z:", "Z:");

// Verbatim drive paths begin with `LETTER:\`. `/` is just a regular character here
check(r"\\?\C:/path\somewhere", r"\\?\C:/path\somewhere");

// A path that contains null is not a valid path.
assert!(maybe_verbatim(Path::new("\0")).is_err());
}
Expand All @@ -93,9 +96,23 @@ fn parse_prefix(path: &str) -> Option<Prefix<'_>> {

#[test]
fn test_parse_prefix_verbatim() {
let prefix = Some(Prefix::VerbatimDisk(b'C'));
assert_eq!(prefix, parse_prefix(r"\\?\C:/windows/system32/notepad.exe"));
assert_eq!(prefix, parse_prefix(r"\\?\C:\windows\system32\notepad.exe"));
assert_eq!(
parse_prefix(r"\\?\C:\windows\system32\notepad.exe"),
Some(Prefix::VerbatimDisk(b'C')),
);
}

#[test]
fn test_verbatim_disk_issue_161651() {
use crate::path::Path;

// This is not a `VerbatimDisk` path, because `/` is not a separator in verbatim paths!
assert_eq!(
parse_prefix(r"\\?\C:/windows\system32"),
Some(Prefix::Verbatim(OsStr::new("C:/windows"))),
);

assert_ne!(Path::new(r"\\?\C:/foo"), Path::new(r"\\?\C:\foo"));
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/path/windows_prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ fn parse_drive(path: &OsStr) -> Option<u8> {
// Parses a drive prefix exactly, e.g. "C:"
fn parse_drive_exact(path: &OsStr) -> Option<u8> {
// only parse two bytes: the drive letter and the drive separator
if path.as_encoded_bytes().get(2).map(|&x| is_sep_byte(x)).unwrap_or(true) {
if path.as_encoded_bytes().get(2).map(|&x| is_verbatim_sep(x)).unwrap_or(true) {
parse_drive(path)
} else {
None
Expand Down
10 changes: 5 additions & 5 deletions library/std/tests/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -989,14 +989,14 @@ pub fn test_decompositions_windows() {
);

t!("\\\\?\\C:/foo/bar",
iter: ["\\\\?\\C:", "\\", "foo/bar"],
iter: ["\\\\?\\C:/foo/bar"],
has_root: true,
is_absolute: true,
parent: Some("\\\\?\\C:/"),
file_name: Some("foo/bar"),
file_stem: Some("foo/bar"),
parent: None,
file_name: None,
file_stem: None,
extension: None,
file_prefix: Some("foo/bar")
file_prefix: None
);

t!("\\\\.\\foo\\bar",
Expand Down
16 changes: 8 additions & 8 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,14 @@ impl CommandLineStep for IntrinsicTest {
builder.info(&format!("Skipping intrinsic-test, as it is not available for {host}"));
return;
}
// intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's
// managed binaries findable by prepending their dirs to PATH.
let Some(rustfmt_path) = builder.ensure(InternalRustfmt) else {
eprintln!(
"WARNING: intrinsic-test skipped because rustfmt is required but not available on this channel"
);
return;
};

let (input_file, skip_file, cflags, sde_runner) = if host.contains("x86_64-unknown-linux") {
let Some(sde) = &builder.config.sde else {
Expand Down Expand Up @@ -1172,14 +1180,6 @@ impl CommandLineStep for IntrinsicTest {
cmd.arg("--cc-arg-style").arg("gcc");
cmd.env("CC", builder.cc(host));
cmd.env("CFLAGS", cflags);
// intrinsic-test shells out to `cargo` and `rustfmt` make bootstrap's
// managed binaries findable by prepending their dirs to PATH.
let Some(rustfmt_path) = builder.ensure(InternalRustfmt) else {
eprintln!(
"WARNING: intrinsic-test skipped because rustfmt is required but not available on this channel"
);
return;
};

let mut path_dirs: Vec<PathBuf> = Vec::new();
if let Some(cargo_dir) = builder.initial_cargo.parent() {
Expand Down
9 changes: 8 additions & 1 deletion src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,13 @@ impl Cargo {
let lto_cflag = if matches!(self.mode, Mode::Rustc | Mode::ToolRustcPrivate)
&& is_lto_stage(&self.compiler)
&& builder.cc_tool(target).is_like_clang()
// Exclude aarch64-linux as we can't assume the user has an LTO-capable linker
// (and these files get distributed in the rustc-dev component).
// FIXME: this means the argument above about doing this for rustc but not std makes
// no sense. We distribute rlibs for both, so both need to be linkable by users. I
// guess we just don't want to risk this for std, but are less worried about
// breaking rustc-dev.
&& !target.starts_with("aarch64-unknown-linux")
{
match builder.config.rust_lto {
RustcLto::Thin => Some("-flto=thin"),
Expand All @@ -474,7 +481,7 @@ impl Cargo {
None
};

// Extend `CXXFLAGS_$TARGET` with our extra flags.
// Extend `CFLAGS_$TARGET` with our extra flags.
let env = format!("CFLAGS_{triple_underscored}");
let mut cflags =
builder.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C).join(" ");
Expand Down
28 changes: 28 additions & 0 deletions src/doc/rustdoc/src/lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,31 @@ note: the lint level is defined here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: Remove explicit link instead
```

## `invalid_markdown_table`

This lint is **warn-by-default**. It detects unescaped pipes (`|`) in table rows which
lead to some row cells being ignored. For example:

```rust
//! | col1 |
//! | ---- |
//! | `code_with(|arg| arg)` |
```

Which will give:

```text
error: table row has too many columns
--> $DIR/foo.rs:5:18
|
5 | //! | `code_with(|arg| arg)` |
| ^ help: any content after this column divider is discarded
|
= help: to escape `|` characters in tables, add a `\` before them like `\|`
note: the lint level is defined here
--> $DIR/foo.rs:1:9
|
1 | #![deny(rustdoc::invalid_markdown_table)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
7 changes: 5 additions & 2 deletions src/librustdoc/calculate_doc_coverage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! Calculates information used for the --show-coverage flag.
//! Calculates information used for the `--show-coverage` flag.
//!
//! More specifically, it counts the number of items with documentation, ones with
//! "examples" (i.e., non-ignored Rust code blocks) and various totals.

use std::collections::BTreeMap;
use std::fs::{File, create_dir_all};
Expand All @@ -17,7 +20,7 @@ use crate::core::DocContext;
use crate::docfs::PathError;
use crate::error::Error;
use crate::html::markdown::{ErrorCodes, find_testable_code};
use crate::passes::{Tests, should_have_doc_example};
use crate::passes::check_doc_test_visibility::{Tests, should_have_doc_example};
use crate::visit::DocVisitor;
use crate::{clean, try_err};

Expand Down
34 changes: 0 additions & 34 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use crate::externalfiles::ExternalHtml;
use crate::html::markdown::IdMap;
use crate::html::render::StylePath;
use crate::html::static_files;
use crate::passes::{self, Condition};
use crate::scrape_examples::{AllCallLocations, ScrapeExamplesOptions};
use crate::{html, opts, theme};

Expand Down Expand Up @@ -428,40 +427,7 @@ impl Options {
// check for deprecated options
check_deprecated_options(matches, dcx);

if matches.opt_strs("passes") == ["list"] {
println!("Available passes for running rustdoc:");
for pass in passes::PASSES {
println!("{:>20} - {}", pass.name, pass.description);
}
println!("\nDefault passes for rustdoc:");
for p in passes::DEFAULT_PASSES {
print!("{:>20}", p.pass.name);
println_condition(p.condition);
}

if nightly_options::match_is_nightly_build(matches) {
println!("\nPasses run with `--show-coverage`:");
for p in passes::COVERAGE_PASSES {
print!("{:>20}", p.pass.name);
println_condition(p.condition);
}
}

fn println_condition(condition: Condition) {
use Condition::*;
match condition {
Always => println!(),
WhenDocumentPrivate => println!(" (when --document-private-items)"),
WhenNotDocumentPrivate => println!(" (when not --document-private-items)"),
WhenNotDocumentHidden => println!(" (when not --document-hidden-items)"),
}
}

return None;
}

let should_test = matches.opt_present("test");

let show_coverage = matches.opt_present("show-coverage");
let output_format_s = matches.opt_str("output-format");
let output_format = match output_format_s.as_deref() {
Expand Down
Loading
Loading