diff --git a/crates/rustc_plugin/examples/print-all-items/rust-toolchain.toml b/crates/rustc_plugin/examples/print-all-items/rust-toolchain.toml index f67f0a7f1..1d17e68a8 100644 --- a/crates/rustc_plugin/examples/print-all-items/rust-toolchain.toml +++ b/crates/rustc_plugin/examples/print-all-items/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-08-20" +channel = "nightly-2026-05-01" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs b/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs index 299b20f02..e6b698c04 100644 --- a/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs +++ b/crates/rustc_plugin/examples/print-all-items/src/bin/cargo-print-all-items.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] -fn main() { +fn main() -> std::process::ExitCode { env_logger::init(); - rustc_plugin::cli_main(print_all_items::PrintAllItemsPlugin); + rustc_plugin::cli_main(print_all_items::PrintAllItemsPlugin) } diff --git a/crates/rustc_plugin/examples/print-all-items/src/bin/print-all-items-driver.rs b/crates/rustc_plugin/examples/print-all-items/src/bin/print-all-items-driver.rs index 1d173af8e..d43e97b9b 100644 --- a/crates/rustc_plugin/examples/print-all-items/src/bin/print-all-items-driver.rs +++ b/crates/rustc_plugin/examples/print-all-items/src/bin/print-all-items-driver.rs @@ -1,6 +1,6 @@ #![feature(rustc_private)] -fn main() { +fn main() -> std::process::ExitCode { env_logger::init(); - rustc_plugin::driver_main(print_all_items::PrintAllItemsPlugin); + rustc_plugin::driver_main(print_all_items::PrintAllItemsPlugin) } diff --git a/crates/rustc_plugin/src/cli.rs b/crates/rustc_plugin/src/cli.rs index 6299e3602..4921b0bca 100644 --- a/crates/rustc_plugin/src/cli.rs +++ b/crates/rustc_plugin/src/cli.rs @@ -1,7 +1,7 @@ use std::{ env, fs, path::PathBuf, - process::{Command, Stdio, exit}, + process::{Command, ExitCode, Stdio}, }; use cargo_metadata::camino::Utf8Path; @@ -15,10 +15,10 @@ pub const SPECIFIC_TARGET: &str = "SPECIFIC_TARGET"; pub const CARGO_VERBOSE: &str = "CARGO_VERBOSE"; /// The top-level function that should be called in your user-facing binary. -pub fn cli_main(plugin: T) { +pub fn cli_main(plugin: T) -> ExitCode { if env::args().any(|arg| arg == "-V") { println!("{}", plugin.version()); - return; + return ExitCode::SUCCESS; } let metadata = cargo_metadata::MetadataCommand::new() @@ -95,7 +95,10 @@ pub fn cli_main(plugin: T) { let exit_status = cmd.status().expect("failed to wait for cargo?"); - exit(exit_status.code().unwrap_or(-1)); + match exit_status.code() { + Some(code) => ExitCode::from(u8::try_from(code).unwrap()), + None => ExitCode::FAILURE, + } } fn only_run_on_file( diff --git a/crates/rustc_plugin/src/driver.rs b/crates/rustc_plugin/src/driver.rs index 231d68fd7..acc07a901 100644 --- a/crates/rustc_plugin/src/driver.rs +++ b/crates/rustc_plugin/src/driver.rs @@ -2,7 +2,7 @@ use std::{ env, ops::Deref, path::{Path, PathBuf}, - process::{Command, exit}, + process::{Command, ExitCode, exit}, }; use rustc_session::{EarlyDiagCtxt, config::ErrorOutputType}; @@ -99,11 +99,11 @@ struct DefaultCallbacks; impl rustc_driver::Callbacks for DefaultCallbacks {} /// The top-level function that should be called by your internal driver binary. -pub fn driver_main(plugin: T) { +pub fn driver_main(plugin: T) -> ExitCode { let early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); rustc_driver::init_rustc_env_logger(&early_dcx); - exit(rustc_driver::catch_with_exit_code(move || { + rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec = env::args().collect(); let (have_sys_root_arg, sys_root) = get_sysroot(&orig_args); @@ -157,7 +157,7 @@ is_target_crate={is_target_crate}" ); rustc_driver::run_compiler(&args, &mut DefaultCallbacks); } - })) + }) } fn is_target_crate(args: &[String]) -> bool { diff --git a/crates/rustc_utils/Cargo.toml b/crates/rustc_utils/Cargo.toml index 309382337..1184486e3 100644 --- a/crates/rustc_utils/Cargo.toml +++ b/crates/rustc_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_utils" -version = "0.14.3-nightly-2025-08-20" +version = "0.15.0-nightly-2026-05-01" edition = "2024" authors = ["Will Crichton "] description = "Utilities for working with the Rust compiler" diff --git a/crates/rustc_utils/src/hir/ty.rs b/crates/rustc_utils/src/hir/ty.rs index f62bd00cb..42ee7a2c5 100644 --- a/crates/rustc_utils/src/hir/ty.rs +++ b/crates/rustc_utils/src/hir/ty.rs @@ -41,7 +41,7 @@ impl<'tcx> TyExt<'tcx> for Ty<'tcx> { use rustc_infer::traits::EvaluationResult; let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - let ty = tcx.erase_regions(self); + let ty = tcx.erase_and_anonymize_regions(self); let result = infcx.type_implements_trait(trait_def_id, [ty], param_env); matches!( result, @@ -50,7 +50,7 @@ impl<'tcx> TyExt<'tcx> for Ty<'tcx> { } fn is_copyable(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool { - let ty = tcx.erase_regions(self); + let ty = tcx.erase_and_anonymize_regions(self); tcx.type_is_copy_modulo_regions(typing_env, ty) } } diff --git a/crates/rustc_utils/src/lib.rs b/crates/rustc_utils/src/lib.rs index e2568187f..c611694d2 100644 --- a/crates/rustc_utils/src/lib.rs +++ b/crates/rustc_utils/src/lib.rs @@ -12,13 +12,8 @@ #![feature( rustc_private, - negative_impls, // for !Send min_specialization, // for rustc_index::newtype_index - type_alias_impl_trait, // for iterators in traits box_patterns, // for ergonomics - exact_size_is_empty, // for graphviz module - impl_trait_in_assoc_type, - doc_auto_cfg, // for feature gates in documentation )] #![warn(clippy::pedantic)] #![allow( diff --git a/crates/rustc_utils/src/mir/body.rs b/crates/rustc_utils/src/mir/body.rs index 5f4d88ba4..fefb4fc20 100644 --- a/crates/rustc_utils/src/mir/body.rs +++ b/crates/rustc_utils/src/mir/body.rs @@ -7,13 +7,12 @@ use std::{ }; use anyhow::{Result, ensure}; -use pretty::PrettyPrintMirOptions; use rustc_data_structures::fx::FxHashMap as HashMap; use rustc_hir::{CoroutineDesugaring, CoroutineKind, HirId, def_id::DefId}; use rustc_middle::{ mir::{ BasicBlock, Body, Local, Location, Place, SourceInfo, TerminatorKind, - VarDebugInfoContents, pretty, pretty::write_mir_fn, + VarDebugInfoContents, pretty::MirWriter, }, ty::{Region, Ty, TyCtxt}, }; @@ -118,15 +117,7 @@ impl<'tcx> BodyExt<'tcx> for Body<'tcx> { fn to_string(&self, tcx: TyCtxt<'tcx>) -> Result { let mut buffer = Vec::new(); - write_mir_fn( - tcx, - self, - &mut |_, _| Ok(()), - &mut buffer, - PrettyPrintMirOptions { - include_extra_comments: false, - }, - )?; + MirWriter::new(tcx).write_mir_fn(self, &mut buffer)?; Ok(String::from_utf8(buffer)?) } diff --git a/crates/rustc_utils/src/mir/borrowck_facts.rs b/crates/rustc_utils/src/mir/borrowck_facts.rs index dac92d200..1097251e9 100644 --- a/crates/rustc_utils/src/mir/borrowck_facts.rs +++ b/crates/rustc_utils/src/mir/borrowck_facts.rs @@ -6,11 +6,10 @@ use rustc_borrowck::consumers::{BodyWithBorrowckFacts, ConsumerOptions}; use rustc_data_structures::fx::FxHashSet as HashSet; use rustc_hir::def_id::LocalDefId; use rustc_middle::{ - mir::{Body, ConcreteOpaqueTypes, StatementKind, TerminatorKind}, + mir::{Body, StatementKind, TerminatorKind}, ty::TyCtxt, util::Providers, }; -use rustc_span::ErrorGuaranteed; use crate::{BodyExt, block_timer, cache::Cache}; @@ -61,7 +60,7 @@ pub fn enable_mir_simplification() { /// For why we need to do override mir_borrowck, see: /// pub fn override_queries(_session: &rustc_session::Session, local: &mut Providers) { - local.mir_borrowck = mir_borrowck; + local.queries.mir_borrowck = mir_borrowck; } thread_local! { @@ -71,7 +70,7 @@ thread_local! { fn mir_borrowck( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> Result<&ConcreteOpaqueTypes<'_>, ErrorGuaranteed> { +) -> rustc_middle::queries::mir_borrowck::ProvidedValue<'_> { block_timer!(&format!( "get_bodies_with_borrowck_facts for {}", tcx.def_path_debug_str(def_id.to_def_id()) @@ -96,8 +95,8 @@ fn mir_borrowck( }); } let mut providers = Providers::default(); - rustc_borrowck::provide(&mut providers); - let original_mir_borrowck = providers.mir_borrowck; + rustc_borrowck::provide(&mut providers.queries); + let original_mir_borrowck = providers.queries.mir_borrowck; original_mir_borrowck(tcx, def_id) } diff --git a/crates/rustc_utils/src/mir/operand.rs b/crates/rustc_utils/src/mir/operand.rs index 690e79ed7..f90a1f5a5 100644 --- a/crates/rustc_utils/src/mir/operand.rs +++ b/crates/rustc_utils/src/mir/operand.rs @@ -12,7 +12,7 @@ impl<'tcx> OperandExt<'tcx> for Operand<'tcx> { fn as_place(&self) -> Option> { match self { Operand::Copy(place) | Operand::Move(place) => Some(*place), - Operand::Constant(_) => None, + Operand::Constant(_) | Operand::RuntimeChecks(_) => None, } } } diff --git a/crates/rustc_utils/src/mir/place.rs b/crates/rustc_utils/src/mir/place.rs index ec41463d7..3d4527107 100644 --- a/crates/rustc_utils/src/mir/place.rs +++ b/crates/rustc_utils/src/mir/place.rs @@ -6,18 +6,15 @@ use log::{trace, warn}; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::{FxHashMap as HashMap, FxHashSet as HashSet}; use rustc_hir::def_id::DefId; -use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::{ mir::{ Body, HasLocalDecls, Local, Location, Mutability, Place, PlaceElem, PlaceRef, ProjectionElem, RETURN_PLACE, VarDebugInfo, VarDebugInfoContents, visit::{PlaceContext, Visitor}, }, - traits::ObligationCause, ty::{self, AdtKind, Region, RegionKind, RegionVid, Ty, TyCtxt, TyKind, TypeVisitor}, }; -use rustc_trait_selection::traits::NormalizeExt; -use rustc_type_ir::TypingMode; +use rustc_type_ir::Unnormalized; use crate::{AdtDefExt, SpanExt}; @@ -285,7 +282,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } ProjectionElem::Downcast(sym, _) => { let variant = sym.map(|s| s.to_string()).unwrap_or_else(|| "??".into()); - (ElemPosition::Suffix, format!("@{variant}",).into()) + (ElemPosition::Suffix, format!("@{variant}").into()) } ProjectionElem::Index(_) => (ElemPosition::Suffix, "[_]".into()), @@ -319,16 +316,10 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } fn normalize(&self, tcx: TyCtxt<'tcx>, def_id: DefId) -> Place<'tcx> { - let param_env = tcx.param_env(def_id); - let place = tcx.erase_regions(*self); - let infcx = tcx.infer_ctxt().build(TypingMode::post_borrowck_analysis( - tcx, - def_id.expect_local(), - )); - let place = infcx - .at(&ObligationCause::dummy(), param_env) - .normalize(place) - .value; + let place = tcx.normalize_erasing_regions( + tcx.typing_env_normalized_for_post_analysis(def_id), + Unnormalized::new_wip(*self), + ); let projection = place .projection diff --git a/crates/rustc_utils/src/source_map/filename.rs b/crates/rustc_utils/src/source_map/filename.rs index e802d4dd7..fbcca5814 100644 --- a/crates/rustc_utils/src/source_map/filename.rs +++ b/crates/rustc_utils/src/source_map/filename.rs @@ -1,11 +1,37 @@ -use std::path::PathBuf; +use std::{fmt, path::PathBuf}; + +use rustc_index::Idx; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Filename(pub PathBuf); -rustc_index::newtype_index! { - #[cfg_attr(feature = "serde", derive(serde::Serialize))] - #[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))] - #[debug_format = "f{}"] - pub struct FilenameIndex {} +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] +#[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))] +pub struct FilenameIndex(usize); + +impl fmt::Debug for FilenameIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "f{}", self.0) + } } + +impl Idx for FilenameIndex { + fn new(idx: usize) -> Self { + FilenameIndex(idx) + } + + fn index(self) -> usize { + self.0 + } +} + +// NOTE(nightly-2026-05-01): the newtype_index has been commented out below +// bc it uses some wacky `T is range` type that isn't implemented by serde or ts_rs. + +// rustc_index::newtype_index! { +// #[cfg_attr(feature = "serde", derive(serde::Serialize))] +// #[cfg_attr(feature = "ts-rs", derive(ts_rs::TS))] +// #[debug_format = "f{}"] +// pub struct FilenameIndex {} +// } diff --git a/crates/rustc_utils/src/source_map/range.rs b/crates/rustc_utils/src/source_map/range.rs index 1a4790b0c..092914c07 100644 --- a/crates/rustc_utils/src/source_map/range.rs +++ b/crates/rustc_utils/src/source_map/range.rs @@ -11,7 +11,9 @@ use rustc_hir::{ }; use rustc_index::IndexVec; use rustc_middle::ty::TyCtxt; -use rustc_span::{FileName, RealFileName, SourceFile, Span, source_map::SourceMap}; +use rustc_span::{ + FileName, RemapPathScopeComponents, SourceFile, Span, source_map::SourceMap, +}; #[cfg(feature = "serde")] use serde::Serialize; #[cfg(feature = "ts-rs")] @@ -141,9 +143,10 @@ impl FilenameIndex { .find(|name| match &name { // rustc seems to store relative paths to files in the workspace, so if filename is absolute, // we can compare them using Path::ends_with - FileName::Real(RealFileName::LocalPath(other)) => { + FileName::Real(real_file_name) => { + let other = real_file_name.path(RemapPathScopeComponents::DOCUMENTATION).to_path_buf(); let canonical = other.canonicalize(); - let other = canonical.as_ref().unwrap_or(other); + let other = canonical.as_ref().unwrap_or(&other); filename.ends_with(other) } _ => false, @@ -155,8 +158,8 @@ impl FilenameIndex { files .iter() .filter_map(|file| match &file.name { - FileName::Real(RealFileName::LocalPath(other)) => - Some(format!("{}", other.display())), + FileName::Real(other) => + Some(other.path(RemapPathScopeComponents::DOCUMENTATION).display().to_string()), _ => None, }) .collect::>() @@ -269,8 +272,9 @@ impl ByteRange { log::trace!("Converting to range: {span:?}"); let file = source_map.lookup_source_file(span.lo()); let filename = match &file.name { - FileName::Real(RealFileName::LocalPath(filename)) => { - Filename(filename.clone()).intern_with_ctx(&mut ctx) + FileName::Real(real_file_name) => { + let filename = real_file_name.path(RemapPathScopeComponents::DOCUMENTATION); + Filename(filename.to_path_buf()).intern_with_ctx(&mut ctx) } filename => bail!("Range::from_span doesn't support {filename:?}"), }; diff --git a/crates/rustc_utils/src/source_map/spanner/mod.rs b/crates/rustc_utils/src/source_map/spanner/mod.rs index fab128edd..2ab092a7c 100644 --- a/crates/rustc_utils/src/source_map/spanner/mod.rs +++ b/crates/rustc_utils/src/source_map/spanner/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::{ }, ty::TyCtxt, }; -use rustc_span::{Span, SpanData, source_map::Spanned}; +use rustc_span::{Span, SpanData, Spanned}; pub use self::hir_span::EnclosingHirSpans; use self::{ diff --git a/crates/rustc_utils/src/source_map/spanner/span_tree.rs b/crates/rustc_utils/src/source_map/spanner/span_tree.rs index f69506c04..d58e3e8df 100644 --- a/crates/rustc_utils/src/source_map/spanner/span_tree.rs +++ b/crates/rustc_utils/src/source_map/spanner/span_tree.rs @@ -1,5 +1,5 @@ use intervaltree::IntervalTree; -use rustc_span::{BytePos, SpanData, source_map::Spanned}; +use rustc_span::{BytePos, SpanData, Spanned}; /// Interval tree data structure specialized to spans. pub struct SpanTree { diff --git a/crates/rustc_utils/src/test_utils.rs b/crates/rustc_utils/src/test_utils.rs index 0950dc8ba..61a5c6b7f 100644 --- a/crates/rustc_utils/src/test_utils.rs +++ b/crates/rustc_utils/src/test_utils.rs @@ -46,6 +46,10 @@ impl FileLoader for StringLoader { fn read_binary_file(&self, path: &Path) -> io::Result> { Ok(fs::read(path)?.into()) } + + fn current_directory(&self) -> io::Result { + Ok(std::env::current_dir().unwrap()) + } } static SYSROOT: LazyLock = LazyLock::new(|| { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 50f81edad..b189af119 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2025-08-20" +channel = "nightly-2026-05-01" components = ["clippy", "rust-src", "rustc-dev", "llvm-tools-preview"]