diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2025-09-03 05:01:14 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2025-09-03 05:01:14 +0000 |
| commit | d98a9c6931559f4b40a1913e74f3eb95c32c113c (patch) | |
| tree | 5783612df63a41809930ecf425792bcaad347e22 | |
| parent | ef1dab1cb6234bb32a5b82e31b8684be0cabfcd9 (diff) | |
| parent | 51ff895062ba60a7cba53f57af928c3fb7b0f2f4 (diff) | |
| download | rust-d98a9c6931559f4b40a1913e74f3eb95c32c113c.tar.gz rust-d98a9c6931559f4b40a1913e74f3eb95c32c113c.zip | |
Merge ref '51ff895062ba' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref: 51ff895062ba60a7cba53f57af928c3fb7b0f2f4 Filtered ref: 5057370cda58bcaad24ea094ec11c8c01b24c2bc This merge was created using https://github.com/rust-lang/josh-sync.
270 files changed, 2740 insertions, 2203 deletions
diff --git a/Cargo.lock b/Cargo.lock index 8b9c243879c..a8df53f3a41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,11 +158,11 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "ar_archive_writer" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01667f6f40216b9a0b2945e05fed5f1ad0ab6470e69cb9378001e37b1c0668e4" +checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b" dependencies = [ - "object 0.36.7", + "object 0.37.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 2c5044f6a35..67c7a9d67ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,33 +59,6 @@ exclude = [ "obj", ] -[workspace.dependencies] -# tidy-alphabetical-start -bitflags = "2.9.3" -derive-where = "1.6.0" -either = "1.15.0" -indexmap = "2.10.0" -itertools = "0.12.1" -# FIXME: Remove this pin once this rustix issue is resolved -# https://github.com/bytecodealliance/rustix/issues/1496 -libc = "=0.2.174" -measureme = "12.0.3" -memchr = "2.7.5" -odht = { version = "0.3.1", features = ["nightly"] } -polonius-engine = "0.13.0" -proc-macro2 = "1.0.101" -quote = "1.0.40" -rustc-demangle = "0.1.26" -rustc-hash = "2.1.1" -rustc-literal-escaper = "0.0.5" -rustc_apfloat = "0.2.3" -scoped-tls = "1.0.1" -serde_json = "1.0.142" -tempfile = "3.20.0" -thin-vec = "0.2.14" -tracing = "0.1.37" -# tidy-alphabetical-end - [profile.release.package.rustc_thread_pool] # The rustc fork of Rayon has deadlock detection code which intermittently # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227) diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml index 3de6d186b8a..83d96d8d04d 100644 --- a/compiler/rustc_abi/Cargo.toml +++ b/compiler/rustc_abi/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.4.1" rand = { version = "0.9.0", default-features = false, optional = true } rand_xoshiro = { version = "0.7.0", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } @@ -15,7 +15,7 @@ rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 41d744e1946..e3b2b1eff72 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -6,6 +6,8 @@ use std::hash::{Hash, Hasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable}; +#[cfg(feature = "nightly")] +use rustc_span::Symbol; use crate::AbiFromStrErr; @@ -226,6 +228,13 @@ impl StableOrd for ExternAbi { #[cfg(feature = "nightly")] rustc_error_messages::into_diag_arg_using_display!(ExternAbi); +#[cfg(feature = "nightly")] +pub enum CVariadicStatus { + NotSupported, + Stable, + Unstable { feature: Symbol }, +} + impl ExternAbi { /// An ABI "like Rust" /// @@ -238,23 +247,33 @@ impl ExternAbi { matches!(self, Rust | RustCall | RustCold) } - pub fn supports_varargs(self) -> bool { + /// Returns whether the ABI supports C variadics. This only controls whether we allow *imports* + /// of such functions via `extern` blocks; there's a separate check during AST construction + /// guarding *definitions* of variadic functions. + #[cfg(feature = "nightly")] + pub fn supports_c_variadic(self) -> CVariadicStatus { // * C and Cdecl obviously support varargs. // * C can be based on Aapcs, SysV64 or Win64, so they must support varargs. // * EfiApi is based on Win64 or C, so it also supports it. + // * System automatically falls back to C when used with variadics, therefore supports it. // // * Stdcall does not, because it would be impossible for the callee to clean // up the arguments. (callee doesn't know how many arguments are there) // * Same for Fastcall, Vectorcall and Thiscall. // * Other calling conventions are related to hardware or the compiler itself. + // + // All of the supported ones must have a test in `tests/codegen/cffi/c-variadic-ffi.rs`. match self { Self::C { .. } | Self::Cdecl { .. } | Self::Aapcs { .. } | Self::Win64 { .. } | Self::SysV64 { .. } - | Self::EfiApi => true, - _ => false, + | Self::EfiApi => CVariadicStatus::Stable, + Self::System { .. } => { + CVariadicStatus::Unstable { feature: rustc_span::sym::extern_system_varargs } + } + _ => CVariadicStatus::NotSupported, } } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index a1a0de5aaf8..369874521e5 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -63,6 +63,8 @@ mod tests; pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; +#[cfg(feature = "nightly")] +pub use extern_abi::CVariadicStatus; pub use extern_abi::{ExternAbi, all_names}; #[cfg(feature = "nightly")] pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml index 7f948a65220..155e14a3796 100644 --- a/compiler/rustc_ast/Cargo.toml +++ b/compiler/rustc_ast/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -memchr.workspace = true -rustc-literal-escaper.workspace = true +bitflags = "2.4.1" +memchr = "2.7.4" +rustc-literal-escaper = "0.0.5" rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } @@ -15,6 +15,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index de3e0e0c87f..802a6fa3249 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -937,7 +937,7 @@ pub enum PatKind { #[derive(Clone, Copy, Encodable, Decodable, Debug, PartialEq, Walkable)] pub enum PatFieldsRest { /// `module::StructName { field, ..}` - Rest, + Rest(Span), /// `module::StructName { field, syntax error }` Recovered(ErrorGuaranteed), /// `module::StructName { field }` @@ -4051,8 +4051,8 @@ mod size_asserts { static_assert_size!(Local, 96); static_assert_size!(MetaItemLit, 40); static_assert_size!(Param, 40); - static_assert_size!(Pat, 72); - static_assert_size!(PatKind, 48); + static_assert_size!(Pat, 80); + static_assert_size!(PatKind, 56); static_assert_size!(Path, 24); static_assert_size!(PathSegment, 24); static_assert_size!(Stmt, 32); diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 317742a3bb8..6ac258155fe 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -24,6 +24,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index cbd17d66b75..3674814b796 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1434,10 +1434,10 @@ impl<'hir> LoweringContext<'_, 'hir> { self.dcx().emit_err(FunctionalRecordUpdateDestructuringAssignment { span: e.span, }); - true + Some(self.lower_span(e.span)) } - StructRest::Rest(_) => true, - StructRest::None => false, + StructRest::Rest(span) => Some(self.lower_span(*span)), + StructRest::None => None, }; let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted); return self.pat_without_dbm(lhs.span, struct_pat); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 70595391b85..72f20a95ff0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2028,7 +2028,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ( hir::ParamName::Plain(self.lower_ident(param.ident)), - hir::GenericParamKind::Const { ty, default, synthetic: false }, + hir::GenericParamKind::Const { ty, default }, ) } } @@ -2508,7 +2508,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fields: &'hir [hir::PatField<'hir>], ) -> &'hir hir::Pat<'hir> { let qpath = hir::QPath::LangItem(lang_item, self.lower_span(span)); - self.pat(span, hir::PatKind::Struct(qpath, fields, false)) + self.pat(span, hir::PatKind::Struct(qpath, fields, None)) } fn pat_ident(&mut self, span: Span, ident: Ident) -> (&'hir hir::Pat<'hir>, HirId) { diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index b8f86247875..ed159f37051 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -106,10 +106,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { break hir::PatKind::Struct( qpath, fs, - matches!( - etc, - ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) - ), + match etc { + ast::PatFieldsRest::Rest(sp) => Some(self.lower_span(*sp)), + ast::PatFieldsRest::Recovered(_) => Some(Span::default()), + _ => None, + }, ); } PatKind::Tuple(pats) => { diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 6d2bcbed22b..3e04f8b11ec 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } @@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -thin-vec.workspace = true +thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a95f1443968..e5f1fcdc4b4 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -57,7 +57,7 @@ ast_passes_auto_super_lifetime = auto traits cannot have super traits or lifetim .label = {ast_passes_auto_super_lifetime} .suggestion = remove the super traits or lifetime bounds -ast_passes_bad_c_variadic = only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +ast_passes_bad_c_variadic = defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention ast_passes_body_in_extern = incorrect `{$kind}` inside `extern` block .cannot_have = cannot have a body diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index 0c7e55305b4..b704040be96 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_ast = { path = "../rustc_ast" } rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } @@ -13,5 +13,5 @@ rustc_span = { path = "../rustc_span" } [dev-dependencies] # tidy-alphabetical-start -thin-vec.workspace = true +thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a056ce3e29d..41b520b04c9 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1769,7 +1769,7 @@ impl<'a> State<'a> { }, |f| f.pat.span, ); - if let ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) = etc { + if let ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) = etc { if !fields.is_empty() { self.word_space(","); } diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 8bfde43fd33..79193f394fe 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -18,5 +18,5 @@ rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -thin-vec.workspace = true +thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 5f9dc41766b..9e7d55180a2 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either.workspace = true -itertools.workspace = true -polonius-engine.workspace = true +either = "1.5.0" +itertools = "0.12" +polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 1517a683531..5537d90e297 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -8,8 +8,8 @@ use std::str::FromStr; use polonius_engine::{Algorithm, AllFacts, Output}; use rustc_data_structures::frozen::Frozen; use rustc_index::IndexSlice; -use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options}; -use rustc_middle::mir::{Body, PassWhere, Promoted, create_dump_file, dump_enabled, dump_mir}; +use rustc_middle::mir::pretty::PrettyPrintMirOptions; +use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::move_paths::MoveData; @@ -68,7 +68,9 @@ pub(crate) fn replace_regions_in_mir<'tcx>( // Replace all remaining regions with fresh inference variables. renumber::renumber_mir(infcx, body, promoted); - dump_mir(infcx.tcx, false, "renumber", &0, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(infcx.tcx, "renumber", body) { + dumper.dump_mir(body); + } universal_regions } @@ -207,9 +209,7 @@ pub(super) fn dump_nll_mir<'tcx>( borrow_set: &BorrowSet<'tcx>, ) { let tcx = infcx.tcx; - if !dump_enabled(tcx, "nll", body.source.def_id()) { - return; - } + let Some(dumper) = MirDumper::new(tcx, "nll", body) else { return }; // We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in // #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example, @@ -220,27 +220,24 @@ pub(super) fn dump_nll_mir<'tcx>( MirIncludeSpans::On | MirIncludeSpans::Nll ), }; - dump_mir_with_options( - tcx, - false, - "nll", - &0, - body, - |pass_where, out| { - emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out) - }, - options, - ); + + let extra_data = &|pass_where, out: &mut dyn std::io::Write| { + emit_nll_mir(tcx, regioncx, closure_region_requirements, borrow_set, pass_where, out) + }; + + let dumper = dumper.set_extra_data(extra_data).set_options(options); + + dumper.dump_mir(body); // Also dump the region constraint graph as a graphviz file. let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "regioncx.all.dot", false, "nll", &0, body)?; + let mut file = dumper.create_dump_file("regioncx.all.dot", body)?; regioncx.dump_graphviz_raw_constraints(tcx, &mut file)?; }; // Also dump the region constraint SCC graph as a graphviz file. let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "regioncx.scc.dot", false, "nll", &0, body)?; + let mut file = dumper.create_dump_file("regioncx.scc.dot", body)?; regioncx.dump_graphviz_scc_constraints(tcx, &mut file)?; }; } diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 6b13b5ad081..62f9ae17347 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -2,9 +2,7 @@ use std::io; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_index::IndexVec; -use rustc_middle::mir::pretty::{ - PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, -}; +use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; @@ -33,22 +31,41 @@ pub(crate) fn dump_polonius_mir<'tcx>( return; } - if !dump_enabled(tcx, "polonius", body.source.def_id()) { - return; - } + let Some(dumper) = MirDumper::new(tcx, "polonius", body) else { return }; let polonius_diagnostics = polonius_diagnostics.expect("missing diagnostics context with `-Zpolonius=next`"); + let extra_data = &|pass_where, out: &mut dyn io::Write| { + emit_polonius_mir( + tcx, + regioncx, + closure_region_requirements, + borrow_set, + &polonius_diagnostics.localized_outlives_constraints, + pass_where, + out, + ) + }; + // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z + // mir-include-spans` on the CLI still has priority. + let options = PrettyPrintMirOptions { + include_extra_comments: matches!( + tcx.sess.opts.unstable_opts.mir_include_spans, + MirIncludeSpans::On | MirIncludeSpans::Nll + ), + }; + + let dumper = dumper.set_extra_data(extra_data).set_options(options); + let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?; + let mut file = dumper.create_dump_file("html", body)?; emit_polonius_dump( - tcx, + &dumper, body, regioncx, borrow_set, &polonius_diagnostics.localized_outlives_constraints, - closure_region_requirements, &mut file, )?; }; @@ -61,12 +78,11 @@ pub(crate) fn dump_polonius_mir<'tcx>( /// - a mermaid graph of the NLL regions and the constraints between them /// - a mermaid graph of the NLL SCCs and the constraints between them fn emit_polonius_dump<'tcx>( - tcx: TyCtxt<'tcx>, + dumper: &MirDumper<'_, '_, 'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, borrow_set: &BorrowSet<'tcx>, localized_outlives_constraints: &LocalizedOutlivesConstraintSet, - closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, out: &mut dyn io::Write, ) -> io::Result<()> { // Prepare the HTML dump file prologue. @@ -79,15 +95,7 @@ fn emit_polonius_dump<'tcx>( writeln!(out, "<div>")?; writeln!(out, "Raw MIR dump")?; writeln!(out, "<pre><code>")?; - emit_html_mir( - tcx, - body, - regioncx, - borrow_set, - &localized_outlives_constraints, - closure_region_requirements, - out, - )?; + emit_html_mir(dumper, body, out)?; writeln!(out, "</code></pre>")?; writeln!(out, "</div>")?; @@ -116,7 +124,7 @@ fn emit_polonius_dump<'tcx>( writeln!(out, "<div>")?; writeln!(out, "NLL regions")?; writeln!(out, "<pre class='mermaid'>")?; - emit_mermaid_nll_regions(tcx, regioncx, out)?; + emit_mermaid_nll_regions(dumper.tcx(), regioncx, out)?; writeln!(out, "</pre>")?; writeln!(out, "</div>")?; @@ -124,7 +132,7 @@ fn emit_polonius_dump<'tcx>( writeln!(out, "<div>")?; writeln!(out, "NLL SCCs")?; writeln!(out, "<pre class='mermaid'>")?; - emit_mermaid_nll_sccs(tcx, regioncx, out)?; + emit_mermaid_nll_sccs(dumper.tcx(), regioncx, out)?; writeln!(out, "</pre>")?; writeln!(out, "</div>")?; @@ -149,45 +157,14 @@ fn emit_polonius_dump<'tcx>( /// Emits the polonius MIR, as escaped HTML. fn emit_html_mir<'tcx>( - tcx: TyCtxt<'tcx>, + dumper: &MirDumper<'_, '_, 'tcx>, body: &Body<'tcx>, - regioncx: &RegionInferenceContext<'tcx>, - borrow_set: &BorrowSet<'tcx>, - localized_outlives_constraints: &LocalizedOutlivesConstraintSet, - closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, out: &mut dyn io::Write, ) -> io::Result<()> { // Buffer the regular MIR dump to be able to escape it. let mut buffer = Vec::new(); - // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z - // mir-include-spans` on the CLI still has priority. - let options = PrettyPrintMirOptions { - include_extra_comments: matches!( - tcx.sess.opts.unstable_opts.mir_include_spans, - MirIncludeSpans::On | MirIncludeSpans::Nll - ), - }; - - dump_mir_to_writer( - tcx, - "polonius", - &0, - body, - &mut buffer, - |pass_where, out| { - emit_polonius_mir( - tcx, - regioncx, - closure_region_requirements, - borrow_set, - localized_outlives_constraints, - pass_where, - out, - ) - }, - options, - )?; + dumper.dump_mir_to_writer(body, &mut buffer)?; // Escape the handful of characters that need it. We don't need to be particularly efficient: // we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8. diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 9ca44d67150..e56b9e641a1 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -30,6 +30,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index bc0a0f034b2..3a28dd7e73c 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -44,9 +44,8 @@ pub(crate) fn codegen_fn<'tcx>( let _mir_guard = crate::PrintOnPanic(|| { let mut buf = Vec::new(); with_no_trimmed_paths!({ - use rustc_middle::mir::pretty; - let options = pretty::PrettyPrintMirOptions::from_cli(tcx); - pretty::write_mir_fn(tcx, mir, &mut |_, _| Ok(()), &mut buf, options).unwrap(); + let writer = pretty::MirWriter::new(tcx); + writer.write_mir_fn(mir, &mut buf).unwrap(); }); String::from_utf8_lossy(&buf).into_owned() }); diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index b04310f3d54..2d11628250c 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -8,15 +8,15 @@ test = false [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.4.1" # To avoid duplicate dependencies, this should match the version of gimli used # by `rustc_codegen_ssa` via its `thorin-dwp` dependency. gimli = "0.31" -itertools.workspace = true -libc.workspace = true -measureme.workspace = true +itertools = "0.12" +libc = "0.2" +measureme = "12.0.1" object = { version = "0.37.0", default-features = false, features = ["std", "read"] } -rustc-demangle.workspace = true +rustc-demangle = "0.1.21" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } @@ -38,9 +38,9 @@ rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } serde = { version = "1", features = ["derive"] } -serde_json.workspace = true +serde_json = "1" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 7a340ae83f3..f9dc48e3aba 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -26,6 +26,7 @@ static LLVM_OBJECT_READER: ObjectReader = ObjectReader { get_symbols: get_llvm_object_symbols, is_64_bit_object_file: llvm_is_64_bit_object_file, is_ec_object_file: llvm_is_ec_object_file, + is_any_arm64_coff: llvm_is_any_arm64_coff, get_xcoff_member_alignment: DEFAULT_OBJECT_READER.get_xcoff_member_alignment, }; @@ -95,3 +96,7 @@ fn llvm_is_64_bit_object_file(buf: &[u8]) -> bool { fn llvm_is_ec_object_file(buf: &[u8]) -> bool { unsafe { llvm::LLVMRustIsECObject(buf.as_ptr(), buf.len()) } } + +fn llvm_is_any_arm64_coff(buf: &[u8]) -> bool { + unsafe { llvm::LLVMRustIsAnyArm64Coff(buf.as_ptr(), buf.len()) } +} diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ba590851dbd..b66fc157b3c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2686,6 +2686,8 @@ unsafe extern "C" { pub(crate) fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool; + pub(crate) fn LLVMRustIsAnyArm64Coff(buf_ptr: *const u8, buf_len: usize) -> bool; + pub(crate) fn LLVMRustSetNoSanitizeAddress(Global: &Value); pub(crate) fn LLVMRustSetNoSanitizeHWAddress(Global: &Value); } diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index ce079f3cb0a..7eb5d302058 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -28,9 +28,12 @@ fn round_pointer_up_to_alignment<'ll>( align: Align, ptr_ty: &'ll Type, ) -> &'ll Value { - let mut ptr_as_int = bx.ptrtoint(addr, bx.cx().type_isize()); - ptr_as_int = round_up_to_alignment(bx, ptr_as_int, align); - bx.inttoptr(ptr_as_int, ptr_ty) + let ptr = bx.inbounds_ptradd(addr, bx.const_i32(align.bytes() as i32 - 1)); + bx.call_intrinsic( + "llvm.ptrmask", + &[ptr_ty, bx.type_i32()], + &[ptr, bx.const_int(bx.isize_ty, -(align.bytes() as isize) as i64)], + ) } fn emit_direct_ptr_va_arg<'ll, 'tcx>( diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 57e1fee2c0a..2dfbc581643 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -5,13 +5,13 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -ar_archive_writer = "0.4.2" -bitflags.workspace = true +ar_archive_writer = "0.5" +bitflags = "2.4.1" bstr = "1.11.3" # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version # per crate", so if you change this, you need to also change it in `rustc_llvm`. cc = "=1.2.16" -itertools.workspace = true +itertools = "0.12" pathdiff = "0.2.0" regex = "1.4" rustc_abi = { path = "../rustc_abi" } @@ -37,18 +37,18 @@ rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -serde_json.workspace = true +serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tempfile.workspace = true -thin-vec.workspace = true +tempfile = "3.2" +thin-vec = "0.2.12" thorin-dwp = "0.9" -tracing.workspace = true +tracing = "0.1" wasm-encoder = "0.219" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] # tidy-alphabetical-start -libc.workspace = true +libc = "0.2.50" # tidy-alphabetical-end [dependencies.object] diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 84a56f6b0b5..cfd8ceac3a6 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -40,16 +40,18 @@ pub struct ImportLibraryItem { pub is_data: bool, } -impl From<ImportLibraryItem> for COFFShortExport { - fn from(item: ImportLibraryItem) -> Self { +impl ImportLibraryItem { + fn into_coff_short_export(self, sess: &Session) -> COFFShortExport { + let import_name = (sess.target.arch == "arm64ec").then(|| self.name.clone()); COFFShortExport { - name: item.name, + name: self.name, ext_name: None, - symbol_name: item.symbol_name, - alias_target: None, - ordinal: item.ordinal.unwrap_or(0), - noname: item.ordinal.is_some(), - data: item.is_data, + symbol_name: self.symbol_name, + import_name, + export_as: None, + ordinal: self.ordinal.unwrap_or(0), + noname: self.ordinal.is_some(), + data: self.is_data, private: false, constant: false, } @@ -113,7 +115,8 @@ pub trait ArchiveBuilderBuilder { .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }), }; - let exports = items.into_iter().map(Into::into).collect::<Vec<_>>(); + let exports = + items.into_iter().map(|item| item.into_coff_short_export(sess)).collect::<Vec<_>>(); let machine = match &*sess.target.arch { "x86_64" => MachineTypes::AMD64, "x86" => MachineTypes::I386, @@ -134,6 +137,7 @@ pub trait ArchiveBuilderBuilder { // when linking a rust staticlib using `/WHOLEARCHIVE`. // See #129020 true, + &[], ) { sess.dcx() .emit_fatal(ErrorCreatingImportLibrary { lib_name, error: error.to_string() }); @@ -527,7 +531,7 @@ impl<'a> ArArchiveBuilder<'a> { &entries, archive_kind, false, - /* is_ec = */ self.sess.target.arch == "arm64ec", + /* is_ec = */ Some(self.sess.target.arch == "arm64ec"), )?; archive_tmpfile.flush()?; drop(archive_tmpfile); diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index c3dc3e42b83..5f6976f5d00 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -519,6 +519,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.val.llval); + + // Explicitly end the lifetime of the `va_list`, this matters for LLVM. + bx.lifetime_end(va_list.val.llval, va_list.layout.size); } _ => bug!("C-variadic function must have a `VaList` place"), } diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index acf19b0f2fc..51dcee8d882 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either.workspace = true +either = "1" rustc_abi = { path = "../rustc_abi" } -rustc_apfloat.workspace = true +rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -22,5 +22,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 852fc11350b..c8296e05f6b 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -6,15 +6,15 @@ edition = "2024" [dependencies] # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } -bitflags.workspace = true -either.workspace = true +bitflags = "2.4.1" +either = "1.0" elsa = "1.11.0" ena = "0.14.3" -indexmap.workspace = true +indexmap = "2.4.0" jobserver_crate = { version = "0.1.28", package = "jobserver" } -measureme.workspace = true +measureme = "12.0.1" parking_lot = "0.12" -rustc-hash.workspace = true +rustc-hash = "2.0.0" rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } rustc_arena = { path = "../rustc_arena" } rustc_graphviz = { path = "../rustc_graphviz" } @@ -25,9 +25,9 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] } stacker = "0.1.17" -tempfile.workspace = true -thin-vec.workspace = true -tracing.workspace = true +tempfile = "3.2" +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end [dependencies.hashbrown] @@ -47,7 +47,7 @@ features = [ [target.'cfg(unix)'.dependencies] # tidy-alphabetical-start -libc.workspace = true +libc = "0.2" # tidy-alphabetical-end [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 196c8aa3547..ae1dbd2cf51 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -49,14 +49,14 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } -serde_json.workspace = true +serde_json = "1.0.59" shlex = "1.0" -tracing.workspace = true +tracing = { version = "0.1.35" } # tidy-alphabetical-end [target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies] # tidy-alphabetical-start -libc.workspace = true +libc = "0.2" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 7d2dc20e136..db22e065907 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -17,6 +17,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } -tracing.workspace = true +tracing = "0.1" unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 67a17ce88fa..7912b8e6098 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -21,10 +21,10 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0.59" termcolor = "1.2.0" termize = "0.2" -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index 9bb7143af51..f897833d85c 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -29,6 +29,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 174844d6ad6..e4e4866b64c 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -556,7 +556,12 @@ fn metavar_expr_concat<'tx>( }; match &named_matches[*curr_idx] { // FIXME(c410-f3r) Nested repetitions are unimplemented - MatchedSeq(_) => unimplemented!(), + MatchedSeq(_) => { + return Err(dcx.struct_span_err( + ident.span, + "nested repetitions with `${concat(...)}` metavariable expressions are not yet supported", + )); + } MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?, } } diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml index b58f2375852..a4746ac455c 100644 --- a/compiler/rustc_feature/Cargo.toml +++ b/compiler/rustc_feature/Cargo.toml @@ -9,5 +9,5 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_span = { path = "../rustc_span" } serde = { version = "1.0.125", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0.59" # tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 9fe55216f93..6af4cfb0e56 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -203,6 +203,9 @@ declare_features! ( (accepted, expr_fragment_specifier_2024, "1.83.0", Some(123742)), /// Allows arbitrary expressions in key-value attributes at parse time. (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), + /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions + /// for functions with varargs. + (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 92b435b4b01..573e9aab055 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -492,9 +492,6 @@ declare_features! ( (incomplete, explicit_tail_calls, "1.72.0", Some(112788)), /// Allows using `#[export_stable]` which indicates that an item is exportable. (incomplete, export_stable, "1.88.0", Some(139939)), - /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions - /// for functions with varargs. - (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)), /// Allows using `system` as a calling convention with varargs. (unstable, extern_system_varargs, "1.86.0", Some(136946)), /// Allows defining `extern type`s. diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml index 60afd9aca87..d7ef4280aef 100644 --- a/compiler/rustc_fluent_macro/Cargo.toml +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -11,8 +11,8 @@ proc-macro = true annotate-snippets = "0.11" fluent-bundle = "0.16" fluent-syntax = "0.12" -proc-macro2.workspace = true -quote.workspace = true +proc-macro2 = "1" +quote = "1" syn = { version = "2", features = ["full"] } unic-langid = { version = "0.9.0", features = ["macros"] } # tidy-alphabetical-end diff --git a/compiler/rustc_fs_util/Cargo.toml b/compiler/rustc_fs_util/Cargo.toml index 37970e81fea..90a6acade8b 100644 --- a/compiler/rustc_fs_util/Cargo.toml +++ b/compiler/rustc_fs_util/Cargo.toml @@ -5,5 +5,5 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -tempfile.workspace = true +tempfile = "3.7.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index e74fcfe7455..1008a3e787d 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -odht.workspace = true +bitflags = "2.9.1" +odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -21,6 +21,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e397c286de2..ae03121e5f7 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -784,7 +784,6 @@ pub enum GenericParamKind<'hir> { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param default: Option<&'hir ConstArg<'hir>>, - synthetic: bool, }, } @@ -1884,8 +1883,8 @@ pub enum PatKind<'hir> { Binding(BindingMode, HirId, Ident, Option<&'hir Pat<'hir>>), /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`). - /// The `bool` is `true` in the presence of a `..`. - Struct(QPath<'hir>, &'hir [PatField<'hir>], bool), + /// The `Option` contains the span of a possible `..`. + Struct(QPath<'hir>, &'hir [PatField<'hir>], Option<Span>), /// A tuple struct/variant pattern `Variant(x, y, .., z)`. /// If the `..` pattern fragment is present, then `DotDotPos` denotes its position. @@ -4979,8 +4978,8 @@ mod size_asserts { static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 72); static_assert_size!(Param<'_>, 32); - static_assert_size!(Pat<'_>, 72); - static_assert_size!(PatKind<'_>, 48); + static_assert_size!(Pat<'_>, 80); + static_assert_size!(PatKind<'_>, 56); static_assert_size!(Path<'_>, 40); static_assert_size!(PathSegment<'_>, 48); static_assert_size!(QPath<'_>, 24); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 9b2f8ae75fa..25a7ae239f3 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1085,7 +1085,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>( GenericParamKind::Type { ref default, .. } => { visit_opt!(visitor, visit_ty_unambig, default) } - GenericParamKind::Const { ref ty, ref default, synthetic: _ } => { + GenericParamKind::Const { ref ty, ref default } => { try_visit!(visitor.visit_ty_unambig(ty)); if let Some(default) = default { try_visit!(visitor.visit_const_param_default(*hir_id, default)); diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index bb86beb2251..e5017794d8f 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -9,7 +9,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -29,5 +29,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index eccb88a938f..08b344638dd 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -978,7 +978,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().fn_sig(def_id); let item = tcx.hir_foreign_item(item); let hir::ForeignItemKind::Fn(sig, ..) = item.kind else { bug!() }; - require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span); + check_c_variadic_abi(tcx, sig.decl, abi, item.span); } DefKind::Static { .. } => { tcx.ensure_ok().codegen_fn_attrs(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 2e4b151d4dc..b5c0ca4727c 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -98,7 +98,7 @@ use tracing::debug; use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys; use self::region::region_scope_tree; -use crate::{errors, require_c_abi_if_c_variadic}; +use crate::{check_c_variadic_abi, errors}; /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] pub(super) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ce0e51f106f..333cea23c41 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -305,7 +305,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic } } - GenericParamKind::Const { ty: _, default, synthetic } => { + GenericParamKind::Const { ty: _, default } => { if default.is_some() { match param_default_policy.expect("no policy for generic param default") { ParamDefaultPolicy::Allowed => {} @@ -316,7 +316,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } } - ty::GenericParamDefKind::Const { has_default: default.is_some(), synthetic } + ty::GenericParamDefKind::Const { has_default: default.is_some() } } }; Some(ty::GenericParamDef { @@ -523,7 +523,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector { type Result = ControlFlow<()>; fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) -> Self::Result { - if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; let res = self.visit_ty_unambig(ty); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index fc519c194bb..f5a64ede398 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -419,14 +419,7 @@ pub(crate) fn check_generic_arg_count( .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })) .count(); let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count; - let synth_const_param_count = gen_params - .own_params - .iter() - .filter(|param| { - matches!(param.kind, ty::GenericParamDefKind::Const { synthetic: true, .. }) - }) - .count(); - let named_const_param_count = param_counts.consts - synth_const_param_count; + let named_const_param_count = param_counts.consts; let infer_lifetimes = (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params(); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index c7b984d9b25..c5e079fe89a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -52,11 +52,11 @@ use rustc_trait_selection::traits::{self, FulfillmentError}; use tracing::{debug, instrument}; use crate::check::check_abi; +use crate::check_c_variadic_abi; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; -use crate::require_c_abi_if_c_variadic; /// A path segment that is semantically allowed to have generic arguments. #[derive(Debug)] @@ -2412,7 +2412,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.lower_ty(t))) } hir::TyKind::FnPtr(bf) => { - require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, hir_ty.span); + check_c_variadic_abi(tcx, bf.decl, bf.abi, hir_ty.span); Ty::new_fn_ptr( tcx, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 44a5ceed469..2562ab7542a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -90,7 +90,7 @@ mod outlives; mod variance; pub use errors::NoVariantNamed; -use rustc_abi::ExternAbi; +use rustc_abi::{CVariadicStatus, ExternAbi}; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; use rustc_hir::{self as hir}; @@ -99,7 +99,6 @@ use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_session::parse::feature_err; -use rustc_span::symbol::sym; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -108,46 +107,34 @@ use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer}; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -fn require_c_abi_if_c_variadic( - tcx: TyCtxt<'_>, - decl: &hir::FnDecl<'_>, - abi: ExternAbi, - span: Span, -) { - // ABIs which can stably use varargs - if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { +fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, span: Span) { + if !decl.c_variadic { + // Not even a variadic function. return; } - // ABIs with feature-gated stability - let extended_abi_support = tcx.features().extended_varargs_abi_support(); - let extern_system_varargs = tcx.features().extern_system_varargs(); - - // If the feature gate has been enabled, we can stop here - if extern_system_varargs && let ExternAbi::System { .. } = abi { - return; - }; - if extended_abi_support && abi.supports_varargs() { - return; - }; - - // Looks like we need to pick an error to emit. - // Is there any feature which we could have enabled to make this work? - let unstable_explain = - format!("C-variadic functions with the {abi} calling convention are unstable"); - match abi { - ExternAbi::System { .. } => { - feature_err(&tcx.sess, sym::extern_system_varargs, span, unstable_explain) + match abi.supports_c_variadic() { + CVariadicStatus::Stable => {} + CVariadicStatus::NotSupported => { + tcx.dcx() + .create_err(errors::VariadicFunctionCompatibleConvention { + span, + convention: &format!("{abi}"), + }) + .emit(); } - abi if abi.supports_varargs() => { - feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, unstable_explain) + CVariadicStatus::Unstable { feature } => { + if !tcx.features().enabled(feature) { + feature_err( + &tcx.sess, + feature, + span, + format!("C-variadic functions with the {abi} calling convention are unstable"), + ) + .emit(); + } } - _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention { - span, - convention: &format!("{abi}"), - }), } - .emit(); } /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index be5859b57c5..b9d8eed54a9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1958,12 +1958,12 @@ impl<'a> State<'a> { self.print_qpath(qpath, true); self.nbsp(); self.word("{"); - let empty = fields.is_empty() && !etc; + let empty = fields.is_empty() && etc.is_none(); if !empty { self.space(); } self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span); - if etc { + if etc.is_some() { if !fields.is_empty() { self.word_space(","); } @@ -2379,7 +2379,7 @@ impl<'a> State<'a> { self.print_type(default); } } - GenericParamKind::Const { ty, ref default, synthetic: _ } => { + GenericParamKind::Const { ty, ref default } => { self.word_space(":"); self.print_type(ty); if let Some(default) = default { diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 5af0c6134ca..f00125c3e09 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } @@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index e37ea031672..652644ad78c 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -117,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(Ambiguity(..)) => true, Err(PrivateMatch(..)) => false, Err(IllegalSizedBound { .. }) => true, - Err(BadReturnType) => false, + Err(BadReturnType) => true, Err(ErrorReported(_)) => false, } } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 87a7cd62ae5..11defc3aa03 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -962,13 +962,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip(); let cause = self.cause( span, - ObligationCauseCode::BinOp { - lhs_hir_id: lhs_expr.hir_id, - rhs_hir_id: opt_rhs_expr.map(|expr| expr.hir_id), - rhs_span: opt_rhs_expr.map(|expr| expr.span), - rhs_is_lit: opt_rhs_expr - .is_some_and(|expr| matches!(expr.kind, hir::ExprKind::Lit(_))), - output_ty: expected.only_has_type(self), + match opt_rhs_expr { + Some(rhs) => ObligationCauseCode::BinOp { + lhs_hir_id: lhs_expr.hir_id, + rhs_hir_id: rhs.hir_id, + rhs_span: rhs.span, + rhs_is_lit: matches!(rhs.kind, hir::ExprKind::Lit(_)), + output_ty: expected.only_has_type(self), + }, + None => ObligationCauseCode::UnOp { hir_id: lhs_expr.hir_id }, }, ); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7dc736e5e6b..f735c0a4160 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -605,7 +605,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, PatKind::Struct(_, fields, has_rest_pat) => match opt_path_res.unwrap() { Ok(ResolvedPat { ty, kind: ResolvedPatKind::Struct { variant } }) => self - .check_pat_struct(pat, fields, has_rest_pat, ty, variant, expected, pat_info), + .check_pat_struct( + pat, + fields, + has_rest_pat.is_some(), + ty, + variant, + expected, + pat_info, + ), Err(guar) => { let ty_err = Ty::new_error(self.tcx, guar); for field in fields { @@ -2428,7 +2436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let len = unmentioned_fields.len(); let (prefix, postfix, sp) = match fields { [] => match &pat.kind { - PatKind::Struct(path, [], false) => { + PatKind::Struct(path, [], None) => { (" { ", " }", path.span().shrink_to_hi().until(pat.span.shrink_to_hi())) } _ => return err, diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index 8d7f2eb8414..db0a5841887 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -19,6 +19,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_index_macros/Cargo.toml b/compiler/rustc_index_macros/Cargo.toml index 8593bde2615..34f3109a526 100644 --- a/compiler/rustc_index_macros/Cargo.toml +++ b/compiler/rustc_index_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2.workspace = true -quote.workspace = true +proc-macro2 = "1" +quote = "1" syn = { version = "2.0.9", features = ["full", "extra-traits"] } # tidy-alphabetical-end diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 6d97fa6af1f..08c03614884 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -18,6 +18,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 40152e78f8a..473ac5e0cea 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -46,7 +46,7 @@ rustc_thread_pool = { path = "../rustc_thread_pool" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_traits = { path = "../rustc_traits" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index bc5ef04079e..ca8c10311fb 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -41,7 +41,7 @@ use rustc_span::{ Symbol, sym, }; use rustc_target::spec::PanicStrategy; -use rustc_trait_selection::traits; +use rustc_trait_selection::{solve, traits}; use tracing::{info, instrument}; use crate::interface::Compiler; @@ -895,6 +895,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { rustc_hir_typeck::provide(providers); ty::provide(providers); traits::provide(providers); + solve::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); rustc_ty_utils::provide(providers); diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index e0019fb1821..343b81bd171 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -14,7 +14,7 @@ Rust lexer used by rustc. No stability guarantees are provided. # Note that this crate purposefully does not depend on other rustc crates [dependencies] -memchr.workspace = true +memchr = "2.7.4" unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] } unicode-xid = "0.2.0" diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 483cc3e93dc..d10b1920343 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -550,28 +550,20 @@ impl Cursor<'_> { self.eat_while(|ch| ch != '\n' && is_whitespace(ch)); let invalid_infostring = self.first() != '\n'; - let mut s = self.as_str(); let mut found = false; - let mut size = 0; - while let Some(closing) = s.find(&"-".repeat(length_opening as usize)) { - let preceding_chars_start = s[..closing].rfind("\n").map_or(0, |i| i + 1); - if s[preceding_chars_start..closing].chars().all(is_whitespace) { - // candidate found - self.bump_bytes(size + closing); - // in case like - // ---cargo - // --- blahblah - // or - // ---cargo - // ---- - // combine those stuff into this frontmatter token such that it gets detected later. - self.eat_until(b'\n'); - found = true; - break; - } else { - s = &s[closing + length_opening as usize..]; - size += closing + length_opening as usize; - } + let nl_fence_pattern = format!("\n{:-<1$}", "", length_opening as usize); + if let Some(closing) = self.as_str().find(&nl_fence_pattern) { + // candidate found + self.bump_bytes(closing + nl_fence_pattern.len()); + // in case like + // ---cargo + // --- blahblah + // or + // ---cargo + // ---- + // combine those stuff into this frontmatter token such that it gets detected later. + self.eat_until(b'\n'); + found = true; } if !found { diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index 7900e4b9ab2..7718f16984d 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -24,6 +24,6 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" unicode-security = "0.1.0" # tidy-alphabetical-end diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index e74de453be2..cd352ce3d0f 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -libc.workspace = true +libc = "0.2.73" # tidy-alphabetical-end [build-dependencies] diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index a910e78d489..fccfff65cfc 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -103,14 +103,14 @@ LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State, #define TRUE_PTR (void *)1 #define FALSE_PTR (void *)0 -extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { +bool withBufferAsSymbolicFile( + char *BufPtr, size_t BufLen, + std::function<bool(object::SymbolicFile &)> Callback) { std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); SmallString<0> SymNameBuf; auto SymName = raw_svector_ostream(SymNameBuf); - // Code starting from this line is copied from s64BitSymbolicFile in - // ArchiveWriter.cpp. // In the scenario when LLVMContext is populated SymbolicFile will contain a // reference to it, thus SymbolicFile should be destroyed first. LLVMContext Context; @@ -120,48 +120,63 @@ extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { return false; } std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); - - return Obj != nullptr ? Obj->is64Bit() : false; -} - -extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) { - std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer( - StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false); - SmallString<0> SymNameBuf; - auto SymName = raw_svector_ostream(SymNameBuf); - - // In the scenario when LLVMContext is populated SymbolicFile will contain a - // reference to it, thus SymbolicFile should be destroyed first. - LLVMContext Context; - Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = - getSymbolicFile(Buf->getMemBufferRef(), Context); - if (!ObjOrErr) { - return false; - } - std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr); - if (Obj == nullptr) { return false; } + return Callback(*Obj); +} - // Code starting from this line is copied from isECObject in - // ArchiveWriter.cpp with an extra #if to work with LLVM 17. - if (Obj->isCOFF()) - return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() != - COFF::IMAGE_FILE_MACHINE_ARM64; - - if (Obj->isCOFFImportFile()) - return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() != - COFF::IMAGE_FILE_MACHINE_ARM64; - - if (Obj->isIR()) { - Expected<std::string> TripleStr = - getBitcodeTargetTriple(Obj->getMemoryBufferRef()); - if (!TripleStr) - return false; - Triple T(*TripleStr); - return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; - } +extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) { + return withBufferAsSymbolicFile( + BufPtr, BufLen, [](object::SymbolicFile &Obj) { return Obj.is64Bit(); }); +} + +extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) { + return withBufferAsSymbolicFile( + BufPtr, BufLen, [](object::SymbolicFile &Obj) { + // Code starting from this line is copied from isECObject in + // ArchiveWriter.cpp with an extra #if to work with LLVM 17. + if (Obj.isCOFF()) + return cast<llvm::object::COFFObjectFile>(&Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; + + if (Obj.isCOFFImportFile()) + return cast<llvm::object::COFFImportFile>(&Obj)->getMachine() != + COFF::IMAGE_FILE_MACHINE_ARM64; + + if (Obj.isIR()) { + Expected<std::string> TripleStr = + getBitcodeTargetTriple(Obj.getMemoryBufferRef()); + if (!TripleStr) + return false; + Triple T(*TripleStr); + return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64; + } + + return false; + }); +} - return false; +extern "C" bool LLVMRustIsAnyArm64Coff(char *BufPtr, size_t BufLen) { + return withBufferAsSymbolicFile( + BufPtr, BufLen, [](object::SymbolicFile &Obj) { + // Code starting from this line is copied from isAnyArm64COFF in + // ArchiveWriter.cpp. + if (Obj.isCOFF()) + return COFF::isAnyArm64(cast<COFFObjectFile>(&Obj)->getMachine()); + + if (Obj.isCOFFImportFile()) + return COFF::isAnyArm64(cast<COFFImportFile>(&Obj)->getMachine()); + + if (Obj.isIR()) { + Expected<std::string> TripleStr = + getBitcodeTargetTriple(Obj.getMemoryBufferRef()); + if (!TripleStr) + return false; + Triple T(*TripleStr); + return T.isOSWindows() && T.getArch() == Triple::aarch64; + } + + return false; + }); } diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index e9d7b4723f8..c673d51a1d4 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -5,10 +5,10 @@ edition = "2024" [dependencies] # tidy-alphabetical-start +tracing = "0.1.28" tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] } tracing-tree = "0.3.1" -tracing.workspace = true # tidy-alphabetical-end [features] diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index 5add2691b88..f9d3b758359 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2.workspace = true -quote.workspace = true +proc-macro2 = "1" +quote = "1" syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a8f3dd18353..1b40d9f684e 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.4.1" libloading = "0.8.0" -odht.workspace = true +odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } @@ -30,11 +30,11 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -tempfile.workspace = true -tracing.workspace = true +tempfile = "3.7.1" +tracing = "0.1" # tidy-alphabetical-end [target.'cfg(target_os = "aix")'.dependencies] # tidy-alphabetical-start -libc.workspace = true +libc = "0.2" # tidy-alphabetical-end diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index f0832405567..fbcce16cedc 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -5,12 +5,12 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -either.workspace = true +bitflags = "2.4.1" +either = "1.5.0" gsgdt = "0.1.2" -polonius-engine.workspace = true +polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } -rustc_apfloat.workspace = true +rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_ir = { path = "../rustc_ast_ir" } @@ -34,8 +34,8 @@ rustc_target = { path = "../rustc_target" } rustc_thread_pool = { path = "../rustc_thread_pool" } rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 4b6e38cd52d..52fbe19c9f2 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -80,6 +80,7 @@ macro_rules! arena_types { rustc_middle::infer::canonical::Canonical<'tcx, rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>> >, + [] inspect_probe: rustc_middle::traits::solve::inspect::Probe<rustc_middle::ty::TyCtxt<'tcx>>, [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities, [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, [] dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index c977e5329c2..da2245b12d2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -62,9 +62,7 @@ pub use terminator::*; pub use self::generic_graph::graphviz_safe_def_name; pub use self::graphviz::write_mir_graphviz; -pub use self::pretty::{ - PassWhere, create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, -}; +pub use self::pretty::{MirDumper, PassWhere, display_allocation, write_mir_pretty}; /// Types for locals pub type LocalDecls<'tcx> = IndexSlice<Local, LocalDecl<'tcx>>; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 128ae8549f7..a7d99f513a1 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -44,7 +44,7 @@ pub enum PassWhere { } /// Cosmetic options for pretty-printing the MIR contents, gathered from the CLI. Each pass can -/// override these when dumping its own specific MIR information with [`dump_mir_with_options`]. +/// override these when dumping its own specific MIR information with `dump_mir`. #[derive(Copy, Clone)] pub struct PrettyPrintMirOptions { /// Whether to include extra comments, like span info. From `-Z mir-include-spans`. @@ -58,277 +58,253 @@ impl PrettyPrintMirOptions { } } -/// If the session is properly configured, dumps a human-readable representation of the MIR (with -/// default pretty-printing options) into: -/// -/// ```text -/// rustc.node<node_id>.<pass_num>.<pass_name>.<disambiguator> -/// ``` -/// -/// Output from this function is controlled by passing `-Z dump-mir=<filter>`, -/// where `<filter>` takes the following forms: -/// -/// - `all` -- dump MIR for all fns, all passes, all everything -/// - a filter defined by a set of substrings combined with `&` and `|` -/// (`&` has higher precedence). At least one of the `|`-separated groups -/// must match; an `|`-separated group matches if all of its `&`-separated -/// substrings are matched. -/// -/// Example: -/// -/// - `nll` == match if `nll` appears in the name -/// - `foo & nll` == match if `foo` and `nll` both appear in the name -/// - `foo & nll | typeck` == match if `foo` and `nll` both appear in the name -/// or `typeck` appears in the name. -/// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name -/// or `typeck` and `bar` both appear in the name. -#[inline] -pub fn dump_mir<'tcx, F>( - tcx: TyCtxt<'tcx>, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, - extra_data: F, -) where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - dump_mir_with_options( - tcx, - pass_num, - pass_name, - disambiguator, - body, - extra_data, - PrettyPrintMirOptions::from_cli(tcx), - ); +/// Manages MIR dumping, which is MIR writing done to a file with a specific name. In particular, +/// it makes it impossible to dump MIR to one of these files when it hasn't been requested from the +/// command line. Layered on top of `MirWriter`, which does the actual writing. +pub struct MirDumper<'dis, 'de, 'tcx> { + show_pass_num: bool, + pass_name: &'static str, + disambiguator: &'dis dyn Display, + writer: MirWriter<'de, 'tcx>, } -/// If the session is properly configured, dumps a human-readable representation of the MIR, with -/// the given [pretty-printing options][PrettyPrintMirOptions]. -/// -/// See [`dump_mir`] for more details. -/// -#[inline] -pub fn dump_mir_with_options<'tcx, F>( - tcx: TyCtxt<'tcx>, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, - extra_data: F, - options: PrettyPrintMirOptions, -) where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - if !dump_enabled(tcx, pass_name, body.source.def_id()) { - return; - } - - dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data, options); -} +impl<'dis, 'de, 'tcx> MirDumper<'dis, 'de, 'tcx> { + // If dumping should be performed (e.g. because it was requested on the + // CLI), returns a `MirDumper` with default values for the following fields: + // - `show_pass_num`: `false` + // - `disambiguator`: `&0` + // - `writer.extra_data`: a no-op + // - `writer.options`: default options derived from CLI flags + pub fn new(tcx: TyCtxt<'tcx>, pass_name: &'static str, body: &Body<'tcx>) -> Option<Self> { + let dump_enabled = if let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir { + // see notes on #41697 below + let node_path = + ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); + filters.split('|').any(|or_filter| { + or_filter.split('&').all(|and_filter| { + let and_filter_trimmed = and_filter.trim(); + and_filter_trimmed == "all" + || pass_name.contains(and_filter_trimmed) + || node_path.contains(and_filter_trimmed) + }) + }) + } else { + false + }; -pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool { - let Some(ref filters) = tcx.sess.opts.unstable_opts.dump_mir else { - return false; - }; - // see notes on #41697 below - let node_path = ty::print::with_forced_impl_filename_line!(tcx.def_path_str(def_id)); - filters.split('|').any(|or_filter| { - or_filter.split('&').all(|and_filter| { - let and_filter_trimmed = and_filter.trim(); - and_filter_trimmed == "all" - || pass_name.contains(and_filter_trimmed) - || node_path.contains(and_filter_trimmed) + dump_enabled.then_some(MirDumper { + show_pass_num: false, + pass_name, + disambiguator: &0, + writer: MirWriter::new(tcx), }) - }) -} + } -// #41697 -- we use `with_forced_impl_filename_line()` because -// `def_path_str()` would otherwise trigger `type_of`, and this can -// run while we are already attempting to evaluate `type_of`. + pub fn tcx(&self) -> TyCtxt<'tcx> { + self.writer.tcx + } -/// Most use-cases of dumping MIR should use the [dump_mir] entrypoint instead, which will also -/// check if dumping MIR is enabled, and if this body matches the filters passed on the CLI. -/// -/// That being said, if the above requirements have been validated already, this function is where -/// most of the MIR dumping occurs, if one needs to export it to a file they have created with -/// [create_dump_file], rather than to a new file created as part of [dump_mir], or to stdout/stderr -/// for debugging purposes. -pub fn dump_mir_to_writer<'tcx, F>( - tcx: TyCtxt<'tcx>, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, - w: &mut dyn io::Write, - mut extra_data: F, - options: PrettyPrintMirOptions, -) -> io::Result<()> -where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - // see notes on #41697 above - let def_path = - ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); - // ignore-tidy-odd-backticks the literal below is fine - write!(w, "// MIR for `{def_path}")?; - match body.source.promoted { - None => write!(w, "`")?, - Some(promoted) => write!(w, "::{promoted:?}`")?, - } - writeln!(w, " {disambiguator} {pass_name}")?; - if let Some(ref layout) = body.coroutine_layout_raw() { - writeln!(w, "/* coroutine_layout = {layout:#?} */")?; + #[must_use] + pub fn set_show_pass_num(mut self) -> Self { + self.show_pass_num = true; + self } - writeln!(w)?; - extra_data(PassWhere::BeforeCFG, w)?; - write_user_type_annotations(tcx, body, w)?; - write_mir_fn(tcx, body, &mut extra_data, w, options)?; - extra_data(PassWhere::AfterCFG, w) -} -fn dump_matched_mir_node<'tcx, F>( - tcx: TyCtxt<'tcx>, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, - extra_data: F, - options: PrettyPrintMirOptions, -) where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body)?; - dump_mir_to_writer(tcx, pass_name, disambiguator, body, &mut file, extra_data, options)?; - }; + #[must_use] + pub fn set_disambiguator(mut self, disambiguator: &'dis dyn Display) -> Self { + self.disambiguator = disambiguator; + self + } - if tcx.sess.opts.unstable_opts.dump_mir_graphviz { - let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body)?; - write_mir_fn_graphviz(tcx, body, false, &mut file)?; - }; + #[must_use] + pub fn set_extra_data( + mut self, + extra_data: &'de dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, + ) -> Self { + self.writer.extra_data = extra_data; + self } -} -/// Returns the path to the filename where we should dump a given MIR. -/// Also used by other bits of code (e.g., NLL inference) that dump -/// graphviz data or other things. -fn dump_path<'tcx>( - tcx: TyCtxt<'tcx>, - extension: &str, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, -) -> PathBuf { - let source = body.source; - let promotion_id = match source.promoted { - Some(id) => format!("-{id:?}"), - None => String::new(), - }; + #[must_use] + pub fn set_options(mut self, options: PrettyPrintMirOptions) -> Self { + self.writer.options = options; + self + } - let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { - String::new() - } else if pass_num { - let (dialect_index, phase_index) = body.phase.index(); - format!(".{}-{}-{:03}", dialect_index, phase_index, body.pass_count) - } else { - ".-------".to_string() - }; + /// If the session is properly configured, dumps a human-readable representation of the MIR + /// (with default pretty-printing options) into: + /// + /// ```text + /// rustc.node<node_id>.<pass_num>.<pass_name>.<disambiguator> + /// ``` + /// + /// Output from this function is controlled by passing `-Z dump-mir=<filter>`, + /// where `<filter>` takes the following forms: + /// + /// - `all` -- dump MIR for all fns, all passes, all everything + /// - a filter defined by a set of substrings combined with `&` and `|` + /// (`&` has higher precedence). At least one of the `|`-separated groups + /// must match; an `|`-separated group matches if all of its `&`-separated + /// substrings are matched. + /// + /// Example: + /// + /// - `nll` == match if `nll` appears in the name + /// - `foo & nll` == match if `foo` and `nll` both appear in the name + /// - `foo & nll | typeck` == match if `foo` and `nll` both appear in the name + /// or `typeck` appears in the name. + /// - `foo & nll | bar & typeck` == match if `foo` and `nll` both appear in the name + /// or `typeck` and `bar` both appear in the name. + pub fn dump_mir(&self, body: &Body<'tcx>) { + let _: io::Result<()> = try { + let mut file = self.create_dump_file("mir", body)?; + self.dump_mir_to_writer(body, &mut file)?; + }; - let crate_name = tcx.crate_name(source.def_id().krate); - let item_name = tcx.def_path(source.def_id()).to_filename_friendly_no_crate(); - // All drop shims have the same DefId, so we have to add the type - // to get unique file names. - let shim_disambiguator = match source.instance { - ty::InstanceKind::DropGlue(_, Some(ty)) => { - // Unfortunately, pretty-printed typed are not very filename-friendly. - // We dome some filtering. - let mut s = ".".to_owned(); - s.extend(ty.to_string().chars().filter_map(|c| match c { - ' ' => None, - ':' | '<' | '>' => Some('_'), - c => Some(c), - })); - s - } - ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => { - let mut s = ".".to_owned(); - s.extend(ty.to_string().chars().filter_map(|c| match c { - ' ' => None, - ':' | '<' | '>' => Some('_'), - c => Some(c), - })); - s - } - ty::InstanceKind::AsyncDropGlue(_, ty) => { - let ty::Coroutine(_, args) = ty.kind() else { - bug!(); + if self.tcx().sess.opts.unstable_opts.dump_mir_graphviz { + let _: io::Result<()> = try { + let mut file = self.create_dump_file("dot", body)?; + write_mir_fn_graphviz(self.tcx(), body, false, &mut file)?; }; - let ty = args.first().unwrap().expect_ty(); - let mut s = ".".to_owned(); - s.extend(ty.to_string().chars().filter_map(|c| match c { - ' ' => None, - ':' | '<' | '>' => Some('_'), - c => Some(c), - })); - s } - ty::InstanceKind::FutureDropPollShim(_, proxy_cor, impl_cor) => { - let mut s = ".".to_owned(); - s.extend(proxy_cor.to_string().chars().filter_map(|c| match c { - ' ' => None, - ':' | '<' | '>' => Some('_'), - c => Some(c), - })); - s.push('.'); - s.extend(impl_cor.to_string().chars().filter_map(|c| match c { - ' ' => None, - ':' | '<' | '>' => Some('_'), - c => Some(c), - })); - s + } + + // #41697 -- we use `with_forced_impl_filename_line()` because `def_path_str()` would otherwise + // trigger `type_of`, and this can run while we are already attempting to evaluate `type_of`. + pub fn dump_mir_to_writer(&self, body: &Body<'tcx>, w: &mut dyn io::Write) -> io::Result<()> { + // see notes on #41697 above + let def_path = ty::print::with_forced_impl_filename_line!( + self.tcx().def_path_str(body.source.def_id()) + ); + // ignore-tidy-odd-backticks the literal below is fine + write!(w, "// MIR for `{def_path}")?; + match body.source.promoted { + None => write!(w, "`")?, + Some(promoted) => write!(w, "::{promoted:?}`")?, + } + writeln!(w, " {} {}", self.disambiguator, self.pass_name)?; + if let Some(ref layout) = body.coroutine_layout_raw() { + writeln!(w, "/* coroutine_layout = {layout:#?} */")?; } - _ => String::new(), - }; + writeln!(w)?; + (self.writer.extra_data)(PassWhere::BeforeCFG, w)?; + write_user_type_annotations(self.tcx(), body, w)?; + self.writer.write_mir_fn(body, w)?; + (self.writer.extra_data)(PassWhere::AfterCFG, w) + } - let mut file_path = PathBuf::new(); - file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir)); + /// Returns the path to the filename where we should dump a given MIR. + /// Also used by other bits of code (e.g., NLL inference) that dump + /// graphviz data or other things. + fn dump_path(&self, extension: &str, body: &Body<'tcx>) -> PathBuf { + let tcx = self.tcx(); + let source = body.source; + let promotion_id = match source.promoted { + Some(id) => format!("-{id:?}"), + None => String::new(), + }; - let file_name = format!( - "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}", - ); + let pass_num = if tcx.sess.opts.unstable_opts.dump_mir_exclude_pass_number { + String::new() + } else if self.show_pass_num { + let (dialect_index, phase_index) = body.phase.index(); + format!(".{}-{}-{:03}", dialect_index, phase_index, body.pass_count) + } else { + ".-------".to_string() + }; - file_path.push(&file_name); + let crate_name = tcx.crate_name(source.def_id().krate); + let item_name = tcx.def_path(source.def_id()).to_filename_friendly_no_crate(); + // All drop shims have the same DefId, so we have to add the type + // to get unique file names. + let shim_disambiguator = match source.instance { + ty::InstanceKind::DropGlue(_, Some(ty)) => { + // Unfortunately, pretty-printed types are not very filename-friendly. + // We do some filtering. + let mut s = ".".to_owned(); + s.extend(ty.to_string().chars().filter_map(|c| match c { + ' ' => None, + ':' | '<' | '>' => Some('_'), + c => Some(c), + })); + s + } + ty::InstanceKind::AsyncDropGlueCtorShim(_, ty) => { + let mut s = ".".to_owned(); + s.extend(ty.to_string().chars().filter_map(|c| match c { + ' ' => None, + ':' | '<' | '>' => Some('_'), + c => Some(c), + })); + s + } + ty::InstanceKind::AsyncDropGlue(_, ty) => { + let ty::Coroutine(_, args) = ty.kind() else { + bug!(); + }; + let ty = args.first().unwrap().expect_ty(); + let mut s = ".".to_owned(); + s.extend(ty.to_string().chars().filter_map(|c| match c { + ' ' => None, + ':' | '<' | '>' => Some('_'), + c => Some(c), + })); + s + } + ty::InstanceKind::FutureDropPollShim(_, proxy_cor, impl_cor) => { + let mut s = ".".to_owned(); + s.extend(proxy_cor.to_string().chars().filter_map(|c| match c { + ' ' => None, + ':' | '<' | '>' => Some('_'), + c => Some(c), + })); + s.push('.'); + s.extend(impl_cor.to_string().chars().filter_map(|c| match c { + ' ' => None, + ':' | '<' | '>' => Some('_'), + c => Some(c), + })); + s + } + _ => String::new(), + }; - file_path -} + let mut file_path = PathBuf::new(); + file_path.push(Path::new(&tcx.sess.opts.unstable_opts.dump_mir_dir)); -/// Attempts to open a file where we should dump a given MIR or other -/// bit of MIR-related data. Used by `mir-dump`, but also by other -/// bits of code (e.g., NLL inference) that dump graphviz data or -/// other things, and hence takes the extension as an argument. -pub fn create_dump_file<'tcx>( - tcx: TyCtxt<'tcx>, - extension: &str, - pass_num: bool, - pass_name: &str, - disambiguator: &dyn Display, - body: &Body<'tcx>, -) -> io::Result<io::BufWriter<fs::File>> { - let file_path = dump_path(tcx, extension, pass_num, pass_name, disambiguator, body); - if let Some(parent) = file_path.parent() { - fs::create_dir_all(parent).map_err(|e| { - io::Error::new( - e.kind(), - format!("IO error creating MIR dump directory: {parent:?}; {e}"), - ) - })?; + let pass_name = self.pass_name; + let disambiguator = self.disambiguator; + let file_name = format!( + "{crate_name}.{item_name}{shim_disambiguator}{promotion_id}{pass_num}.{pass_name}.{disambiguator}.{extension}", + ); + + file_path.push(&file_name); + + file_path + } + + /// Attempts to open a file where we should dump a given MIR or other + /// bit of MIR-related data. Used by `mir-dump`, but also by other + /// bits of code (e.g., NLL inference) that dump graphviz data or + /// other things, and hence takes the extension as an argument. + pub fn create_dump_file( + &self, + extension: &str, + body: &Body<'tcx>, + ) -> io::Result<io::BufWriter<fs::File>> { + let file_path = self.dump_path(extension, body); + if let Some(parent) = file_path.parent() { + fs::create_dir_all(parent).map_err(|e| { + io::Error::new( + e.kind(), + format!("IO error creating MIR dump directory: {parent:?}; {e}"), + ) + })?; + } + fs::File::create_buffered(&file_path).map_err(|e| { + io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) + }) } - fs::File::create_buffered(&file_path).map_err(|e| { - io::Error::new(e.kind(), format!("IO error creating MIR dump file: {file_path:?}; {e}")) - }) } /////////////////////////////////////////////////////////////////////////// @@ -341,7 +317,7 @@ pub fn write_mir_pretty<'tcx>( single: Option<DefId>, w: &mut dyn io::Write, ) -> io::Result<()> { - let options = PrettyPrintMirOptions::from_cli(tcx); + let writer = MirWriter::new(tcx); writeln!(w, "// WARNING: This output format is intended for human consumers only")?; writeln!(w, "// and is subject to change without notice. Knock yourself out.")?; @@ -357,11 +333,11 @@ pub fn write_mir_pretty<'tcx>( } let render_body = |w: &mut dyn io::Write, body| -> io::Result<()> { - write_mir_fn(tcx, body, &mut |_, _| Ok(()), w, options)?; + writer.write_mir_fn(body, w)?; for body in tcx.promoted_mir(def_id) { writeln!(w)?; - write_mir_fn(tcx, body, &mut |_, _| Ok(()), w, options)?; + writer.write_mir_fn(body, w)?; } Ok(()) }; @@ -373,7 +349,7 @@ pub fn write_mir_pretty<'tcx>( writeln!(w, "// MIR FOR CTFE")?; // Do not use `render_body`, as that would render the promoteds again, but these // are shared between mir_for_ctfe and optimized_mir - write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w, options)?; + writer.write_mir_fn(tcx.mir_for_ctfe(def_id), w)?; } else { let instance_mir = tcx.instance_mir(ty::InstanceKind::Item(def_id)); render_body(w, instance_mir)?; @@ -382,31 +358,35 @@ pub fn write_mir_pretty<'tcx>( Ok(()) } -/// Write out a human-readable textual representation for the given function. -pub fn write_mir_fn<'tcx, F>( +/// Does the writing of MIR to output, e.g. a file. +pub struct MirWriter<'de, 'tcx> { tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - extra_data: &mut F, - w: &mut dyn io::Write, + extra_data: &'de dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>, options: PrettyPrintMirOptions, -) -> io::Result<()> -where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - write_mir_intro(tcx, body, w, options)?; - for block in body.basic_blocks.indices() { - extra_data(PassWhere::BeforeBlock(block), w)?; - write_basic_block(tcx, block, body, extra_data, w, options)?; - if block.index() + 1 != body.basic_blocks.len() { - writeln!(w)?; - } +} + +impl<'de, 'tcx> MirWriter<'de, 'tcx> { + pub fn new(tcx: TyCtxt<'tcx>) -> Self { + MirWriter { tcx, extra_data: &|_, _| Ok(()), options: PrettyPrintMirOptions::from_cli(tcx) } } - writeln!(w, "}}")?; + /// Write out a human-readable textual representation for the given function. + pub fn write_mir_fn(&self, body: &Body<'tcx>, w: &mut dyn io::Write) -> io::Result<()> { + write_mir_intro(self.tcx, body, w, self.options)?; + for block in body.basic_blocks.indices() { + (self.extra_data)(PassWhere::BeforeBlock(block), w)?; + self.write_basic_block(block, body, w)?; + if block.index() + 1 != body.basic_blocks.len() { + writeln!(w)?; + } + } - write_allocations(tcx, body, w)?; + writeln!(w, "}}")?; - Ok(()) + write_allocations(self.tcx, body, w)?; + + Ok(()) + } } /// Prints local variables in a scope tree. @@ -719,95 +699,88 @@ pub fn dump_mir_def_ids(tcx: TyCtxt<'_>, single: Option<DefId>) -> Vec<DefId> { /////////////////////////////////////////////////////////////////////////// // Basic blocks and their parts (statements, terminators, ...) -/// Write out a human-readable textual representation for the given basic block. -fn write_basic_block<'tcx, F>( - tcx: TyCtxt<'tcx>, - block: BasicBlock, - body: &Body<'tcx>, - extra_data: &mut F, - w: &mut dyn io::Write, - options: PrettyPrintMirOptions, -) -> io::Result<()> -where - F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, -{ - let data = &body[block]; - - // Basic block label at the top. - let cleanup_text = if data.is_cleanup { " (cleanup)" } else { "" }; - writeln!(w, "{INDENT}{block:?}{cleanup_text}: {{")?; +impl<'de, 'tcx> MirWriter<'de, 'tcx> { + /// Write out a human-readable textual representation for the given basic block. + fn write_basic_block( + &self, + block: BasicBlock, + body: &Body<'tcx>, + w: &mut dyn io::Write, + ) -> io::Result<()> { + let data = &body[block]; + + // Basic block label at the top. + let cleanup_text = if data.is_cleanup { " (cleanup)" } else { "" }; + writeln!(w, "{INDENT}{block:?}{cleanup_text}: {{")?; + + // List of statements in the middle. + let mut current_location = Location { block, statement_index: 0 }; + for statement in &data.statements { + (self.extra_data)(PassWhere::BeforeLocation(current_location), w)?; + let indented_body = format!("{INDENT}{INDENT}{statement:?};"); + if self.options.include_extra_comments { + writeln!( + w, + "{:A$} // {}{}", + indented_body, + if self.tcx.sess.verbose_internals() { + format!("{current_location:?}: ") + } else { + String::new() + }, + comment(self.tcx, statement.source_info), + A = ALIGN, + )?; + } else { + writeln!(w, "{indented_body}")?; + } - // List of statements in the middle. - let mut current_location = Location { block, statement_index: 0 }; - for statement in &data.statements { - extra_data(PassWhere::BeforeLocation(current_location), w)?; - let indented_body = format!("{INDENT}{INDENT}{statement:?};"); - if options.include_extra_comments { - writeln!( + write_extra( + self.tcx, w, - "{:A$} // {}{}", - indented_body, - if tcx.sess.verbose_internals() { - format!("{current_location:?}: ") - } else { - String::new() - }, - comment(tcx, statement.source_info), - A = ALIGN, + &|visitor| visitor.visit_statement(statement, current_location), + self.options, )?; - } else { - writeln!(w, "{indented_body}")?; - } - write_extra( - tcx, - w, - |visitor| { - visitor.visit_statement(statement, current_location); - }, - options, - )?; + (self.extra_data)(PassWhere::AfterLocation(current_location), w)?; - extra_data(PassWhere::AfterLocation(current_location), w)?; + current_location.statement_index += 1; + } - current_location.statement_index += 1; - } + // Terminator at the bottom. + (self.extra_data)(PassWhere::BeforeLocation(current_location), w)?; + if data.terminator.is_some() { + let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind); + if self.options.include_extra_comments { + writeln!( + w, + "{:A$} // {}{}", + indented_terminator, + if self.tcx.sess.verbose_internals() { + format!("{current_location:?}: ") + } else { + String::new() + }, + comment(self.tcx, data.terminator().source_info), + A = ALIGN, + )?; + } else { + writeln!(w, "{indented_terminator}")?; + } - // Terminator at the bottom. - extra_data(PassWhere::BeforeLocation(current_location), w)?; - if data.terminator.is_some() { - let indented_terminator = format!("{0}{0}{1:?};", INDENT, data.terminator().kind); - if options.include_extra_comments { - writeln!( + write_extra( + self.tcx, w, - "{:A$} // {}{}", - indented_terminator, - if tcx.sess.verbose_internals() { - format!("{current_location:?}: ") - } else { - String::new() - }, - comment(tcx, data.terminator().source_info), - A = ALIGN, + &|visitor| visitor.visit_terminator(data.terminator(), current_location), + self.options, )?; - } else { - writeln!(w, "{indented_terminator}")?; } - write_extra( - tcx, - w, - |visitor| { - visitor.visit_terminator(data.terminator(), current_location); - }, - options, - )?; - } - - extra_data(PassWhere::AfterLocation(current_location), w)?; - extra_data(PassWhere::AfterTerminator(block), w)?; + (self.extra_data)(PassWhere::AfterLocation(current_location), w)?; + (self.extra_data)(PassWhere::AfterTerminator(block), w)?; - writeln!(w, "{INDENT}}}") + writeln!(w, "{INDENT}}}") + } } impl Debug for Statement<'_> { @@ -1374,15 +1347,12 @@ fn post_fmt_projection(projection: &[PlaceElem<'_>], fmt: &mut Formatter<'_>) -> /// After we print the main statement, we sometimes dump extra /// information. There's often a lot of little things "nuzzled up" in /// a statement. -fn write_extra<'tcx, F>( +fn write_extra<'tcx>( tcx: TyCtxt<'tcx>, write: &mut dyn io::Write, - mut visit_op: F, + visit_op: &dyn Fn(&mut ExtraComments<'tcx>), options: PrettyPrintMirOptions, -) -> io::Result<()> -where - F: FnMut(&mut ExtraComments<'tcx>), -{ +) -> io::Result<()> { if options.include_extra_comments { let mut extra_comments = ExtraComments { tcx, comments: vec![] }; visit_op(&mut extra_comments); diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index ea62461ebeb..bea2191c560 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -6,6 +6,7 @@ use rustc_span::ErrorGuaranteed; use crate::mir::interpret::EvalToValTreeResult; use crate::query::CyclePlaceholder; +use crate::traits::solve; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, traits}; @@ -219,6 +220,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ T1) { type Result = [u8; size_of::<(&'static (), &'static ())>()]; } +impl<T0> EraseType for (solve::QueryResult<'_>, &'_ T0) { + type Result = [u8; size_of::<(solve::QueryResult<'static>, &'static ())>()]; +} + impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) { type Result = [u8; size_of::<(&'static (), &'static [()])>()]; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8ce70f75c67..874cee54c7c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -131,7 +131,7 @@ use crate::traits::query::{ }; use crate::traits::{ CodegenObligationError, DynCompatibilityViolation, EvaluationResult, ImplSource, - ObligationCause, OverflowError, WellFormedLoc, specialization_graph, + ObligationCause, OverflowError, WellFormedLoc, solve, specialization_graph, }; use crate::ty::fast_reject::SimplifiedType; use crate::ty::layout::ValidityRequirement; @@ -2563,6 +2563,14 @@ rustc_queries! { desc { "computing autoderef types for `{}`", goal.canonical.value.value } } + /// Used by `-Znext-solver` to compute proof trees. + query evaluate_root_goal_for_proof_tree_raw( + goal: solve::CanonicalInput<'tcx>, + ) -> (solve::QueryResult<'tcx>, &'tcx solve::inspect::Probe<TyCtxt<'tcx>>) { + no_hash + desc { "computing proof tree for `{}`", goal.canonical.value.goal.predicate } + } + /// Returns the Rust target features for the current target. These are not always the same as LLVM target features! query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> { arena_cache diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 32f91bfba6b..ab8a3142953 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -389,10 +389,14 @@ pub enum ObligationCauseCode<'tcx> { /// against. MatchImpl(ObligationCause<'tcx>, DefId), + UnOp { + hir_id: HirId, + }, + BinOp { lhs_hir_id: HirId, - rhs_hir_id: Option<HirId>, - rhs_span: Option<Span>, + rhs_hir_id: HirId, + rhs_span: Span, rhs_is_lit: bool, output_ty: Option<Ty<'tcx>>, }, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5dbbc7297ab..72ab6ac612c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -72,9 +72,9 @@ use crate::query::plumbing::QuerySystem; use crate::query::{IntoQueryParam, LocalCrate, Providers, TyCtxtAt}; use crate::thir::Thir; use crate::traits; -use crate::traits::solve; use crate::traits::solve::{ - ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData, + self, CanonicalInput, ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, + PredefinedOpaquesData, QueryResult, inspect, }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ @@ -737,6 +737,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.opaque_types_defined_by(defining_anchor).iter().chain(coroutines_defined_by), ) } + + type ProbeRef = &'tcx inspect::Probe<TyCtxt<'tcx>>; + fn mk_probe_ref(self, probe: inspect::Probe<Self>) -> &'tcx inspect::Probe<TyCtxt<'tcx>> { + self.arena.alloc(probe) + } + fn evaluate_root_goal_for_proof_tree_raw( + self, + canonical_goal: CanonicalInput<'tcx>, + ) -> (QueryResult<'tcx>, &'tcx inspect::Probe<TyCtxt<'tcx>>) { + self.evaluate_root_goal_for_proof_tree_raw(canonical_goal) + } } macro_rules! bidirectional_lang_item_map { diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index c7b3b541549..b6b10e24585 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -13,7 +13,7 @@ use crate::ty::{EarlyBinder, GenericArgsRef}; pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, - Const { has_default: bool, synthetic: bool }, + Const { has_default: bool }, } impl GenericParamDefKind { diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index 440cb0bdbf3..f756f0a19ee 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } -rustc_apfloat.workspace = true +rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -23,5 +23,5 @@ rustc_pattern_analysis = { path = "../rustc_pattern_analysis" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index eb99c184bd2..7676b720e35 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -293,9 +293,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.diverge_from(loop_block); // Logic for `match`. - let scrutinee_place_builder = - unpack!(body_block = this.as_place_builder(body_block, scrutinee)); let scrutinee_span = this.thir.exprs[scrutinee].span; + let scrutinee_place_builder = unpack!( + body_block = this.lower_scrutinee(body_block, scrutinee, scrutinee_span) + ); + let match_start_span = match_span.shrink_to_lo().to(scrutinee_span); let mut patterns = Vec::with_capacity(arms.len()); @@ -343,7 +345,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, |this| { this.lower_match_arms( - destination, + state_place, scrutinee_place_builder, scrutinee_span, arms, diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 6ee9674bb08..d216c4ecd11 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -388,7 +388,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /// Evaluate the scrutinee and add the PlaceMention for it. - fn lower_scrutinee( + pub(crate) fn lower_scrutinee( &mut self, mut block: BasicBlock, scrutinee_id: ExprId, diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 6a8f0b21ee0..cdb2c5561ce 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -806,10 +806,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); body.coverage_info_hi = self.coverage_info.as_ref().map(|b| b.as_done()); - use rustc_middle::mir::pretty; - let options = pretty::PrettyPrintMirOptions::from_cli(self.tcx); - pretty::write_mir_fn(self.tcx, &body, &mut |_, _| Ok(()), &mut std::io::stdout(), options) - .unwrap(); + let writer = pretty::MirWriter::new(self.tcx); + writer.write_mir_fn(&body, &mut std::io::stdout()).unwrap(); } fn finish(self) -> Body<'tcx> { @@ -827,18 +825,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); body.coverage_info_hi = self.coverage_info.map(|b| b.into_done()); + let writer = pretty::MirWriter::new(self.tcx); for (index, block) in body.basic_blocks.iter().enumerate() { if block.terminator.is_none() { - use rustc_middle::mir::pretty; - let options = pretty::PrettyPrintMirOptions::from_cli(self.tcx); - pretty::write_mir_fn( - self.tcx, - &body, - &mut |_, _| Ok(()), - &mut std::io::stdout(), - options, - ) - .unwrap(); + writer.write_mir_fn(&body, &mut std::io::stdout()).unwrap(); span_bug!(self.fn_span, "no terminator on block {:?}", index); } } diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 11713bb77f1..9621f9f20bd 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -polonius-engine.workspace = true +polonius-engine = "0.13.0" regex = "1" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } @@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 372a3f3a8b8..b85b82b8f6d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -10,8 +10,7 @@ use std::{io, ops, str}; use regex::Regex; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ - self, BasicBlock, Body, Location, create_dump_file, dump_enabled, graphviz_safe_def_name, - traversal, + self, BasicBlock, Body, Location, MirDumper, graphviz_safe_def_name, traversal, }; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -61,11 +60,13 @@ where fs::File::create_buffered(&path)? } - None if dump_enabled(tcx, A::NAME, def_id) => { - create_dump_file(tcx, "dot", false, A::NAME, &pass_name.unwrap_or("-----"), body)? + None => { + let Some(dumper) = MirDumper::new(tcx, A::NAME, body) else { + return Ok(()); + }; + let disambiguator = &pass_name.unwrap_or("-----"); + dumper.set_disambiguator(disambiguator).create_dump_file("dot", body)? } - - _ => return Ok(()), } }; let mut file = match file { diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 99ef67e2625..08c43a4648c 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either.workspace = true -itertools.workspace = true +either = "1" +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -26,5 +26,5 @@ rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 761d5461a99..4603c695ded 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1294,7 +1294,9 @@ fn create_coroutine_resume_function<'tcx>( pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None); - dump_mir(tcx, false, "coroutine_resume", &0, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_resume", body) { + dumper.dump_mir(body); + } } /// An operation that can be performed on a coroutine. @@ -1446,7 +1448,9 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { assert!(body.coroutine_drop().is_none() && body.coroutine_drop_async().is_none()); - dump_mir(tcx, false, "coroutine_before", &0, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_before", body) { + dumper.dump_mir(body); + } // The first argument is the coroutine type passed by value let coroutine_ty = body.local_decls.raw[1].ty; @@ -1506,7 +1510,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { ) { let context_mut_ref = transform_async_context(tcx, body); expand_async_drops(tcx, body, context_mut_ref, coroutine_kind, coroutine_ty); - dump_mir(tcx, false, "coroutine_async_drop_expand", &0, body, |_, _| Ok(())); + + if let Some(dumper) = MirDumper::new(tcx, "coroutine_async_drop_expand", body) { + dumper.dump_mir(body); + } } else { cleanup_async_drops(body); } @@ -1605,14 +1612,18 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // This is expanded to a drop ladder in `elaborate_coroutine_drops`. let drop_clean = insert_clean_drop(tcx, body, has_async_drops); - dump_mir(tcx, false, "coroutine_pre-elab", &0, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_pre-elab", body) { + dumper.dump_mir(body); + } // Expand `drop(coroutine_struct)` to a drop ladder which destroys upvars. // If any upvars are moved out of, drop elaboration will handle upvar destruction. // However we need to also elaborate the code generated by `insert_clean_drop`. elaborate_coroutine_drops(tcx, body); - dump_mir(tcx, false, "coroutine_post-transform", &0, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_post-transform", body) { + dumper.dump_mir(body); + } let can_unwind = can_unwind(tcx, body); diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 81d7b7ba02c..951ff69c19e 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -77,7 +77,7 @@ use rustc_hir::definitions::DisambiguatorState; use rustc_middle::bug; use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; -use rustc_middle::mir::{self, dump_mir}; +use rustc_middle::mir::{self, MirDumper}; use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, TypeVisitableExt}; pub(crate) fn coroutine_by_move_body_def_id<'tcx>( @@ -225,7 +225,10 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( ); by_move_body.source = mir::MirSource::from_instance(InstanceKind::Item(body_def.def_id().to_def_id())); - dump_mir(tcx, false, "built", &"after", &by_move_body, |_, _| Ok(())); + + if let Some(dumper) = MirDumper::new(tcx, "built", &by_move_body) { + dumper.set_disambiguator(&"after").dump_mir(&by_move_body); + } // Feed HIR because we try to access this body's attrs in the inliner. body_def.feed_hir(); diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 1a314e029f4..fd2d8b2b056 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -605,7 +605,9 @@ pub(super) fn create_coroutine_drop_shim<'tcx>( // Temporary change MirSource to coroutine's instance so that dump_mir produces more sensible // filename. body.source.instance = coroutine_instance; - dump_mir(tcx, false, "coroutine_drop", &0, &body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop", &body) { + dumper.dump_mir(&body); + } body.source.instance = drop_instance; // Creating a coroutine drop shim happens on `Analysis(PostCleanup) -> Runtime(Initial)` @@ -696,7 +698,9 @@ pub(super) fn create_coroutine_drop_shim_async<'tcx>( None, ); - dump_mir(tcx, false, "coroutine_drop_async", &0, &body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_async", &body) { + dumper.dump_mir(&body); + } body } @@ -741,7 +745,9 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( }; body.basic_blocks_mut()[call_bb].terminator = Some(Terminator { source_info, kind }); - dump_mir(tcx, false, "coroutine_drop_proxy_async", &0, &body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "coroutine_drop_proxy_async", &body) { + dumper.dump_mir(&body); + } body } diff --git a/compiler/rustc_mir_transform/src/coverage/expansion.rs b/compiler/rustc_mir_transform/src/coverage/expansion.rs new file mode 100644 index 00000000000..91e0528f52f --- /dev/null +++ b/compiler/rustc_mir_transform/src/coverage/expansion.rs @@ -0,0 +1,127 @@ +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; +use rustc_middle::mir::coverage::BasicCoverageBlock; +use rustc_span::{ExpnId, ExpnKind, Span}; + +#[derive(Clone, Copy, Debug)] +pub(crate) struct SpanWithBcb { + pub(crate) span: Span, + pub(crate) bcb: BasicCoverageBlock, +} + +#[derive(Debug)] +pub(crate) struct ExpnTree { + nodes: FxIndexMap<ExpnId, ExpnNode>, +} + +impl ExpnTree { + pub(crate) fn get(&self, expn_id: ExpnId) -> Option<&ExpnNode> { + self.nodes.get(&expn_id) + } + + /// Yields the tree node for the given expansion ID (if present), followed + /// by the nodes of all of its descendants in depth-first order. + pub(crate) fn iter_node_and_descendants( + &self, + root_expn_id: ExpnId, + ) -> impl Iterator<Item = &ExpnNode> { + gen move { + let Some(root_node) = self.get(root_expn_id) else { return }; + yield root_node; + + // Stack of child-node-ID iterators that drives the depth-first traversal. + let mut iter_stack = vec![root_node.child_expn_ids.iter()]; + + while let Some(curr_iter) = iter_stack.last_mut() { + // Pull the next ID from the top of the stack. + let Some(&curr_id) = curr_iter.next() else { + iter_stack.pop(); + continue; + }; + + // Yield this node. + let Some(node) = self.get(curr_id) else { continue }; + yield node; + + // Push the node's children, to be traversed next. + if !node.child_expn_ids.is_empty() { + iter_stack.push(node.child_expn_ids.iter()); + } + } + } + } +} + +#[derive(Debug)] +pub(crate) struct ExpnNode { + /// Storing the expansion ID in its own node is not strictly necessary, + /// but is helpful for debugging and might be useful later. + #[expect(dead_code)] + pub(crate) expn_id: ExpnId, + + // Useful info extracted from `ExpnData`. + pub(crate) expn_kind: ExpnKind, + /// Non-dummy `ExpnData::call_site` span. + pub(crate) call_site: Option<Span>, + /// Expansion ID of `call_site`, if present. + /// This links an expansion node to its parent in the tree. + pub(crate) call_site_expn_id: Option<ExpnId>, + + /// Spans (and their associated BCBs) belonging to this expansion. + pub(crate) spans: Vec<SpanWithBcb>, + /// Expansions whose call-site is in this expansion. + pub(crate) child_expn_ids: FxIndexSet<ExpnId>, +} + +impl ExpnNode { + fn new(expn_id: ExpnId) -> Self { + let expn_data = expn_id.expn_data(); + + let call_site = Some(expn_data.call_site).filter(|sp| !sp.is_dummy()); + let call_site_expn_id = try { call_site?.ctxt().outer_expn() }; + + Self { + expn_id, + + expn_kind: expn_data.kind.clone(), + call_site, + call_site_expn_id, + + spans: vec![], + child_expn_ids: FxIndexSet::default(), + } + } +} + +/// Given a collection of span/BCB pairs from potentially-different syntax contexts, +/// arranges them into an "expansion tree" based on their expansion call-sites. +pub(crate) fn build_expn_tree(spans: impl IntoIterator<Item = SpanWithBcb>) -> ExpnTree { + let mut nodes = FxIndexMap::default(); + let new_node = |&expn_id: &ExpnId| ExpnNode::new(expn_id); + + for span_with_bcb in spans { + // Create a node for this span's enclosing expansion, and add the span to it. + let expn_id = span_with_bcb.span.ctxt().outer_expn(); + let node = nodes.entry(expn_id).or_insert_with_key(new_node); + node.spans.push(span_with_bcb); + + // Now walk up the expansion call-site chain, creating nodes and registering children. + let mut prev = expn_id; + let mut curr_expn_id = node.call_site_expn_id; + while let Some(expn_id) = curr_expn_id { + let entry = nodes.entry(expn_id); + let node_existed = matches!(entry, IndexEntry::Occupied(_)); + + let node = entry.or_insert_with_key(new_node); + node.child_expn_ids.insert(prev); + + if node_existed { + break; + } + + prev = expn_id; + curr_expn_id = node.call_site_expn_id; + } + } + + ExpnTree { nodes } +} diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index c5fef299244..08c7d346009 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -8,6 +8,7 @@ use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; mod counters; +mod expansion; mod graph; mod hir_info; mod mappings; diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index d1b04c8f587..325935ee846 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -1,15 +1,14 @@ -use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir; use rustc_middle::mir::coverage::{Mapping, MappingKind, START_BCB}; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span}; +use rustc_span::{BytePos, DesugaringKind, ExpnId, ExpnKind, MacroKind, Span}; use tracing::instrument; +use crate::coverage::expansion::{self, ExpnTree, SpanWithBcb}; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; use crate::coverage::hir_info::ExtractedHirInfo; -use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir, SpanFromMir}; -use crate::coverage::unexpand; +use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir}; mod from_mir; @@ -34,19 +33,51 @@ pub(super) fn extract_refined_covspans<'tcx>( let &ExtractedHirInfo { body_span, .. } = hir_info; let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph); - let mut covspans = raw_spans - .into_iter() - .filter_map(|RawSpanFromMir { raw_span, bcb }| try { - let (span, expn_kind) = - unexpand::unexpand_into_body_span_with_expn_kind(raw_span, body_span)?; - // Discard any spans that fill the entire body, because they tend - // to represent compiler-inserted code, e.g. implicitly returning `()`. - if span.source_equal(body_span) { - return None; - }; - SpanFromMir { span, expn_kind, bcb } - }) - .collect::<Vec<_>>(); + // Use the raw spans to build a tree of expansions for this function. + let expn_tree = expansion::build_expn_tree( + raw_spans + .into_iter() + .map(|RawSpanFromMir { raw_span, bcb }| SpanWithBcb { span: raw_span, bcb }), + ); + + let mut covspans = vec![]; + let mut push_covspan = |covspan: Covspan| { + let covspan_span = covspan.span; + // Discard any spans not contained within the function body span. + // Also discard any spans that fill the entire body, because they tend + // to represent compiler-inserted code, e.g. implicitly returning `()`. + if !body_span.contains(covspan_span) || body_span.source_equal(covspan_span) { + return; + } + + // Each pushed covspan should have the same context as the body span. + // If it somehow doesn't, discard the covspan, or panic in debug builds. + if !body_span.eq_ctxt(covspan_span) { + debug_assert!( + false, + "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}" + ); + return; + } + + covspans.push(covspan); + }; + + if let Some(node) = expn_tree.get(body_span.ctxt().outer_expn()) { + for &SpanWithBcb { span, bcb } in &node.spans { + push_covspan(Covspan { span, bcb }); + } + + // For each expansion with its call-site in the body span, try to + // distill a corresponding covspan. + for &child_expn_id in &node.child_expn_ids { + if let Some(covspan) = + single_covspan_for_child_expn(tcx, graph, &expn_tree, child_expn_id) + { + push_covspan(covspan); + } + } + } // Only proceed if we found at least one usable span. if covspans.is_empty() { @@ -57,17 +88,10 @@ pub(super) fn extract_refined_covspans<'tcx>( // Otherwise, add a fake span at the start of the body, to avoid an ugly // gap between the start of the body and the first real span. // FIXME: Find a more principled way to solve this problem. - covspans.push(SpanFromMir::for_fn_sig( - hir_info.fn_sig_span.unwrap_or_else(|| body_span.shrink_to_lo()), - )); - - // First, perform the passes that need macro information. - covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb)); - remove_unwanted_expansion_spans(&mut covspans); - shrink_visible_macro_spans(tcx, &mut covspans); - - // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`. - let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>(); + covspans.push(Covspan { + span: hir_info.fn_sig_span.unwrap_or_else(|| body_span.shrink_to_lo()), + bcb: START_BCB, + }); let compare_covspans = |a: &Covspan, b: &Covspan| { compare_spans(a.span, b.span) @@ -117,43 +141,37 @@ pub(super) fn extract_refined_covspans<'tcx>( })); } -/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate -/// multiple condition/consequent blocks that have the span of the whole macro -/// invocation, which is unhelpful. Keeping only the first such span seems to -/// give better mappings, so remove the others. -/// -/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which -/// leads to incorrect coverage if the `Future` is immediately ready (#98712). -/// -/// (The input spans should be sorted in BCB dominator order, so that the -/// retained "first" span is likely to dominate the others.) -fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) { - let mut deduplicated_spans = FxHashSet::default(); - - covspans.retain(|covspan| { - match covspan.expn_kind { - // Retain only the first await-related or macro-expanded covspan with this span. - Some(ExpnKind::Desugaring(DesugaringKind::Await)) => { - deduplicated_spans.insert(covspan.span) - } - Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span), - // Ignore (retain) other spans. - _ => true, +/// For a single child expansion, try to distill it into a single span+BCB mapping. +fn single_covspan_for_child_expn( + tcx: TyCtxt<'_>, + graph: &CoverageGraph, + expn_tree: &ExpnTree, + expn_id: ExpnId, +) -> Option<Covspan> { + let node = expn_tree.get(expn_id)?; + + let bcbs = + expn_tree.iter_node_and_descendants(expn_id).flat_map(|n| n.spans.iter().map(|s| s.bcb)); + + let bcb = match node.expn_kind { + // For bang-macros (e.g. `assert!`, `trace!`) and for `await`, taking + // the "first" BCB in dominator order seems to give good results. + ExpnKind::Macro(MacroKind::Bang, _) | ExpnKind::Desugaring(DesugaringKind::Await) => { + bcbs.min_by(|&a, &b| graph.cmp_in_dominator_order(a, b))? } - }); -} - -/// When a span corresponds to a macro invocation that is visible from the -/// function body, truncate it to just the macro name plus `!`. -/// This seems to give better results for code that uses macros. -fn shrink_visible_macro_spans(tcx: TyCtxt<'_>, covspans: &mut Vec<SpanFromMir>) { - let source_map = tcx.sess.source_map(); + // For other kinds of expansion, taking the "last" (most-dominated) BCB + // seems to give good results. + _ => bcbs.max_by(|&a, &b| graph.cmp_in_dominator_order(a, b))?, + }; - for covspan in covspans { - if matches!(covspan.expn_kind, Some(ExpnKind::Macro(MacroKind::Bang, _))) { - covspan.span = source_map.span_through_char(covspan.span, '!'); - } + // For bang-macro expansions, limit the call-site span to just the macro + // name plus `!`, excluding the macro arguments. + let mut span = node.call_site?; + if matches!(node.expn_kind, ExpnKind::Macro(MacroKind::Bang, _)) { + span = tcx.sess.source_map().span_through_char(span, '!'); } + + Some(Covspan { span, bcb }) } /// Discard all covspans that overlap a hole. diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 7985e1c0798..dfeaa90dc2e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -5,10 +5,9 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::mir::{ self, FakeReadCause, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_span::{ExpnKind, Span}; +use rustc_span::Span; -use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph, START_BCB}; -use crate::coverage::spans::Covspan; +use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; #[derive(Debug)] pub(crate) struct RawSpanFromMir { @@ -160,32 +159,3 @@ impl Hole { true } } - -#[derive(Debug)] -pub(crate) struct SpanFromMir { - /// A span that has been extracted from MIR and then "un-expanded" back to - /// within the current function's `body_span`. After various intermediate - /// processing steps, this span is emitted as part of the final coverage - /// mappings. - /// - /// With the exception of `fn_sig_span`, this should always be contained - /// within `body_span`. - pub(crate) span: Span, - pub(crate) expn_kind: Option<ExpnKind>, - pub(crate) bcb: BasicCoverageBlock, -} - -impl SpanFromMir { - pub(crate) fn for_fn_sig(fn_sig_span: Span) -> Self { - Self::new(fn_sig_span, None, START_BCB) - } - - pub(crate) fn new(span: Span, expn_kind: Option<ExpnKind>, bcb: BasicCoverageBlock) -> Self { - Self { span, expn_kind, bcb } - } - - pub(crate) fn into_covspan(self) -> Covspan { - let Self { span, expn_kind: _, bcb } = self; - Covspan { span, bcb } - } -} diff --git a/compiler/rustc_mir_transform/src/coverage/unexpand.rs b/compiler/rustc_mir_transform/src/coverage/unexpand.rs index cb861544736..922edd3cc4f 100644 --- a/compiler/rustc_mir_transform/src/coverage/unexpand.rs +++ b/compiler/rustc_mir_transform/src/coverage/unexpand.rs @@ -1,4 +1,4 @@ -use rustc_span::{ExpnKind, Span}; +use rustc_span::Span; /// Walks through the expansion ancestors of `original_span` to find a span that /// is contained in `body_span` and has the same [syntax context] as `body_span`. @@ -7,49 +7,3 @@ pub(crate) fn unexpand_into_body_span(original_span: Span, body_span: Span) -> O // we can just delegate directly to `find_ancestor_inside_same_ctxt`. original_span.find_ancestor_inside_same_ctxt(body_span) } - -/// Walks through the expansion ancestors of `original_span` to find a span that -/// is contained in `body_span` and has the same [syntax context] as `body_span`. -/// -/// If the returned span represents a bang-macro invocation (e.g. `foo!(..)`), -/// the returned symbol will be the name of that macro (e.g. `foo`). -pub(crate) fn unexpand_into_body_span_with_expn_kind( - original_span: Span, - body_span: Span, -) -> Option<(Span, Option<ExpnKind>)> { - let (span, prev) = unexpand_into_body_span_with_prev(original_span, body_span)?; - - let expn_kind = prev.map(|prev| prev.ctxt().outer_expn_data().kind); - - Some((span, expn_kind)) -} - -/// Walks through the expansion ancestors of `original_span` to find a span that -/// is contained in `body_span` and has the same [syntax context] as `body_span`. -/// The ancestor that was traversed just before the matching span (if any) is -/// also returned. -/// -/// For example, a return value of `Some((ancestor, Some(prev)))` means that: -/// - `ancestor == original_span.find_ancestor_inside_same_ctxt(body_span)` -/// - `prev.parent_callsite() == ancestor` -/// -/// [syntax context]: rustc_span::SyntaxContext -fn unexpand_into_body_span_with_prev( - original_span: Span, - body_span: Span, -) -> Option<(Span, Option<Span>)> { - let mut prev = None; - let mut curr = original_span; - - while !body_span.contains(curr) || !curr.eq_ctxt(body_span) { - prev = Some(curr); - curr = curr.parent_callsite()?; - } - - debug_assert_eq!(Some(curr), original_span.find_ancestor_inside_same_ctxt(body_span)); - if let Some(prev) = prev { - debug_assert_eq!(Some(curr), prev.parent_callsite()); - } - - Some((curr, prev)) -} diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 4c94a6c524e..cf7425251e8 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -137,8 +137,8 @@ use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::bug; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::{ - Body, HasLocalDecls, InlineAsmOperand, Local, LocalKind, Location, Operand, PassWhere, Place, - Rvalue, Statement, StatementKind, TerminatorKind, dump_mir, traversal, + Body, HasLocalDecls, InlineAsmOperand, Local, LocalKind, Location, MirDumper, Operand, + PassWhere, Place, Rvalue, Statement, StatementKind, TerminatorKind, traversal, }; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::Analysis; @@ -810,11 +810,15 @@ fn dest_prop_mir_dump<'tcx>( let location = points.point_from_location(location); live.rows().filter(|&r| live.contains(r, location)).collect::<Vec<_>>() }; - dump_mir(tcx, false, "DestinationPropagation-dataflow", &round, body, |pass_where, w| { - if let PassWhere::BeforeLocation(loc) = pass_where { - writeln!(w, " // live: {:?}", locals_live_at(loc))?; - } - Ok(()) - }); + if let Some(dumper) = MirDumper::new(tcx, "DestinationPropagation-dataflow", body) { + let extra_data = &|pass_where, w: &mut dyn std::io::Write| { + if let PassWhere::BeforeLocation(loc) = pass_where { + writeln!(w, " // live: {:?}", locals_live_at(loc))?; + } + Ok(()) + }; + + dumper.set_disambiguator(&round).set_extra_data(extra_data).dump_mir(body) + } } diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 08f25276cec..8f319e64916 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -5,6 +5,7 @@ #![feature(const_type_name)] #![feature(cow_is_borrowed)] #![feature(file_buffered)] +#![feature(gen_blocks)] #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] #![feature(try_blocks)] diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 2f0edf31162..794984d2f3e 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -12,8 +12,8 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::bug; use rustc_middle::mir::{ - self, BasicBlock, Body, ClearCrossCrate, Local, Location, Place, StatementKind, TerminatorKind, - dump_mir, + self, BasicBlock, Body, ClearCrossCrate, Local, Location, MirDumper, Place, StatementKind, + TerminatorKind, }; use rustc_middle::ty::significant_drop_order::{ extract_component_with_significant_dtor, ty_dtor_span, @@ -227,7 +227,10 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< return; } - dump_mir(tcx, false, "lint_tail_expr_drop_order", &0 as _, body, |_, _| Ok(())); + if let Some(dumper) = MirDumper::new(tcx, "lint_tail_expr_drop_order", body) { + dumper.dump_mir(body); + } + let locals_with_user_names = collect_user_names(body); let is_closure_like = tcx.is_closure_like(def_id.to_def_id()); diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 5b3ddcc777b..ab09cdf787e 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; +use rustc_middle::mir::{Body, MirDumper, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use tracing::trace; @@ -281,16 +281,22 @@ fn run_passes_inner<'tcx>( let lint = tcx.sess.opts.unstable_opts.lint_mir; for pass in passes { - let name = pass.name(); + let pass_name = pass.name(); if !should_run_pass(tcx, *pass, optimizations) { continue; }; - let dump_enabled = pass.is_mir_dump_enabled(); + let dumper = if pass.is_mir_dump_enabled() + && let Some(dumper) = MirDumper::new(tcx, pass_name, body) + { + Some(dumper.set_show_pass_num().set_disambiguator(&"before")) + } else { + None + }; - if dump_enabled { - dump_mir_for_pass(tcx, body, name, false); + if let Some(dumper) = dumper.as_ref() { + dumper.dump_mir(body); } if let Some(prof_arg) = &prof_arg { @@ -302,14 +308,15 @@ fn run_passes_inner<'tcx>( pass.run_pass(tcx, body); } - if dump_enabled { - dump_mir_for_pass(tcx, body, name, true); + if let Some(dumper) = dumper { + dumper.set_disambiguator(&"after").dump_mir(body); } + if validate { - validate_body(tcx, body, format!("after pass {name}")); + validate_body(tcx, body, format!("after pass {pass_name}")); } if lint { - lint_body(tcx, body, format!("after pass {name}")); + lint_body(tcx, body, format!("after pass {pass_name}")); } body.pass_count += 1; @@ -345,18 +352,9 @@ pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when validate::Validator { when }.run_pass(tcx, body); } -fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) { - mir::dump_mir( - tcx, - true, - pass_name, - if is_after { &"after" } else { &"before" }, - body, - |_, _| Ok(()), - ); -} - pub(super) fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { assert_eq!(body.pass_count, 0); - mir::dump_mir(tcx, true, body.phase.name(), &"after", body, |_, _| Ok(())) + if let Some(dumper) = MirDumper::new(tcx, body.phase.name(), body) { + dumper.set_show_pass_num().set_disambiguator(&"after").dump_mir(body) + } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index c6760b3583f..bca8ffb693b 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1242,14 +1242,12 @@ fn build_construct_coroutine_by_move_shim<'tcx>( let body = new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span); - dump_mir( - tcx, - false, - if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" }, - &0, - &body, - |_, _| Ok(()), - ); + + let pass_name = + if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" }; + if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) { + dumper.dump_mir(&body); + } body } diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 78266d3c6d8..09a55f0b5f8 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -16,6 +16,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } serde = "1" -serde_json.workspace = true -tracing.workspace = true +serde_json = "1" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 43db90c08f3..05bcabad02f 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -5,13 +5,13 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -derive-where.workspace = true +derive-where = "1.2.7" rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } rustc_type_ir = { path = "../rustc_type_ir", default-features = false } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 4644b145b18..6f9f4067384 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -56,22 +56,23 @@ where /// /// This expects `goal` and `opaque_types` to be eager resolved. pub(super) fn canonicalize_goal( - &self, + delegate: &D, goal: Goal<I, I::Predicate>, opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>, ) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) { let mut orig_values = Default::default(); let canonical = Canonicalizer::canonicalize_input( - self.delegate, + delegate, &mut orig_values, QueryInput { goal, - predefined_opaques_in_body: self + predefined_opaques_in_body: delegate .cx() .mk_predefined_opaques_in_body(PredefinedOpaquesData { opaque_types }), }, ); - let query_input = ty::CanonicalQueryInput { canonical, typing_mode: self.typing_mode() }; + let query_input = + ty::CanonicalQueryInput { canonical, typing_mode: delegate.typing_mode() }; (orig_values, query_input) } @@ -271,28 +272,23 @@ where /// - we apply the `external_constraints` returned by the query, returning /// the `normalization_nested_goals` pub(super) fn instantiate_and_apply_query_response( - &mut self, + delegate: &D, param_env: I::ParamEnv, original_values: &[I::GenericArg], response: CanonicalResponse<I>, + span: I::Span, ) -> (NestedNormalizationGoals<I>, Certainty) { let instantiation = Self::compute_query_response_instantiation_values( - self.delegate, + delegate, &original_values, &response, - self.origin_span, + span, ); let Response { var_values, external_constraints, certainty } = - self.delegate.instantiate_canonical(response, instantiation); + delegate.instantiate_canonical(response, instantiation); - Self::unify_query_var_values( - self.delegate, - param_env, - &original_values, - var_values, - self.origin_span, - ); + Self::unify_query_var_values(delegate, param_env, &original_values, var_values, span); let ExternalConstraintsData { region_constraints, @@ -300,8 +296,8 @@ where normalization_nested_goals, } = &*external_constraints; - self.register_region_constraints(region_constraints); - self.register_new_opaque_types(opaque_types); + Self::register_region_constraints(delegate, region_constraints, span); + Self::register_new_opaque_types(delegate, opaque_types, span); (normalization_nested_goals.clone(), certainty) } @@ -424,21 +420,26 @@ where } fn register_region_constraints( - &mut self, + delegate: &D, outlives: &[ty::OutlivesPredicate<I, I::GenericArg>], + span: I::Span, ) { for &ty::OutlivesPredicate(lhs, rhs) in outlives { match lhs.kind() { - ty::GenericArgKind::Lifetime(lhs) => self.register_region_outlives(lhs, rhs), - ty::GenericArgKind::Type(lhs) => self.register_ty_outlives(lhs, rhs), + ty::GenericArgKind::Lifetime(lhs) => delegate.sub_regions(rhs, lhs, span), + ty::GenericArgKind::Type(lhs) => delegate.register_ty_outlives(lhs, rhs, span), ty::GenericArgKind::Const(_) => panic!("const outlives: {lhs:?}: {rhs:?}"), } } } - fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) { + fn register_new_opaque_types( + delegate: &D, + opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)], + span: I::Span, + ) { for &(key, ty) in opaque_types { - let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span); + let prev = delegate.register_hidden_type_in_storage(key, ty, span); // We eagerly resolve inference variables when computing the query response. // This can cause previously distinct opaque type keys to now be structurally equal. // @@ -447,7 +448,7 @@ where // types here. However, doing so is difficult as it may result in nested goals and // any errors may make it harder to track the control flow for diagnostics. if let Some(prev) = prev { - self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span); + delegate.add_duplicate_opaque_type(key, prev, span); } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 4f87902e46e..31106a74527 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -20,13 +20,12 @@ use crate::coherence; use crate::delegate::SolverDelegate; use crate::placeholder::BoundVarReplacer; use crate::resolve::eager_resolve_vars; -use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::ty::may_use_unstable_feature; use crate::solve::{ - CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalEvaluationKind, - GoalSource, GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, - QueryResult, + CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluation, GoalSource, + GoalStalledOn, HasChanged, NestedNormalizationGoals, NoSolution, QueryInput, QueryResult, + inspect, }; pub(super) mod canonical; @@ -130,7 +129,7 @@ where // evaluation code. tainted: Result<(), NoSolution>, - pub(super) inspect: ProofTreeBuilder<D>, + pub(super) inspect: inspect::EvaluationStepBuilder<D>, } #[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)] @@ -172,10 +171,7 @@ pub trait SolverDelegateEvalExt: SolverDelegate { goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>, span: <Self::Interner as Interner>::Span, ) -> ( - Result< - (NestedNormalizationGoals<Self::Interner>, GoalEvaluation<Self::Interner>), - NoSolution, - >, + Result<NestedNormalizationGoals<Self::Interner>, NoSolution>, inspect::GoalEvaluation<Self::Interner>, ); } @@ -192,14 +188,9 @@ where span: I::Span, stalled_on: Option<GoalStalledOn<I>>, ) -> Result<GoalEvaluation<I>, NoSolution> { - EvalCtxt::enter_root( - self, - self.cx().recursion_limit(), - GenerateProofTree::No, - span, - |ecx| ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, stalled_on), - ) - .0 + EvalCtxt::enter_root(self, self.cx().recursion_limit(), span, |ecx| { + ecx.evaluate_goal(GoalSource::Misc, goal, stalled_on) + }) } fn root_goal_may_hold_with_depth( @@ -208,10 +199,9 @@ where goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>, ) -> bool { self.probe(|| { - EvalCtxt::enter_root(self, root_depth, GenerateProofTree::No, I::Span::dummy(), |ecx| { - ecx.evaluate_goal(GoalEvaluationKind::Root, GoalSource::Misc, goal, None) + EvalCtxt::enter_root(self, root_depth, I::Span::dummy(), |ecx| { + ecx.evaluate_goal(GoalSource::Misc, goal, None) }) - .0 }) .is_ok() } @@ -221,18 +211,8 @@ where &self, goal: Goal<I, I::Predicate>, span: I::Span, - ) -> ( - Result<(NestedNormalizationGoals<I>, GoalEvaluation<I>), NoSolution>, - inspect::GoalEvaluation<I>, - ) { - let (result, proof_tree) = EvalCtxt::enter_root( - self, - self.cx().recursion_limit(), - GenerateProofTree::Yes, - span, - |ecx| ecx.evaluate_goal_raw(GoalEvaluationKind::Root, GoalSource::Misc, goal, None), - ); - (result, proof_tree.unwrap()) + ) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) { + evaluate_root_goal_for_proof_tree(self, goal, span) } } @@ -301,17 +281,16 @@ where pub(super) fn enter_root<R>( delegate: &D, root_depth: usize, - generate_proof_tree: GenerateProofTree, origin_span: I::Span, f: impl FnOnce(&mut EvalCtxt<'_, D>) -> R, - ) -> (R, Option<inspect::GoalEvaluation<I>>) { + ) -> R { let mut search_graph = SearchGraph::new(root_depth); let mut ecx = EvalCtxt { delegate, search_graph: &mut search_graph, nested_goals: Default::default(), - inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree), + inspect: inspect::EvaluationStepBuilder::new_noop(), // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. @@ -324,15 +303,12 @@ where tainted: Ok(()), }; let result = f(&mut ecx); - - let proof_tree = ecx.inspect.finalize(); assert!( ecx.nested_goals.is_empty(), "root `EvalCtxt` should not have any goals added to it" ); - assert!(search_graph.is_empty()); - (result, proof_tree) + result } /// Creates a nested evaluation context that shares the same search graph as the @@ -346,11 +322,10 @@ where cx: I, search_graph: &'a mut SearchGraph<D>, canonical_input: CanonicalInput<I>, - canonical_goal_evaluation: &mut ProofTreeBuilder<D>, + proof_tree_builder: &mut inspect::ProofTreeBuilder<D>, f: impl FnOnce(&mut EvalCtxt<'_, D>, Goal<I, I::Predicate>) -> R, ) -> R { let (ref delegate, input, var_values) = D::build_with_canonical(cx, &canonical_input); - for &(key, ty) in &input.predefined_opaques_in_body.opaque_types { let prev = delegate.register_hidden_type_in_storage(key, ty, I::Span::dummy()); // It may be possible that two entries in the opaque type storage end up @@ -381,12 +356,12 @@ where nested_goals: Default::default(), origin_span: I::Span::dummy(), tainted: Ok(()), - inspect: canonical_goal_evaluation.new_goal_evaluation_step(var_values), + inspect: proof_tree_builder.new_evaluation_step(var_values), }; let result = f(&mut ecx, input.goal); ecx.inspect.probe_final_state(ecx.delegate, ecx.max_input_universe); - canonical_goal_evaluation.goal_evaluation_step(ecx.inspect); + proof_tree_builder.finish_evaluation_step(ecx.inspect); // When creating a query response we clone the opaque type constraints // instead of taking them. This would cause an ICE here, since we have @@ -406,13 +381,12 @@ where /// been constrained and the certainty of the result. fn evaluate_goal( &mut self, - goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal<I, I::Predicate>, stalled_on: Option<GoalStalledOn<I>>, ) -> Result<GoalEvaluation<I>, NoSolution> { let (normalization_nested_goals, goal_evaluation) = - self.evaluate_goal_raw(goal_evaluation_kind, source, goal, stalled_on)?; + self.evaluate_goal_raw(source, goal, stalled_on)?; assert!(normalization_nested_goals.is_empty()); Ok(goal_evaluation) } @@ -426,7 +400,6 @@ where /// storage. pub(super) fn evaluate_goal_raw( &mut self, - goal_evaluation_kind: GoalEvaluationKind, source: GoalSource, goal: Goal<I, I::Predicate>, stalled_on: Option<GoalStalledOn<I>>, @@ -458,17 +431,14 @@ where let opaque_types = self.delegate.clone_opaque_types_lookup_table(); let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types)); - let (orig_values, canonical_goal) = self.canonicalize_goal(goal, opaque_types); - let mut goal_evaluation = - self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind); + let (orig_values, canonical_goal) = + Self::canonicalize_goal(self.delegate, goal, opaque_types); let canonical_result = self.search_graph.evaluate_goal( self.cx(), canonical_goal, self.step_kind_for_source(source), - &mut goal_evaluation, + &mut inspect::ProofTreeBuilder::new_noop(), ); - goal_evaluation.query_result(canonical_result); - self.inspect.goal_evaluation(goal_evaluation); let response = match canonical_result { Err(e) => return Err(e), Ok(response) => response, @@ -477,8 +447,13 @@ where let has_changed = if !has_only_region_constraints(response) { HasChanged::Yes } else { HasChanged::No }; - let (normalization_nested_goals, certainty) = - self.instantiate_and_apply_query_response(goal.param_env, &orig_values, response); + let (normalization_nested_goals, certainty) = Self::instantiate_and_apply_query_response( + self.delegate, + goal.param_env, + &orig_values, + response, + self.origin_span, + ); // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. @@ -676,12 +651,7 @@ where let ( NestedNormalizationGoals(nested_goals), GoalEvaluation { goal, certainty, stalled_on, has_changed: _ }, - ) = self.evaluate_goal_raw( - GoalEvaluationKind::Nested, - source, - unconstrained_goal, - stalled_on, - )?; + ) = self.evaluate_goal_raw(source, unconstrained_goal, stalled_on)?; // Add the nested goals from normalization to our own nested goals. trace!(?nested_goals); self.nested_goals.extend(nested_goals.into_iter().map(|(s, g)| (s, g, None))); @@ -734,7 +704,7 @@ where } } else { let GoalEvaluation { goal, certainty, has_changed, stalled_on } = - self.evaluate_goal(GoalEvaluationKind::Nested, source, goal, stalled_on)?; + self.evaluate_goal(source, goal, stalled_on)?; if has_changed == HasChanged::Yes { unchanged_certainty = None; } @@ -1297,3 +1267,62 @@ where if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate } } } + +/// Do not call this directly, use the `tcx` query instead. +pub fn evaluate_root_goal_for_proof_tree_raw_provider< + D: SolverDelegate<Interner = I>, + I: Interner, +>( + cx: I, + canonical_goal: CanonicalInput<I>, +) -> (QueryResult<I>, I::ProbeRef) { + let mut inspect = inspect::ProofTreeBuilder::new(); + let canonical_result = SearchGraph::<D>::evaluate_root_goal_for_proof_tree( + cx, + cx.recursion_limit(), + canonical_goal, + &mut inspect, + ); + let final_revision = inspect.unwrap(); + (canonical_result, cx.mk_probe_ref(final_revision)) +} + +/// Evaluate a goal to build a proof tree. +/// +/// This is a copy of [EvalCtxt::evaluate_goal_raw] which avoids relying on the +/// [EvalCtxt] and uses a separate cache. +pub(super) fn evaluate_root_goal_for_proof_tree<D: SolverDelegate<Interner = I>, I: Interner>( + delegate: &D, + goal: Goal<I, I::Predicate>, + origin_span: I::Span, +) -> (Result<NestedNormalizationGoals<I>, NoSolution>, inspect::GoalEvaluation<I>) { + let opaque_types = delegate.clone_opaque_types_lookup_table(); + let (goal, opaque_types) = eager_resolve_vars(delegate, (goal, opaque_types)); + + let (orig_values, canonical_goal) = EvalCtxt::canonicalize_goal(delegate, goal, opaque_types); + + let (canonical_result, final_revision) = + delegate.cx().evaluate_root_goal_for_proof_tree_raw(canonical_goal); + + let proof_tree = inspect::GoalEvaluation { + uncanonicalized_goal: goal, + orig_values, + final_revision, + result: canonical_result, + }; + + let response = match canonical_result { + Err(e) => return (Err(e), proof_tree), + Ok(response) => response, + }; + + let (normalization_nested_goals, _certainty) = EvalCtxt::instantiate_and_apply_query_response( + delegate, + goal.param_env, + &proof_tree.orig_values, + response, + origin_span, + ); + + (Ok(normalization_nested_goals), proof_tree) +} diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs index fc56b006d94..2675ed0d0da 100644 --- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs +++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs @@ -12,96 +12,86 @@ use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; use crate::solve::eval_ctxt::canonical; -use crate::solve::{ - Certainty, GenerateProofTree, Goal, GoalEvaluationKind, GoalSource, QueryResult, inspect, -}; +use crate::solve::{Certainty, Goal, GoalSource, QueryResult, inspect}; -/// The core data structure when building proof trees. +/// We need to know whether to build a prove tree while evaluating. We +/// pass a `ProofTreeBuilder` with `state: Some(None)` into the search +/// graph which then causes the initial `EvalCtxt::compute_goal` to actually +/// build a proof tree which then gets written into the `state`. /// -/// In case the current evaluation does not generate a proof -/// tree, `state` is simply `None` and we avoid any work. -/// -/// The possible states of the solver are represented via -/// variants of [DebugSolver]. For any nested computation we call -/// `ProofTreeBuilder::new_nested_computation_kind` which -/// creates a new `ProofTreeBuilder` to temporarily replace the -/// current one. Once that nested computation is done, -/// `ProofTreeBuilder::nested_computation_kind` is called -/// to add the finished nested evaluation to the parent. -/// -/// We provide additional information to the current state -/// by calling methods such as `ProofTreeBuilder::probe_kind`. -/// -/// The actual structure closely mirrors the finished proof -/// trees. At the end of trait solving `ProofTreeBuilder::finalize` -/// is called to recursively convert the whole structure to a -/// finished proof tree. +/// Building the proof tree for a single evaluation step happens via the +/// [EvaluationStepBuilder] which is updated by the `EvalCtxt` when +/// appropriate. pub(crate) struct ProofTreeBuilder<D, I = <D as SolverDelegate>::Interner> where D: SolverDelegate<Interner = I>, I: Interner, { + state: Option<Box<Option<inspect::Probe<I>>>>, _infcx: PhantomData<D>, - state: Option<Box<DebugSolver<I>>>, } -/// The current state of the proof tree builder, at most places -/// in the code, only one or two variants are actually possible. -/// -/// We simply ICE in case that assumption is broken. -#[derive_where(Debug; I: Interner)] -enum DebugSolver<I: Interner> { - Root, - GoalEvaluation(WipGoalEvaluation<I>), - CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep<I>), -} +impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { + pub(crate) fn new() -> ProofTreeBuilder<D> { + ProofTreeBuilder { state: Some(Box::new(None)), _infcx: PhantomData } + } -impl<I: Interner> From<WipGoalEvaluation<I>> for DebugSolver<I> { - fn from(g: WipGoalEvaluation<I>) -> DebugSolver<I> { - DebugSolver::GoalEvaluation(g) + pub(crate) fn new_noop() -> ProofTreeBuilder<D> { + ProofTreeBuilder { state: None, _infcx: PhantomData } } -} -impl<I: Interner> From<WipCanonicalGoalEvaluationStep<I>> for DebugSolver<I> { - fn from(g: WipCanonicalGoalEvaluationStep<I>) -> DebugSolver<I> { - DebugSolver::CanonicalGoalEvaluationStep(g) + pub(crate) fn is_noop(&self) -> bool { + self.state.is_none() } -} -#[derive_where(PartialEq, Debug; I: Interner)] -struct WipGoalEvaluation<I: Interner> { - pub uncanonicalized_goal: Goal<I, I::Predicate>, - pub orig_values: Vec<I::GenericArg>, - pub encountered_overflow: bool, - /// After we finished evaluating this is moved into `kind`. - pub final_revision: Option<WipCanonicalGoalEvaluationStep<I>>, - pub result: Option<QueryResult<I>>, -} + pub(crate) fn new_evaluation_step( + &mut self, + var_values: ty::CanonicalVarValues<I>, + ) -> EvaluationStepBuilder<D> { + if self.is_noop() { + EvaluationStepBuilder { state: None, _infcx: PhantomData } + } else { + EvaluationStepBuilder { + state: Some(Box::new(WipEvaluationStep { + var_values: var_values.var_values.to_vec(), + evaluation: WipProbe { + initial_num_var_values: var_values.len(), + steps: vec![], + kind: None, + final_state: None, + }, + probe_depth: 0, + })), + _infcx: PhantomData, + } + } + } -impl<I: Interner> Eq for WipGoalEvaluation<I> {} - -impl<I: Interner> WipGoalEvaluation<I> { - fn finalize(self) -> inspect::GoalEvaluation<I> { - inspect::GoalEvaluation { - uncanonicalized_goal: self.uncanonicalized_goal, - orig_values: self.orig_values, - kind: if self.encountered_overflow { - assert!(self.final_revision.is_none()); - inspect::GoalEvaluationKind::Overflow - } else { - let final_revision = self.final_revision.unwrap().finalize(); - inspect::GoalEvaluationKind::Evaluation { final_revision } - }, - result: self.result.unwrap(), + pub(crate) fn finish_evaluation_step( + &mut self, + goal_evaluation_step: EvaluationStepBuilder<D>, + ) { + if let Some(this) = self.state.as_deref_mut() { + *this = Some(goal_evaluation_step.state.unwrap().finalize()); } } + + pub(crate) fn unwrap(self) -> inspect::Probe<I> { + self.state.unwrap().unwrap() + } } -/// This only exists during proof tree building and does not have -/// a corresponding struct in `inspect`. We need this to track a -/// bunch of metadata about the current evaluation. -#[derive_where(PartialEq, Debug; I: Interner)] -struct WipCanonicalGoalEvaluationStep<I: Interner> { +pub(crate) struct EvaluationStepBuilder<D, I = <D as SolverDelegate>::Interner> +where + D: SolverDelegate<Interner = I>, + I: Interner, +{ + state: Option<Box<WipEvaluationStep<I>>>, + _infcx: PhantomData<D>, +} + +#[derive_where(PartialEq, Eq, Debug; I: Interner)] +struct WipEvaluationStep<I: Interner> { /// Unlike `EvalCtxt::var_values`, we append a new /// generic arg here whenever we create a new inference /// variable. @@ -113,9 +103,7 @@ struct WipCanonicalGoalEvaluationStep<I: Interner> { evaluation: WipProbe<I>, } -impl<I: Interner> Eq for WipCanonicalGoalEvaluationStep<I> {} - -impl<I: Interner> WipCanonicalGoalEvaluationStep<I> { +impl<I: Interner> WipEvaluationStep<I> { fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> { let mut current = &mut self.evaluation; for _ in 0..self.probe_depth { @@ -181,169 +169,48 @@ impl<I: Interner> WipProbeStep<I> { } } -impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { - fn new(state: impl Into<DebugSolver<I>>) -> ProofTreeBuilder<D> { - ProofTreeBuilder { state: Some(Box::new(state.into())), _infcx: PhantomData } - } - - fn opt_nested<T: Into<DebugSolver<I>>>(&self, state: impl FnOnce() -> Option<T>) -> Self { - ProofTreeBuilder { - state: self.state.as_ref().and_then(|_| Some(state()?.into())).map(Box::new), - _infcx: PhantomData, - } +impl<D: SolverDelegate<Interner = I>, I: Interner> EvaluationStepBuilder<D> { + pub(crate) fn new_noop() -> EvaluationStepBuilder<D> { + EvaluationStepBuilder { state: None, _infcx: PhantomData } } - fn nested<T: Into<DebugSolver<I>>>(&self, state: impl FnOnce() -> T) -> Self { - ProofTreeBuilder { - state: self.state.as_ref().map(|_| Box::new(state().into())), - _infcx: PhantomData, - } + pub(crate) fn is_noop(&self) -> bool { + self.state.is_none() } - fn as_mut(&mut self) -> Option<&mut DebugSolver<I>> { + fn as_mut(&mut self) -> Option<&mut WipEvaluationStep<I>> { self.state.as_deref_mut() } - pub(crate) fn take_and_enter_probe(&mut self) -> ProofTreeBuilder<D> { - let mut nested = ProofTreeBuilder { state: self.state.take(), _infcx: PhantomData }; + pub(crate) fn take_and_enter_probe(&mut self) -> EvaluationStepBuilder<D> { + let mut nested = EvaluationStepBuilder { state: self.state.take(), _infcx: PhantomData }; nested.enter_probe(); nested } - pub(crate) fn finalize(self) -> Option<inspect::GoalEvaluation<I>> { - match *self.state? { - DebugSolver::GoalEvaluation(wip_goal_evaluation) => { - Some(wip_goal_evaluation.finalize()) - } - root => unreachable!("unexpected proof tree builder root node: {:?}", root), - } - } - - pub(crate) fn new_maybe_root(generate_proof_tree: GenerateProofTree) -> ProofTreeBuilder<D> { - match generate_proof_tree { - GenerateProofTree::No => ProofTreeBuilder::new_noop(), - GenerateProofTree::Yes => ProofTreeBuilder::new_root(), - } - } - - fn new_root() -> ProofTreeBuilder<D> { - ProofTreeBuilder::new(DebugSolver::Root) - } - - fn new_noop() -> ProofTreeBuilder<D> { - ProofTreeBuilder { state: None, _infcx: PhantomData } - } - - pub(crate) fn is_noop(&self) -> bool { - self.state.is_none() - } - - pub(in crate::solve) fn new_goal_evaluation( - &mut self, - uncanonicalized_goal: Goal<I, I::Predicate>, - orig_values: &[I::GenericArg], - kind: GoalEvaluationKind, - ) -> ProofTreeBuilder<D> { - self.opt_nested(|| match kind { - GoalEvaluationKind::Root => Some(WipGoalEvaluation { - uncanonicalized_goal, - orig_values: orig_values.to_vec(), - encountered_overflow: false, - final_revision: None, - result: None, - }), - GoalEvaluationKind::Nested => None, - }) - } - - pub(crate) fn canonical_goal_evaluation_overflow(&mut self) { + pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) { if let Some(this) = self.as_mut() { - match this { - DebugSolver::GoalEvaluation(goal_evaluation) => { - goal_evaluation.encountered_overflow = true; - } - _ => unreachable!(), - }; + this.var_values.push(arg.into()); } } - pub(crate) fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder<D>) { + fn enter_probe(&mut self) { if let Some(this) = self.as_mut() { - match this { - DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), - DebugSolver::CanonicalGoalEvaluationStep(_) => { - assert!(goal_evaluation.state.is_none()) - } - _ => unreachable!(), - } - } - } - - pub(crate) fn new_goal_evaluation_step( - &mut self, - var_values: ty::CanonicalVarValues<I>, - ) -> ProofTreeBuilder<D> { - self.nested(|| WipCanonicalGoalEvaluationStep { - var_values: var_values.var_values.to_vec(), - evaluation: WipProbe { - initial_num_var_values: var_values.len(), + let initial_num_var_values = this.var_values.len(); + this.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe { + initial_num_var_values, steps: vec![], kind: None, final_state: None, - }, - probe_depth: 0, - }) - } - - pub(crate) fn goal_evaluation_step(&mut self, goal_evaluation_step: ProofTreeBuilder<D>) { - if let Some(this) = self.as_mut() { - match (this, *goal_evaluation_step.state.unwrap()) { - ( - DebugSolver::GoalEvaluation(goal_evaluation), - DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), - ) => { - goal_evaluation.final_revision = Some(goal_evaluation_step); - } - _ => unreachable!(), - } - } - } - - pub(crate) fn add_var_value<T: Into<I::GenericArg>>(&mut self, arg: T) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - state.var_values.push(arg.into()); - } - Some(s) => panic!("tried to add var values to {s:?}"), - } - } - - fn enter_probe(&mut self) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - let initial_num_var_values = state.var_values.len(); - state.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe { - initial_num_var_values, - steps: vec![], - kind: None, - final_state: None, - })); - state.probe_depth += 1; - } - Some(s) => panic!("tried to start probe to {s:?}"), + })); + this.probe_depth += 1; } } pub(crate) fn probe_kind(&mut self, probe_kind: inspect::ProbeKind<I>) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - let prev = state.current_evaluation_scope().kind.replace(probe_kind); - assert_eq!(prev, None); - } - _ => panic!(), + if let Some(this) = self.as_mut() { + let prev = this.current_evaluation_scope().kind.replace(probe_kind); + assert_eq!(prev, None); } } @@ -352,19 +219,11 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { delegate: &D, max_input_universe: ty::UniverseIndex, ) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - let final_state = canonical::make_canonical_state( - delegate, - &state.var_values, - max_input_universe, - (), - ); - let prev = state.current_evaluation_scope().final_state.replace(final_state); - assert_eq!(prev, None); - } - _ => panic!(), + if let Some(this) = self.as_mut() { + let final_state = + canonical::make_canonical_state(delegate, &this.var_values, max_input_universe, ()); + let prev = this.current_evaluation_scope().final_state.replace(final_state); + assert_eq!(prev, None); } } @@ -375,18 +234,14 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { source: GoalSource, goal: Goal<I, I::Predicate>, ) { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - let goal = canonical::make_canonical_state( - delegate, - &state.var_values, - max_input_universe, - goal, - ); - state.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal)) - } - _ => panic!(), + if let Some(this) = self.as_mut() { + let goal = canonical::make_canonical_state( + delegate, + &this.var_values, + max_input_universe, + goal, + ); + this.current_evaluation_scope().steps.push(WipProbeStep::AddGoal(source, goal)) } } @@ -396,47 +251,31 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { max_input_universe: ty::UniverseIndex, impl_args: I::GenericArgs, ) { - match self.as_mut() { - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - let impl_args = canonical::make_canonical_state( - delegate, - &state.var_values, - max_input_universe, - impl_args, - ); - state - .current_evaluation_scope() - .steps - .push(WipProbeStep::RecordImplArgs { impl_args }); - } - None => {} - _ => panic!(), + if let Some(this) = self.as_mut() { + let impl_args = canonical::make_canonical_state( + delegate, + &this.var_values, + max_input_universe, + impl_args, + ); + this.current_evaluation_scope().steps.push(WipProbeStep::RecordImplArgs { impl_args }); } } pub(crate) fn make_canonical_response(&mut self, shallow_certainty: Certainty) { - match self.as_mut() { - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - state - .current_evaluation_scope() - .steps - .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty }); - } - None => {} - _ => panic!(), + if let Some(this) = self.as_mut() { + this.current_evaluation_scope() + .steps + .push(WipProbeStep::MakeCanonicalResponse { shallow_certainty }); } } - pub(crate) fn finish_probe(mut self) -> ProofTreeBuilder<D> { - match self.as_mut() { - None => {} - Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { - assert_ne!(state.probe_depth, 0); - let num_var_values = state.current_evaluation_scope().initial_num_var_values; - state.var_values.truncate(num_var_values); - state.probe_depth -= 1; - } - _ => panic!(), + pub(crate) fn finish_probe(mut self) -> EvaluationStepBuilder<D> { + if let Some(this) = self.as_mut() { + assert_ne!(this.probe_depth, 0); + let num_var_values = this.current_evaluation_scope().initial_num_var_values; + this.var_values.truncate(num_var_values); + this.probe_depth -= 1; } self @@ -444,21 +283,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> { pub(crate) fn query_result(&mut self, result: QueryResult<I>) { if let Some(this) = self.as_mut() { - match this { - DebugSolver::GoalEvaluation(goal_evaluation) => { - assert_eq!(goal_evaluation.result.replace(result), None); - } - DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { - assert_eq!( - evaluation_step - .evaluation - .kind - .replace(inspect::ProbeKind::Root { result }), - None - ); - } - _ => unreachable!(), - } + assert_eq!(this.evaluation.kind.replace(inspect::ProbeKind::Root { result }), None); } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 710b59f662a..85f9d852d95 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -27,7 +27,10 @@ pub use rustc_type_ir::solve::*; use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; -pub use self::eval_ctxt::{EvalCtxt, GenerateProofTree, SolverDelegateEvalExt}; +pub use self::eval_ctxt::{ + EvalCtxt, GenerateProofTree, SolverDelegateEvalExt, + evaluate_root_goal_for_proof_tree_raw_provider, +}; use crate::delegate::SolverDelegate; use crate::solve::assembly::Candidate; @@ -42,12 +45,6 @@ use crate::solve::assembly::Candidate; /// recursion limit again. However, this feels very unlikely. const FIXPOINT_STEP_LIMIT: usize = 8; -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum GoalEvaluationKind { - Root, - Nested, -} - /// Whether evaluating this goal ended up changing the /// inference state. #[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)] diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index 84f8eda4f8d..f0342e0523f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -7,8 +7,9 @@ use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult}; use rustc_type_ir::{Interner, TypingMode}; use crate::delegate::SolverDelegate; -use crate::solve::inspect::ProofTreeBuilder; -use crate::solve::{EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints}; +use crate::solve::{ + EvalCtxt, FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints, inspect, +}; /// This type is never constructed. We only use it to implement `search_graph::Delegate` /// for all types which impl `SolverDelegate` and doing it directly fails in coherence. @@ -34,7 +35,7 @@ where const FIXPOINT_STEP_LIMIT: usize = FIXPOINT_STEP_LIMIT; - type ProofTreeBuilder = ProofTreeBuilder<D>; + type ProofTreeBuilder = inspect::ProofTreeBuilder<D>; fn inspect_is_noop(inspect: &mut Self::ProofTreeBuilder) -> bool { inspect.is_noop() } @@ -81,12 +82,7 @@ where Self::initial_provisional_result(cx, kind, input) == result } - fn on_stack_overflow( - cx: I, - input: CanonicalInput<I>, - inspect: &mut ProofTreeBuilder<D>, - ) -> QueryResult<I> { - inspect.canonical_goal_evaluation_overflow(); + fn on_stack_overflow(cx: I, input: CanonicalInput<I>) -> QueryResult<I> { response_no_constraints(cx, input, Certainty::overflow(true)) } diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index 7cb4ae7ff5f..6d738a10371 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -5,8 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -rustc-literal-escaper.workspace = true +bitflags = "2.4.1" +rustc-literal-escaper = "0.0.5" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -18,8 +18,8 @@ rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" unicode-normalization = "0.1.11" unicode-width = "0.2.0" # tidy-alphabetical-end diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7de4f6efd0b..9b09cbba7af 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2910,7 +2910,8 @@ impl<'a> Parser<'a> { } } - fn parse_for_head(&mut self) -> PResult<'a, (Box<Pat>, Box<Expr>)> { + // Public to use it for custom `for` expressions in rustfmt forks like https://github.com/tucant/rustfmt + pub fn parse_for_head(&mut self) -> PResult<'a, (Box<Pat>, Box<Expr>)> { let begin_paren = if self.token == token::OpenParen { // Record whether we are about to parse `for (`. // This is used below for recovery in case of `for ( $stuff ) $block` diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9754691a0b9..c4d30b3d328 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1516,7 +1516,7 @@ impl<'a> Parser<'a> { || self.check_noexpect(&token::DotDotDot) || self.check_keyword(exp!(Underscore)) { - etc = PatFieldsRest::Rest; + etc = PatFieldsRest::Rest(self.token.span); let mut etc_sp = self.token.span; if first_etc_and_maybe_comma_span.is_none() { if let Some(comma_tok) = diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index 645e34b6e32..d178fcda1fb 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-literal-escaper.workspace = true +rustc-literal-escaper = "0.0.5" rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml index c74608a6146..ba81ef3103b 100644 --- a/compiler/rustc_passes/Cargo.toml +++ b/compiler/rustc_passes/Cargo.toml @@ -24,5 +24,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 801a533c943..ae16a51bc69 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1583,7 +1583,7 @@ impl<'tcx> Liveness<'_, 'tcx> { }); let can_remove = match pat.kind { - hir::PatKind::Struct(_, fields, true) => { + hir::PatKind::Struct(_, fields, Some(_)) => { // if all fields are shorthand, remove the struct field, otherwise, mark with _ as prefix fields.iter().all(|f| f.is_shorthand) } diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml index e4909ab6d16..a59f7bbeb9e 100644 --- a/compiler/rustc_pattern_analysis/Cargo.toml +++ b/compiler/rustc_pattern_analysis/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc-hash.workspace = true +rustc-hash = "2.0.0" rustc_abi = { path = "../rustc_abi", optional = true } -rustc_apfloat.workspace = true +rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena", optional = true } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_errors = { path = "../rustc_errors", optional = true } @@ -19,7 +19,7 @@ rustc_middle = { path = "../rustc_middle", optional = true } rustc_session = { path = "../rustc_session", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = { version = "1.8.1", features = ["union"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [dev-dependencies] diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 7de58132e13..c8bfdb91304 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -15,5 +15,5 @@ rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_ty_utils = { path = "../rustc_ty_utils" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml index 99e7fc7abc6..beb95aa3b52 100644 --- a/compiler/rustc_proc_macro/Cargo.toml +++ b/compiler/rustc_proc_macro/Cargo.toml @@ -16,7 +16,7 @@ doctest = false [dependencies] # tidy-alphabetical-start -rustc-literal-escaper.workspace = true +rustc-literal-escaper = "0.0.5" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_public/Cargo.toml b/compiler/rustc_public/Cargo.toml index e67e4fe6739..70af30c1a5f 100644 --- a/compiler/rustc_public/Cargo.toml +++ b/compiler/rustc_public/Cargo.toml @@ -12,9 +12,9 @@ rustc_public_bridge = { path = "../rustc_public_bridge" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -scoped-tls.workspace = true +scoped-tls = "1.0" serde = { version = "1.0.125", features = [ "derive" ] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 5a661072bc7..207038db40d 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -656,13 +656,13 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { use crate::ty::GenericParamDefKind; - match self { + match *self { ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, ty::GenericParamDefKind::Type { has_default, synthetic } => { - GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic } + GenericParamDefKind::Type { has_default, synthetic } } - ty::GenericParamDefKind::Const { has_default, synthetic: _ } => { - GenericParamDefKind::Const { has_default: *has_default } + ty::GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Const { has_default } } } } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index 3d5cf0eb72d..e5cceacf15d 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -measureme.workspace = true +measureme = "12.0.1" rustc_data_structures = { path = "../rustc_data_structures" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } @@ -15,5 +15,5 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 0df933bc81c..7480ba03474 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -21,7 +21,7 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_thread_pool = { path = "../rustc_thread_pool" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [dependencies.hashbrown] diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 4da4c0840df..eb98a6e85c0 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -5,9 +5,9 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -indexmap.workspace = true -itertools.workspace = true +bitflags = "2.4.1" +indexmap = "2.4.0" +itertools = "0.12" pulldown-cmark = { version = "0.11", features = ["html"], default-features = false } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } @@ -27,6 +27,6 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index f75a625a279..fa3c06059b3 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1008,16 +1008,13 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let msg = format!("extern crate `{ident}` already in extern prelude"); self.r.tcx.dcx().span_delayed_bug(item.span, msg); } else { - entry.item_binding = Some(imported_binding); - entry.introduced_by_item = orig_name.is_some(); + entry.item_binding = Some((imported_binding, orig_name.is_some())); } entry } Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry { - item_binding: Some(imported_binding), - flag_binding: Cell::new(None), - only_item: true, - introduced_by_item: true, + item_binding: Some((imported_binding, true)), + flag_binding: None, }), }; } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 11d93a58ae2..50a1ad23a54 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -204,7 +204,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { .r .extern_prelude .get(&Macros20NormalizedIdent::new(extern_crate.ident)) - .is_none_or(|entry| entry.introduced_by_item) + .is_none_or(|entry| entry.introduced_by_item()) { continue; } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 337e7d2dd86..5dfc4292a38 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -322,7 +322,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let from_item = self .extern_prelude .get(&Macros20NormalizedIdent::new(ident)) - .is_none_or(|entry| entry.introduced_by_item); + .is_none_or(|entry| entry.introduced_by_item()); // Only suggest removing an import if both bindings are to the same def, if both spans // aren't dummy spans. Further, if both bindings are imports, then the ident must have // been introduced by an item. @@ -1845,7 +1845,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let AmbiguityError { kind, ident, b1, b2, misc1, misc2, .. } = *ambiguity_error; let extern_prelude_ambiguity = || { self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)).is_some_and(|entry| { - entry.item_binding == Some(b1) && entry.flag_binding.get() == Some(b2) + entry.item_binding.map(|(b, _)| b) == Some(b1) + && entry.flag_binding.as_ref().and_then(|pb| pb.get().binding()) == Some(b2) }) }; let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index d4f7fb276a9..6a12fafcb1e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3922,7 +3922,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) { match rest { - ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => { + ast::PatFieldsRest::Rest(_) | ast::PatFieldsRest::Recovered(_) => { // Record that the pattern doesn't introduce all the bindings it could. if let Some(partial_res) = self.r.partial_res_map.get(&pat.id) && let Some(res) = partial_res.full_res() diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 2afb52ef4d4..9674c0356c2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -32,7 +32,7 @@ use std::sync::Arc; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use effective_visibilities::EffectiveVisibilitiesVisitor; use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; -use imports::{Import, ImportData, ImportKind, NameResolution}; +use imports::{Import, ImportData, ImportKind, NameResolution, PendingBinding}; use late::{ ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource, UnnecessaryQualification, @@ -1025,18 +1025,26 @@ impl<'ra> NameBindingData<'ra> { } } -#[derive(Default, Clone)] struct ExternPreludeEntry<'ra> { /// Binding from an `extern crate` item. - item_binding: Option<NameBinding<'ra>>, + /// The boolean flag is true is `item_binding` is non-redundant, happens either when + /// `flag_binding` is `None`, or when `extern crate` introducing `item_binding` used renaming. + item_binding: Option<(NameBinding<'ra>, /* introduced by item */ bool)>, /// Binding from an `--extern` flag, lazily populated on first use. - flag_binding: Cell<Option<NameBinding<'ra>>>, - /// There was no `--extern` flag introducing this name, - /// `flag_binding` doesn't need to be populated. - only_item: bool, - /// `item_binding` is non-redundant, happens either when `only_item` is true, - /// or when `extern crate` introducing `item_binding` used renaming. - introduced_by_item: bool, + flag_binding: Option<Cell<PendingBinding<'ra>>>, +} + +impl ExternPreludeEntry<'_> { + fn introduced_by_item(&self) -> bool { + matches!(self.item_binding, Some((_, true))) + } + + fn flag() -> Self { + ExternPreludeEntry { + item_binding: None, + flag_binding: Some(Cell::new(PendingBinding::Pending)), + } + } } struct DeriveData { @@ -1528,7 +1536,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let name = Symbol::intern(name) && name.can_be_raw() { - Some((Macros20NormalizedIdent::with_dummy_span(name), Default::default())) + let ident = Macros20NormalizedIdent::with_dummy_span(name); + Some((ident, ExternPreludeEntry::flag())) } else { None } @@ -1536,11 +1545,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .collect(); if !attr::contains_name(attrs, sym::no_core) { - extern_prelude - .insert(Macros20NormalizedIdent::with_dummy_span(sym::core), Default::default()); + let ident = Macros20NormalizedIdent::with_dummy_span(sym::core); + extern_prelude.insert(ident, ExternPreludeEntry::flag()); if !attr::contains_name(attrs, sym::no_std) { - extern_prelude - .insert(Macros20NormalizedIdent::with_dummy_span(sym::std), Default::default()); + let ident = Macros20NormalizedIdent::with_dummy_span(sym::std); + extern_prelude.insert(ident, ExternPreludeEntry::flag()); } } @@ -2062,12 +2071,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. - if used == Used::Scope { - if let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)) { - if !entry.introduced_by_item && entry.item_binding == Some(used_binding) { - return; - } - } + if used == Used::Scope + && let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)) + && entry.item_binding == Some((used_binding, false)) + { + return; } let old_used = self.import_use_map.entry(import).or_insert(used); if *old_used < used { @@ -2226,7 +2234,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { finalize: bool, ) -> Option<NameBinding<'ra>> { let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)); - entry.and_then(|entry| entry.item_binding).map(|binding| { + entry.and_then(|entry| entry.item_binding).map(|(binding, _)| { if finalize { self.get_mut().record_use(ident, binding, Used::Scope); } @@ -2236,31 +2244,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn extern_prelude_get_flag(&self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> { let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident)); - entry.and_then(|entry| match entry.flag_binding.get() { - Some(binding) => { - if finalize { - self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); + entry.and_then(|entry| entry.flag_binding.as_ref()).and_then(|flag_binding| { + let binding = match flag_binding.get() { + PendingBinding::Ready(binding) => { + if finalize { + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); + } + binding } - Some(binding) - } - None if entry.only_item => None, - None => { - let crate_id = if finalize { - self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span) - } else { - self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name) - }; - match crate_id { - Some(crate_id) => { + PendingBinding::Pending => { + let crate_id = if finalize { + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span) + } else { + self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name) + }; + crate_id.map(|crate_id| { let res = Res::Def(DefKind::Mod, crate_id.as_def_id()); - let binding = - self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT); - entry.flag_binding.set(Some(binding)); - Some(binding) - } - None => finalize.then_some(self.dummy_binding), + self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT) + }) } - } + }; + flag_binding.set(PendingBinding::Ready(binding)); + binding.or_else(|| finalize.then_some(self.dummy_binding)) }) } diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index 3dbeaa435f3..9069d2c233d 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.5.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } @@ -13,6 +13,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" twox-hash = "1.6.3" # tidy-alphabetical-end diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml index 853f87ebed9..948242352e7 100644 --- a/compiler/rustc_serialize/Cargo.toml +++ b/compiler/rustc_serialize/Cargo.toml @@ -5,14 +5,14 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -indexmap.workspace = true +indexmap = "2.0.0" rustc_hashes = { path = "../rustc_hashes" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true +thin-vec = "0.2.12" # tidy-alphabetical-end [dev-dependencies] # tidy-alphabetical-start rustc_macros = { path = "../rustc_macros" } -tempfile.workspace = true +tempfile = "3.2" # tidy-alphabetical-end diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 5870fb29ae8..60d56b1b808 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.4.1" getopts = "0.2" rand = "0.9.0" rustc_abi = { path = "../rustc_abi" } @@ -23,12 +23,14 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } termize = "0.2" -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] +# FIXME: Remove this pin once this rustix issue is resolved +# https://github.com/bytecodealliance/rustix/issues/1496 # tidy-alphabetical-start -libc.workspace = true +libc = "=0.2.174" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index da6f2101d23..43a2d692577 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start blake3 = "1.5.2" -derive-where.workspace = true -indexmap.workspace = true +derive-where = "1.2.7" +indexmap = { version = "2.0.0" } itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } rustc_arena = { path = "../rustc_arena" } @@ -16,9 +16,9 @@ rustc_hashes = { path = "../rustc_hashes" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -scoped-tls.workspace = true +scoped-tls = "1.0" sha1 = "0.10.0" sha2 = "0.10.1" -tracing.workspace = true +tracing = "0.1" unicode-width = "0.2.0" # tidy-alphabetical-end diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 0ceac4b3e1b..0df9c7682bf 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -6,7 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start punycode = "0.4.0" -rustc-demangle.workspace = true +rustc-demangle = "0.1.21" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -15,5 +15,5 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index ed59ee2a575..7fabb227d9a 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true +bitflags = "2.4.1" object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] } rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -16,8 +16,8 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } serde = "1.0.219" serde_derive = "1.0.219" -serde_json.workspace = true +serde_json = "1.0.59" serde_path_to_error = "0.1.17" -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs index 126f0251239..05783fde1ad 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_trusty.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { description: Some("ARM64 Trusty".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs index 8f93523909e..7292412a18d 100644 --- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs +++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs @@ -20,9 +20,9 @@ pub(crate) fn target() -> Target { llvm_target: "arm64ec-pc-windows-msvc".into(), metadata: TargetMetadata { description: Some("Arm64EC Windows MSVC".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), - std: None, // ? + std: Some(true), }, pointer_width: 64, data_layout: diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs index 31d492e83cd..2b0b0e1d117 100644 --- a/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_trusty.rs @@ -13,7 +13,7 @@ pub(crate) fn target() -> Target { description: Some("Armv7-A Trusty".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs index c7b002bc9bb..dbcb5fd4e11 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_trusty.rs @@ -12,7 +12,7 @@ pub(crate) fn target() -> Target { description: Some("x86_64 Trusty".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 64, data_layout: diff --git a/compiler/rustc_thread_pool/Cargo.toml b/compiler/rustc_thread_pool/Cargo.toml index 8e8c6469512..c92984470b7 100644 --- a/compiler/rustc_thread_pool/Cargo.toml +++ b/compiler/rustc_thread_pool/Cargo.toml @@ -20,10 +20,10 @@ smallvec = "1.8.1" [dev-dependencies] rand = "0.9" rand_xorshift = "0.4" -scoped-tls.workspace = true +scoped-tls = "1.0" [target.'cfg(unix)'.dev-dependencies] -libc.workspace = true +libc = "0.2" [[test]] name = "stack_overflow_crash" diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 6b79b98d1bf..1071105522d 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -21,6 +21,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2" +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index d768e0bf63f..bc984f30472 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3,7 +3,8 @@ use std::borrow::Cow; use std::path::PathBuf; use rustc_abi::ExternAbi; -use rustc_ast::TraitObjectSyntax; +use rustc_ast::ast::LitKind; +use rustc_ast::{LitIntType, TraitObjectSyntax}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -280,6 +281,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (suggested, noted_missing_impl) = self.try_conversion_context(&obligation, main_trait_predicate, &mut err); } + suggested |= self.detect_negative_literal( + &obligation, + main_trait_predicate, + &mut err, + ); + if let Some(ret_span) = self.return_type_span(&obligation) { if is_try_conversion { let ty = self.tcx.short_string( @@ -950,6 +957,38 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Ok(()) } + fn detect_negative_literal( + &self, + obligation: &PredicateObligation<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, + err: &mut Diag<'_>, + ) -> bool { + if let ObligationCauseCode::UnOp { hir_id, .. } = obligation.cause.code() + && let hir::Node::Expr(expr) = self.tcx.hir_node(*hir_id) + && let hir::ExprKind::Unary(hir::UnOp::Neg, inner) = expr.kind + && let hir::ExprKind::Lit(lit) = inner.kind + && let LitKind::Int(_, LitIntType::Unsuffixed) = lit.node + { + err.span_suggestion_verbose( + lit.span.shrink_to_hi(), + "consider specifying an integer type that can be negative", + match trait_pred.skip_binder().self_ty().kind() { + ty::Uint(ty::UintTy::Usize) => "isize", + ty::Uint(ty::UintTy::U8) => "i8", + ty::Uint(ty::UintTy::U16) => "i16", + ty::Uint(ty::UintTy::U32) => "i32", + ty::Uint(ty::UintTy::U64) => "i64", + ty::Uint(ty::UintTy::U128) => "i128", + _ => "i64", + } + .to_string(), + Applicability::MaybeIncorrect, + ); + return true; + } + false + } + /// When the `E` of the resulting `Result<T, E>` in an expression `foo().bar().baz()?`, /// identify those method chain sub-expressions that could or could not have been annotated /// with `?`. @@ -2730,9 +2769,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { suggested: bool, ) { let body_def_id = obligation.cause.body_id; - let span = if let ObligationCauseCode::BinOp { rhs_span: Some(rhs_span), .. } = - obligation.cause.code() - { + let span = if let ObligationCauseCode::BinOp { rhs_span, .. } = obligation.cause.code() { *rhs_span } else { span diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index aa153d3607b..40a27c9aebe 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -554,7 +554,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return true; } } else if let ( - ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id: Some(rhs_hir_id), .. }, + ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, .. }, predicate, ) = code.peel_derives_with_predicate() && let Some(typeck_results) = &self.typeck_results @@ -2801,6 +2801,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::QuestionMark | ObligationCauseCode::CheckAssociatedTypeBounds { .. } | ObligationCauseCode::LetElse + | ObligationCauseCode::UnOp { .. } | ObligationCauseCode::BinOp { .. } | ObligationCauseCode::AscribeUserTypeProvePredicate(..) | ObligationCauseCode::AlwaysApplicableImpl @@ -3839,9 +3840,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) { let rhs_span = match obligation.cause.code() { - ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { - span - } + ObligationCauseCode::BinOp { rhs_span, rhs_is_lit, .. } if *rhs_is_lit => rhs_span, _ => return, }; if let ty::Float(_) = trait_pred.skip_binder().self_ty().kind() @@ -5108,16 +5107,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let tcx = self.tcx; let predicate = predicate.upcast(tcx); match *cause_code { - ObligationCauseCode::BinOp { - lhs_hir_id, - rhs_hir_id: Some(rhs_hir_id), - rhs_span: Some(rhs_span), - .. - } if let Some(typeck_results) = &self.typeck_results - && let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id) - && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id) - && let Some(lhs_ty) = typeck_results.expr_ty_opt(lhs) - && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) => + ObligationCauseCode::BinOp { lhs_hir_id, rhs_hir_id, rhs_span, .. } + if let Some(typeck_results) = &self.typeck_results + && let hir::Node::Expr(lhs) = tcx.hir_node(lhs_hir_id) + && let hir::Node::Expr(rhs) = tcx.hir_node(rhs_hir_id) + && let Some(lhs_ty) = typeck_results.expr_ty_opt(lhs) + && let Some(rhs_ty) = typeck_results.expr_ty_opt(rhs) => { if let Some(pred) = predicate.as_trait_clause() && tcx.is_lang_item(pred.def_id(), LangItem::PartialEq) diff --git a/compiler/rustc_trait_selection/src/solve.rs b/compiler/rustc_trait_selection/src/solve.rs index f58961683a9..5d200c4d340 100644 --- a/compiler/rustc_trait_selection/src/solve.rs +++ b/compiler/rustc_trait_selection/src/solve.rs @@ -13,4 +13,20 @@ pub use normalize::{ deeply_normalize, deeply_normalize_with_skipped_universes, deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals, }; +use rustc_middle::query::Providers; +use rustc_middle::ty::TyCtxt; pub use select::InferCtxtSelectExt; + +fn evaluate_root_goal_for_proof_tree_raw<'tcx>( + tcx: TyCtxt<'tcx>, + canonical_input: CanonicalInput<TyCtxt<'tcx>>, +) -> (QueryResult<TyCtxt<'tcx>>, &'tcx inspect::Probe<TyCtxt<'tcx>>) { + evaluate_root_goal_for_proof_tree_raw_provider::<SolverDelegate<'tcx>, TyCtxt<'tcx>>( + tcx, + canonical_input, + ) +} + +pub fn provide(providers: &mut Providers) { + *providers = Providers { evaluate_root_goal_for_proof_tree_raw, ..*providers }; +} diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 308486811e6..342d7121fc3 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -37,7 +37,7 @@ pub struct InspectGoal<'a, 'tcx> { orig_values: Vec<ty::GenericArg<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>, result: Result<Certainty, NoSolution>, - evaluation_kind: inspect::GoalEvaluationKind<TyCtxt<'tcx>>, + final_revision: &'tcx inspect::Probe<TyCtxt<'tcx>>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, source: GoalSource, } @@ -249,7 +249,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { // `InspectGoal::new` so that the goal has the right result (and maintains // the impression that we don't do this normalizes-to infer hack at all). let (nested, proof_tree) = infcx.evaluate_root_goal_for_proof_tree(goal, span); - let nested_goals_result = nested.and_then(|(nested, _)| { + let nested_goals_result = nested.and_then(|nested| { normalizes_to_term_hack.constrain_and( infcx, span, @@ -391,15 +391,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { pub fn candidates(&'a self) -> Vec<InspectCandidate<'a, 'tcx>> { let mut candidates = vec![]; - let last_eval_step = match &self.evaluation_kind { - // An annoying edge case in case the recursion limit is 0. - inspect::GoalEvaluationKind::Overflow => return vec![], - inspect::GoalEvaluationKind::Evaluation { final_revision } => final_revision, - }; - let mut nested_goals = vec![]; - self.candidates_recur(&mut candidates, &mut nested_goals, &last_eval_step); - + self.candidates_recur(&mut candidates, &mut nested_goals, &self.final_revision); candidates } @@ -426,7 +419,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { ) -> Self { let infcx = <&SolverDelegate<'tcx>>::from(infcx); - let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, kind, result } = root; + let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, final_revision, result } = + root; // If there's a normalizes-to goal, AND the evaluation result with the result of // constraining the normalizes-to RHS and computing the nested goals. let result = result.and_then(|ok| { @@ -441,7 +435,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { orig_values, goal: eager_resolve_vars(infcx, uncanonicalized_goal), result, - evaluation_kind: kind, + final_revision, normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n), source, } diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml index 24360a94cc7..9f40f4d5c23 100644 --- a/compiler/rustc_traits/Cargo.toml +++ b/compiler/rustc_traits/Cargo.toml @@ -10,5 +10,5 @@ rustc_infer = { path = "../rustc_infer" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 2ac2b46cc58..e61717e5e9c 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -11,12 +11,12 @@ rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = "1.8.1" -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end [dev-dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 394cde5a323..ce08b300cc8 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -itertools.workspace = true +itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -20,5 +20,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -tracing.workspace = true +tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 42860fa2d88..d55e9b3b1be 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -5,11 +5,11 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -bitflags.workspace = true -derive-where.workspace = true +bitflags = "2.4.1" +derive-where = "1.2.7" ena = "0.14.3" -indexmap.workspace = true -rustc-hash.workspace = true +indexmap = "2.0.0" +rustc-hash = "2.0.0" rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_error_messages = { path = "../rustc_error_messages", optional = true } @@ -19,8 +19,8 @@ rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } smallvec = { version = "1.8.1", default-features = false, features = ["const_generics"] } -thin-vec.workspace = true -tracing.workspace = true +thin-vec = "0.2.12" +tracing = "0.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 21fe7879b29..f5448baf8c0 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -10,7 +10,9 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::lang_items::{SolverLangItem, SolverTraitLangItem}; use crate::relate::Relate; -use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; +use crate::solve::{ + CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult, inspect, +}; use crate::visit::{Flags, TypeVisitable}; use crate::{self as ty, CanonicalParamEnvCacheEntry, search_graph}; @@ -380,6 +382,13 @@ pub trait Interner: self, defining_anchor: Self::LocalDefId, ) -> Self::LocalDefIds; + + type ProbeRef: Copy + Debug + Hash + Eq + Deref<Target = inspect::Probe<Self>>; + fn mk_probe_ref(self, probe: inspect::Probe<Self>) -> Self::ProbeRef; + fn evaluate_root_goal_for_proof_tree_raw( + self, + canonical_goal: CanonicalInput<Self>, + ) -> (QueryResult<Self>, Self::ProbeRef); } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 348178a527f..dbbc0c217d7 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -92,11 +92,7 @@ pub trait Delegate: Sized { input: <Self::Cx as Cx>::Input, result: <Self::Cx as Cx>::Result, ) -> bool; - fn on_stack_overflow( - cx: Self::Cx, - input: <Self::Cx as Cx>::Input, - inspect: &mut Self::ProofTreeBuilder, - ) -> <Self::Cx as Cx>::Result; + fn on_stack_overflow(cx: Self::Cx, input: <Self::Cx as Cx>::Input) -> <Self::Cx as Cx>::Result; fn on_fixpoint_overflow( cx: Self::Cx, input: <Self::Cx as Cx>::Input, @@ -703,6 +699,31 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { } } + pub fn evaluate_root_goal_for_proof_tree( + cx: X, + root_depth: usize, + input: X::Input, + inspect: &mut D::ProofTreeBuilder, + ) -> X::Result { + let mut this = SearchGraph::<D>::new(root_depth); + let available_depth = AvailableDepth(root_depth); + let step_kind_from_parent = PathKind::Inductive; // is never used + this.stack.push(StackEntry { + input, + step_kind_from_parent, + available_depth, + provisional_result: None, + required_depth: 0, + heads: Default::default(), + encountered_overflow: false, + usages: None, + candidate_usages: None, + nested_goals: Default::default(), + }); + let evaluation_result = this.evaluate_goal_in_task(cx, input, inspect); + evaluation_result.result + } + /// Probably the most involved method of the whole solver. /// /// While goals get computed via `D::compute_goal`, this function handles @@ -718,7 +739,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { let Some(available_depth) = AvailableDepth::allowed_depth_for_nested::<D>(self.root_depth, &self.stack) else { - return self.handle_overflow(cx, input, inspect); + return self.handle_overflow(cx, input); }; // We check the provisional cache before checking the global cache. This simplifies @@ -833,12 +854,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { result } - fn handle_overflow( - &mut self, - cx: X, - input: X::Input, - inspect: &mut D::ProofTreeBuilder, - ) -> X::Result { + fn handle_overflow(&mut self, cx: X, input: X::Input) -> X::Result { if let Some(last) = self.stack.last_mut() { last.encountered_overflow = true; // If computing a goal `B` depends on another goal `A` and @@ -853,7 +869,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> { } debug!("encountered stack overflow"); - D::on_stack_overflow(cx, input, inspect) + D::on_stack_overflow(cx, input) } /// When reevaluating a goal with a changed provisional result, all provisional cache entry diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index afb4043648f..5452ac44158 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -45,31 +45,18 @@ pub type CanonicalState<I, T> = Canonical<I, State<I, T>>; /// for the `CanonicalVarValues` of the canonicalized goal. /// We use this to map any [CanonicalState] from the local `InferCtxt` /// of the solver query to the `InferCtxt` of the caller. -#[derive_where(PartialEq, Hash; I: Interner)] +#[derive_where(PartialEq, Eq, Hash; I: Interner)] pub struct GoalEvaluation<I: Interner> { pub uncanonicalized_goal: Goal<I, I::Predicate>, pub orig_values: Vec<I::GenericArg>, - pub kind: GoalEvaluationKind<I>, + pub final_revision: I::ProbeRef, pub result: QueryResult<I>, } -impl<I: Interner> Eq for GoalEvaluation<I> {} - -#[derive_where(PartialEq, Hash, Debug; I: Interner)] -pub enum GoalEvaluationKind<I: Interner> { - Overflow, - Evaluation { - /// This is always `ProbeKind::Root`. - final_revision: Probe<I>, - }, -} - -impl<I: Interner> Eq for GoalEvaluationKind<I> {} - /// A self-contained computation during trait solving. This either /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation /// of a goal. -#[derive_where(PartialEq, Hash, Debug; I: Interner)] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub struct Probe<I: Interner> { /// What happened inside of this probe in chronological order. pub steps: Vec<ProbeStep<I>>, @@ -77,9 +64,7 @@ pub struct Probe<I: Interner> { pub final_state: CanonicalState<I, ()>, } -impl<I: Interner> Eq for Probe<I> {} - -#[derive_where(PartialEq, Hash, Debug; I: Interner)] +#[derive_where(PartialEq, Eq, Hash, Debug; I: Interner)] pub enum ProbeStep<I: Interner> { /// We added a goal to the `EvalCtxt` which will get proven /// the next time `EvalCtxt::try_evaluate_added_goals` is called. @@ -98,12 +83,10 @@ pub enum ProbeStep<I: Interner> { MakeCanonicalResponse { shallow_certainty: Certainty }, } -impl<I: Interner> Eq for ProbeStep<I> {} - /// What kind of probe we're in. In case the probe represents a candidate, or /// the final result of the current goal - via [ProbeKind::Root] - we also /// store the [QueryResult]. -#[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] +#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub enum ProbeKind<I: Interner> { /// The root inference context while proving a goal. @@ -128,5 +111,3 @@ pub enum ProbeKind<I: Interner> { /// Checking that a rigid alias is well-formed. RigidAlias { result: QueryResult<I> }, } - -impl<I: Interner> Eq for ProbeKind<I> {} diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml index 29a2cc89033..15a55575099 100644 --- a/compiler/rustc_type_ir_macros/Cargo.toml +++ b/compiler/rustc_type_ir_macros/Cargo.toml @@ -8,8 +8,8 @@ proc-macro = true [dependencies] # tidy-alphabetical-start -proc-macro2.workspace = true -quote.workspace = true +proc-macro2 = "1" +quote = "1" syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 7489a8bb6e7..73b74d53323 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -99,7 +99,8 @@ pub enum ControlFlow<B, C = ()> { } #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] -impl<B, C> ops::Try for ControlFlow<B, C> { +#[rustc_const_unstable(feature = "const_try", issue = "74935")] +impl<B, C> const ops::Try for ControlFlow<B, C> { type Output = C; type Residual = ControlFlow<B, convert::Infallible>; @@ -118,9 +119,10 @@ impl<B, C> ops::Try for ControlFlow<B, C> { } #[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")] +#[rustc_const_unstable(feature = "const_try", issue = "74935")] // Note: manually specifying the residual type instead of using the default to work around // https://github.com/rust-lang/rust/issues/99940 -impl<B, C> ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> { +impl<B, C> const ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> { #[inline] fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self { match residual { diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index 95d1e2069ac..c0a27775694 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -736,6 +736,31 @@ impl<T> Bound<T> { } } +impl<T: Copy> Bound<&T> { + /// Map a `Bound<&T>` to a `Bound<T>` by copying the contents of the bound. + /// + /// # Examples + /// + /// ``` + /// #![feature(bound_copied)] + /// + /// use std::ops::Bound::*; + /// use std::ops::RangeBounds; + /// + /// assert_eq!((1..12).start_bound(), Included(&1)); + /// assert_eq!((1..12).start_bound().copied(), Included(1)); + /// ``` + #[unstable(feature = "bound_copied", issue = "145966")] + #[must_use] + pub fn copied(self) -> Bound<T> { + match self { + Bound::Unbounded => Bound::Unbounded, + Bound::Included(x) => Bound::Included(*x), + Bound::Excluded(x) => Bound::Excluded(*x), + } + } +} + impl<T: Clone> Bound<&T> { /// Map a `Bound<&T>` to a `Bound<T>` by cloning the contents of the bound. /// @@ -745,8 +770,11 @@ impl<T: Clone> Bound<&T> { /// use std::ops::Bound::*; /// use std::ops::RangeBounds; /// - /// assert_eq!((1..12).start_bound(), Included(&1)); - /// assert_eq!((1..12).start_bound().cloned(), Included(1)); + /// let a1 = String::from("a"); + /// let (a2, a3, a4) = (a1.clone(), a1.clone(), a1.clone()); + /// + /// assert_eq!(Included(&a1), (a2..).start_bound()); + /// assert_eq!(Included(a3), (a4..).start_bound().cloned()); /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "bound_cloned", since = "1.55.0")] diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs index ac4a2066530..c173d7f0ae0 100644 --- a/library/coretests/tests/floats/f128.rs +++ b/library/coretests/tests/floats/f128.rs @@ -1,18 +1,18 @@ // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(target_has_reliable_f128)] -use std::f128::consts; - use super::{assert_approx_eq, assert_biteq}; // Note these tolerances make sense around zero, but not for more extreme exponents. /// Default tolerances. Works for values that should be near precise but not exact. Roughly /// the precision carried by `100 * 100`. +#[allow(unused)] const TOL: f128 = 1e-12; /// For operations that are near exact, usually not involving math of different /// signs. +#[allow(unused)] const TOL_PRECISE: f128 = 1e-28; /// First pattern over the mantissa @@ -44,70 +44,12 @@ fn test_mul_add() { #[test] #[cfg(any(miri, target_has_reliable_f128_math))] -fn test_recip() { - let nan: f128 = f128::NAN; - let inf: f128 = f128::INFINITY; - let neg_inf: f128 = f128::NEG_INFINITY; - assert_biteq!(1.0f128.recip(), 1.0); - assert_biteq!(2.0f128.recip(), 0.5); - assert_biteq!((-0.4f128).recip(), -2.5); - assert_biteq!(0.0f128.recip(), inf); +fn test_max_recip() { assert_approx_eq!( f128::MAX.recip(), 8.40525785778023376565669454330438228902076605e-4933, 1e-4900 ); - assert!(nan.recip().is_nan()); - assert_biteq!(inf.recip(), 0.0); - assert_biteq!(neg_inf.recip(), -0.0); -} - -#[test] -#[cfg(not(miri))] -#[cfg(target_has_reliable_f128_math)] -fn test_powi() { - let nan: f128 = f128::NAN; - let inf: f128 = f128::INFINITY; - let neg_inf: f128 = f128::NEG_INFINITY; - assert_biteq!(1.0f128.powi(1), 1.0); - assert_approx_eq!((-3.1f128).powi(2), 9.6100000000000005506706202140776519387, TOL); - assert_approx_eq!(5.9f128.powi(-2), 0.028727377190462507313100483690639638451, TOL); - assert_biteq!(8.3f128.powi(0), 1.0); - assert!(nan.powi(2).is_nan()); - assert_biteq!(inf.powi(3), inf); - assert_biteq!(neg_inf.powi(2), inf); -} - -#[test] -fn test_to_degrees() { - let pi: f128 = consts::PI; - let nan: f128 = f128::NAN; - let inf: f128 = f128::INFINITY; - let neg_inf: f128 = f128::NEG_INFINITY; - assert_biteq!(0.0f128.to_degrees(), 0.0); - assert_approx_eq!((-5.8f128).to_degrees(), -332.31552117587745090765431723855668471, TOL); - assert_approx_eq!(pi.to_degrees(), 180.0, TOL); - assert!(nan.to_degrees().is_nan()); - assert_biteq!(inf.to_degrees(), inf); - assert_biteq!(neg_inf.to_degrees(), neg_inf); - assert_biteq!(1_f128.to_degrees(), 57.2957795130823208767981548141051703); -} - -#[test] -fn test_to_radians() { - let pi: f128 = consts::PI; - let nan: f128 = f128::NAN; - let inf: f128 = f128::INFINITY; - let neg_inf: f128 = f128::NEG_INFINITY; - assert_biteq!(0.0f128.to_radians(), 0.0); - assert_approx_eq!(154.6f128.to_radians(), 2.6982790235832334267135442069489767804, TOL); - assert_approx_eq!((-332.31f128).to_radians(), -5.7999036373023566567593094812182763013, TOL); - // check approx rather than exact because round trip for pi doesn't fall on an exactly - // representable value (unlike `f32` and `f64`). - assert_approx_eq!(180.0f128.to_radians(), pi, TOL_PRECISE); - assert!(nan.to_radians().is_nan()); - assert_biteq!(inf.to_radians(), inf); - assert_biteq!(neg_inf.to_radians(), neg_inf); } #[test] diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs index bb9c8a002fe..c12de7221ba 100644 --- a/library/coretests/tests/floats/f16.rs +++ b/library/coretests/tests/floats/f16.rs @@ -1,8 +1,6 @@ // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(target_has_reliable_f16)] -use std::f16::consts; - use super::{assert_approx_eq, assert_biteq}; /// Tolerance for results on the order of 10.0e-2 @@ -50,64 +48,8 @@ fn test_mul_add() { #[test] #[cfg(any(miri, target_has_reliable_f16_math))] -fn test_recip() { - let nan: f16 = f16::NAN; - let inf: f16 = f16::INFINITY; - let neg_inf: f16 = f16::NEG_INFINITY; - assert_biteq!(1.0f16.recip(), 1.0); - assert_biteq!(2.0f16.recip(), 0.5); - assert_biteq!((-0.4f16).recip(), -2.5); - assert_biteq!(0.0f16.recip(), inf); +fn test_max_recip() { assert_approx_eq!(f16::MAX.recip(), 1.526624e-5f16, 1e-4); - assert!(nan.recip().is_nan()); - assert_biteq!(inf.recip(), 0.0); - assert_biteq!(neg_inf.recip(), -0.0); -} - -#[test] -#[cfg(not(miri))] -#[cfg(target_has_reliable_f16_math)] -fn test_powi() { - let nan: f16 = f16::NAN; - let inf: f16 = f16::INFINITY; - let neg_inf: f16 = f16::NEG_INFINITY; - assert_biteq!(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_biteq!(8.3f16.powi(0), 1.0); - assert!(nan.powi(2).is_nan()); - assert_biteq!(inf.powi(3), inf); - assert_biteq!(neg_inf.powi(2), inf); -} - -#[test] -fn test_to_degrees() { - let pi: f16 = consts::PI; - let nan: f16 = f16::NAN; - let inf: f16 = f16::INFINITY; - let neg_inf: f16 = f16::NEG_INFINITY; - assert_biteq!(0.0f16.to_degrees(), 0.0); - assert_approx_eq!((-5.8f16).to_degrees(), -332.315521, TOL_P2); - assert_approx_eq!(pi.to_degrees(), 180.0, TOL_P2); - assert!(nan.to_degrees().is_nan()); - assert_biteq!(inf.to_degrees(), inf); - assert_biteq!(neg_inf.to_degrees(), neg_inf); - assert_biteq!(1_f16.to_degrees(), 57.2957795130823208767981548141051703); -} - -#[test] -fn test_to_radians() { - let pi: f16 = consts::PI; - let nan: f16 = f16::NAN; - let inf: f16 = f16::INFINITY; - let neg_inf: f16 = f16::NEG_INFINITY; - assert_biteq!(0.0f16.to_radians(), 0.0); - assert_approx_eq!(154.6f16.to_radians(), 2.698279, TOL_0); - assert_approx_eq!((-332.31f16).to_radians(), -5.799903, TOL_0); - assert_approx_eq!(180.0f16.to_radians(), pi, TOL_0); - assert!(nan.to_radians().is_nan()); - assert_biteq!(inf.to_radians(), inf); - assert_biteq!(neg_inf.to_radians(), neg_inf); } #[test] diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs index e77e44655dc..b79295f470d 100644 --- a/library/coretests/tests/floats/f32.rs +++ b/library/coretests/tests/floats/f32.rs @@ -1,5 +1,4 @@ use core::f32; -use core::f32::consts; use super::{assert_approx_eq, assert_biteq}; @@ -9,11 +8,6 @@ const NAN_MASK1: u32 = 0x002a_aaaa; /// Second pattern over the mantissa const NAN_MASK2: u32 = 0x0055_5555; -/// Miri adds some extra errors to float functions; make sure the tests still pass. -/// These values are purely used as a canary to test against and are thus not a stable guarantee Rust provides. -/// They serve as a way to get an idea of the real precision of floating point operations on different platforms. -const APPROX_DELTA: f32 = if cfg!(miri) { 1e-4 } else { 1e-6 }; - // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/ #[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)] #[test] @@ -33,64 +27,6 @@ fn test_mul_add() { } #[test] -fn test_recip() { - let nan: f32 = f32::NAN; - let inf: f32 = f32::INFINITY; - let neg_inf: f32 = f32::NEG_INFINITY; - assert_biteq!(1.0f32.recip(), 1.0); - assert_biteq!(2.0f32.recip(), 0.5); - assert_biteq!((-0.4f32).recip(), -2.5); - assert_biteq!(0.0f32.recip(), inf); - assert!(nan.recip().is_nan()); - assert_biteq!(inf.recip(), 0.0); - assert_biteq!(neg_inf.recip(), -0.0); -} - -#[test] -fn test_powi() { - let nan: f32 = f32::NAN; - let inf: f32 = f32::INFINITY; - let neg_inf: f32 = f32::NEG_INFINITY; - assert_approx_eq!(1.0f32.powi(1), 1.0); - assert_approx_eq!((-3.1f32).powi(2), 9.61, APPROX_DELTA); - assert_approx_eq!(5.9f32.powi(-2), 0.028727); - assert_biteq!(8.3f32.powi(0), 1.0); - assert!(nan.powi(2).is_nan()); - assert_biteq!(inf.powi(3), inf); - assert_biteq!(neg_inf.powi(2), inf); -} - -#[test] -fn test_to_degrees() { - let pi: f32 = consts::PI; - let nan: f32 = f32::NAN; - let inf: f32 = f32::INFINITY; - let neg_inf: f32 = f32::NEG_INFINITY; - assert_biteq!(0.0f32.to_degrees(), 0.0); - assert_approx_eq!((-5.8f32).to_degrees(), -332.315521); - assert_biteq!(pi.to_degrees(), 180.0); - assert!(nan.to_degrees().is_nan()); - assert_biteq!(inf.to_degrees(), inf); - assert_biteq!(neg_inf.to_degrees(), neg_inf); - assert_biteq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703); -} - -#[test] -fn test_to_radians() { - let pi: f32 = consts::PI; - let nan: f32 = f32::NAN; - let inf: f32 = f32::INFINITY; - let neg_inf: f32 = f32::NEG_INFINITY; - assert_biteq!(0.0f32.to_radians(), 0.0); - assert_approx_eq!(154.6f32.to_radians(), 2.698279); - assert_approx_eq!((-332.31f32).to_radians(), -5.799903); - assert_biteq!(180.0f32.to_radians(), pi); - assert!(nan.to_radians().is_nan()); - assert_biteq!(inf.to_radians(), inf); - assert_biteq!(neg_inf.to_radians(), neg_inf); -} - -#[test] fn test_float_bits_conv() { assert_eq!((1f32).to_bits(), 0x3f800000); assert_eq!((12.5f32).to_bits(), 0x41480000); diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs index fea9cc19b39..a2540586328 100644 --- a/library/coretests/tests/floats/f64.rs +++ b/library/coretests/tests/floats/f64.rs @@ -1,5 +1,4 @@ use core::f64; -use core::f64::consts; use super::{assert_approx_eq, assert_biteq}; @@ -28,63 +27,6 @@ fn test_mul_add() { } #[test] -fn test_recip() { - let nan: f64 = f64::NAN; - let inf: f64 = f64::INFINITY; - let neg_inf: f64 = f64::NEG_INFINITY; - assert_biteq!(1.0f64.recip(), 1.0); - assert_biteq!(2.0f64.recip(), 0.5); - assert_biteq!((-0.4f64).recip(), -2.5); - assert_biteq!(0.0f64.recip(), inf); - assert!(nan.recip().is_nan()); - assert_biteq!(inf.recip(), 0.0); - assert_biteq!(neg_inf.recip(), -0.0); -} - -#[test] -fn test_powi() { - let nan: f64 = f64::NAN; - let inf: f64 = f64::INFINITY; - let neg_inf: f64 = f64::NEG_INFINITY; - assert_approx_eq!(1.0f64.powi(1), 1.0); - assert_approx_eq!((-3.1f64).powi(2), 9.61); - assert_approx_eq!(5.9f64.powi(-2), 0.028727); - assert_biteq!(8.3f64.powi(0), 1.0); - assert!(nan.powi(2).is_nan()); - assert_biteq!(inf.powi(3), inf); - assert_biteq!(neg_inf.powi(2), inf); -} - -#[test] -fn test_to_degrees() { - let pi: f64 = consts::PI; - let nan: f64 = f64::NAN; - let inf: f64 = f64::INFINITY; - let neg_inf: f64 = f64::NEG_INFINITY; - assert_biteq!(0.0f64.to_degrees(), 0.0); - assert_approx_eq!((-5.8f64).to_degrees(), -332.315521); - assert_biteq!(pi.to_degrees(), 180.0); - assert!(nan.to_degrees().is_nan()); - assert_biteq!(inf.to_degrees(), inf); - assert_biteq!(neg_inf.to_degrees(), neg_inf); -} - -#[test] -fn test_to_radians() { - let pi: f64 = consts::PI; - let nan: f64 = f64::NAN; - let inf: f64 = f64::INFINITY; - let neg_inf: f64 = f64::NEG_INFINITY; - assert_biteq!(0.0f64.to_radians(), 0.0); - assert_approx_eq!(154.6f64.to_radians(), 2.698279); - assert_approx_eq!((-332.31f64).to_radians(), -5.799903); - assert_biteq!(180.0f64.to_radians(), pi); - assert!(nan.to_radians().is_nan()); - assert_biteq!(inf.to_radians(), inf); - assert_biteq!(neg_inf.to_radians(), neg_inf); -} - -#[test] fn test_float_bits_conv() { assert_eq!((1f64).to_bits(), 0x3ff0000000000000); assert_eq!((12.5f64).to_bits(), 0x4029000000000000); diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 2c2a07920d0..5f59cb9cce3 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -1,13 +1,20 @@ use std::num::FpCategory as Fp; use std::ops::{Add, Div, Mul, Rem, Sub}; -trait TestableFloat { +trait TestableFloat: Sized { /// Unsigned int with the same size, for converting to/from bits. type Int; /// Set the default tolerance for float comparison based on the type. const APPROX: Self; + /// Allow looser tolerance for f32 on miri + const POWI_APPROX: Self = Self::APPROX; + /// Allow looser tolerance for f16 + const _180_TO_RADIANS_APPROX: Self = Self::APPROX; + /// Allow for looser tolerance for f16 + const PI_TO_DEGREES_APPROX: Self = Self::APPROX; const ZERO: Self; const ONE: Self; + const PI: Self; const MIN_POSITIVE_NORMAL: Self; const MAX_SUBNORMAL: Self; /// Smallest number @@ -25,8 +32,11 @@ trait TestableFloat { impl TestableFloat for f16 { type Int = u16; const APPROX: Self = 1e-3; + const _180_TO_RADIANS_APPROX: Self = 1e-2; + const PI_TO_DEGREES_APPROX: Self = 0.125; const ZERO: Self = 0.0; const ONE: Self = 1.0; + const PI: Self = std::f16::consts::PI; const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE; const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down(); const TINY: Self = Self::from_bits(0x1); @@ -39,8 +49,13 @@ impl TestableFloat for f16 { impl TestableFloat for f32 { type Int = u32; const APPROX: Self = 1e-6; + /// Miri adds some extra errors to float functions; make sure the tests still pass. + /// These values are purely used as a canary to test against and are thus not a stable guarantee Rust provides. + /// They serve as a way to get an idea of the real precision of floating point operations on different platforms. + const POWI_APPROX: Self = if cfg!(miri) { 1e-4 } else { Self::APPROX }; const ZERO: Self = 0.0; const ONE: Self = 1.0; + const PI: Self = std::f32::consts::PI; const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE; const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down(); const TINY: Self = Self::from_bits(0x1); @@ -55,6 +70,7 @@ impl TestableFloat for f64 { const APPROX: Self = 1e-6; const ZERO: Self = 0.0; const ONE: Self = 1.0; + const PI: Self = std::f64::consts::PI; const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE; const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down(); const TINY: Self = Self::from_bits(0x1); @@ -69,6 +85,7 @@ impl TestableFloat for f128 { const APPROX: Self = 1e-9; const ZERO: Self = 0.0; const ONE: Self = 1.0; + const PI: Self = std::f128::consts::PI; const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE; const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down(); const TINY: Self = Self::from_bits(0x1); @@ -1340,3 +1357,86 @@ float_test! { assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &s_nan())); } } + +float_test! { + name: recip, + attrs: { + f16: #[cfg(any(miri, target_has_reliable_f16_math))], + f128: #[cfg(any(miri, target_has_reliable_f128_math))], + }, + test<Float> { + let nan: Float = Float::NAN; + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + assert_biteq!((1.0 as Float).recip(), 1.0); + assert_biteq!((2.0 as Float).recip(), 0.5); + assert_biteq!((-0.4 as Float).recip(), -2.5); + assert_biteq!((0.0 as Float).recip(), inf); + assert!(nan.recip().is_nan()); + assert_biteq!(inf.recip(), 0.0); + assert_biteq!(neg_inf.recip(), -0.0); + } +} + +float_test! { + name: powi, + attrs: { + const: #[cfg(false)], + f16: #[cfg(all(not(miri), target_has_reliable_f16_math))], + f128: #[cfg(all(not(miri), target_has_reliable_f128_math))], + }, + test<Float> { + let nan: Float = Float::NAN; + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + assert_approx_eq!(Float::ONE.powi(1), Float::ONE); + assert_approx_eq!((-3.1 as Float).powi(2), 9.6100000000000005506706202140776519387, Float::POWI_APPROX); + assert_approx_eq!((5.9 as Float).powi(-2), 0.028727377190462507313100483690639638451); + assert_biteq!((8.3 as Float).powi(0), Float::ONE); + assert!(nan.powi(2).is_nan()); + assert_biteq!(inf.powi(3), inf); + assert_biteq!(neg_inf.powi(2), inf); + } +} + +float_test! { + name: to_degrees, + attrs: { + f16: #[cfg(target_has_reliable_f16)], + f128: #[cfg(target_has_reliable_f128)], + }, + test<Float> { + let pi: Float = Float::PI; + let nan: Float = Float::NAN; + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + assert_biteq!((0.0 as Float).to_degrees(), 0.0); + assert_approx_eq!((-5.8 as Float).to_degrees(), -332.31552117587745090765431723855668471); + assert_approx_eq!(pi.to_degrees(), 180.0, Float::PI_TO_DEGREES_APPROX); + assert!(nan.to_degrees().is_nan()); + assert_biteq!(inf.to_degrees(), inf); + assert_biteq!(neg_inf.to_degrees(), neg_inf); + assert_biteq!((1.0 as Float).to_degrees(), 57.2957795130823208767981548141051703); + } +} + +float_test! { + name: to_radians, + attrs: { + f16: #[cfg(target_has_reliable_f16)], + f128: #[cfg(target_has_reliable_f128)], + }, + test<Float> { + let pi: Float = Float::PI; + let nan: Float = Float::NAN; + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + assert_biteq!((0.0 as Float).to_radians(), 0.0); + assert_approx_eq!((154.6 as Float).to_radians(), 2.6982790235832334267135442069489767804); + assert_approx_eq!((-332.31 as Float).to_radians(), -5.7999036373023566567593094812182763013); + assert_approx_eq!((180.0 as Float).to_radians(), pi, Float::_180_TO_RADIANS_APPROX); + assert!(nan.to_radians().is_nan()); + assert_biteq!(inf.to_radians(), inf); + assert_biteq!(neg_inf.to_radians(), neg_inf); + } +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3771699c59f..7bdc6ff7882 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -290,7 +290,6 @@ #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -#![feature(extended_varargs_abi_support)] #![feature(f16)] #![feature(f128)] #![feature(ffi_const)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index 87a3fc80dfa..8b7282c51d1 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -819,7 +819,7 @@ fn panic_with_hook( rtprintpanic!("aborting due to panic at {location}:\n{payload}\n"); } } - crate::sys::abort_internal(); + crate::process::abort(); } match *HOOK.read().unwrap_or_else(PoisonError::into_inner) { @@ -853,7 +853,7 @@ fn panic_with_hook( // through a nounwind function (e.g. extern "C") then we cannot continue // unwinding and have to abort immediately. rtprintpanic!("thread caused non-unwinding panic. aborting.\n"); - crate::sys::abort_internal(); + crate::process::abort(); } rust_panic(payload) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 373584d0117..48265de90c4 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -2495,6 +2495,7 @@ pub fn exit(code: i32) -> ! { #[stable(feature = "process_abort", since = "1.17.0")] #[cold] #[cfg_attr(not(test), rustc_diagnostic_item = "process_abort")] +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn abort() -> ! { crate::sys::abort_internal(); } diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 400128acf12..ac5c823a1bf 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -364,6 +364,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> { // multithreaded C program. It is much less severe for Rust, because Rust // stdlib doesn't use libc stdio buffering. In a typical Rust program, which // does not use C stdio, even a buggy libc::abort() is, in fact, safe. +#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn abort_internal() -> ! { unsafe { libc::abort() } } diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 10ad4541bed..3b6a86cbc8f 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -356,6 +356,7 @@ pub fn abort_internal() -> ! { } #[cfg(miri)] +#[track_caller] // even without panics, this helps for Miri backtraces pub fn abort_internal() -> ! { crate::intrinsics::abort(); } diff --git a/library/std/tests/floats/f32.rs b/library/std/tests/floats/f32.rs index 38c906c1d87..c61a8ec4d20 100644 --- a/library/std/tests/floats/f32.rs +++ b/library/std/tests/floats/f32.rs @@ -79,8 +79,8 @@ fn test_log() { let nan: f32 = f32::NAN; let inf: f32 = f32::INFINITY; let neg_inf: f32 = f32::NEG_INFINITY; - assert_approx_eq!(10.0f32.log(10.0), 1.0); - assert_approx_eq!(2.3f32.log(3.5), 0.664858); + assert_approx_eq!(10.0f32.log(10.0), 1.0, APPROX_DELTA); + assert_approx_eq!(2.3f32.log(3.5), 0.664858, APPROX_DELTA); assert_approx_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0, APPROX_DELTA); assert!(1.0f32.log(1.0).is_nan()); assert!(1.0f32.log(-13.9).is_nan()); diff --git a/src/doc/rustc/src/platform-support/vxworks.md b/src/doc/rustc/src/platform-support/vxworks.md index 3fccee80722..091c757a2ee 100644 --- a/src/doc/rustc/src/platform-support/vxworks.md +++ b/src/doc/rustc/src/platform-support/vxworks.md @@ -20,6 +20,7 @@ Target triplets available: ## Target maintainers [@biabbas](https://github.com/biabbas) +[@hax0kartik](https://github.com/hax0kartik) ## Requirements diff --git a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md b/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md deleted file mode 100644 index b20c30ec8f1..00000000000 --- a/src/doc/unstable-book/src/language-features/extended-varargs-abi-support.md +++ /dev/null @@ -1,10 +0,0 @@ -# `extended_varargs_abi_support` - -The tracking issue for this feature is: [#100189] - -[#100189]: https://github.com/rust-lang/rust/issues/100189 - ------------------------- - -This feature adds the possibility of using `sysv64`, `win64` or `efiapi` calling -conventions on functions with varargs. diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 2985971a053..5d36ffc2d3a 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,20 +12,20 @@ path = "lib.rs" arrayvec = { version = "0.7", default-features = false } askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] } base64 = "0.21.7" -indexmap.workspace = true -itertools.workspace = true +indexmap = "2" +itertools = "0.12" minifier = { version = "0.3.5", default-features = false } pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0" smallvec = "1.8.1" stringdex = { version = "0.0.1-alpha4" } -tempfile.workspace = true +tempfile = "3" threadpool = "1.8.1" +tracing = "0.1" tracing-tree = "0.3.0" -tracing.workspace = true unicode-segmentation = "1.9" # tidy-alphabetical-end diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4ff94cc6f3b..93932936a2e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -557,7 +557,7 @@ fn clean_generic_param_def( }, ) } - ty::GenericParamDefKind::Const { has_default, synthetic } => ( + ty::GenericParamDefKind::Const { has_default } => ( def.name, GenericParamDefKind::Const { ty: Box::new(clean_middle_ty( @@ -580,7 +580,6 @@ fn clean_generic_param_def( } else { None }, - synthetic, }, ), }; @@ -636,14 +635,13 @@ fn clean_generic_param<'tcx>( }, ) } - hir::GenericParamKind::Const { ty, default, synthetic } => ( + hir::GenericParamKind::Const { ty, default } => ( param.name.ident().name, GenericParamDefKind::Const { ty: Box::new(clean_ty(ty, cx)), default: default.map(|ct| { Box::new(lower_const_arg_for_rustdoc(cx.tcx, ct, FeedConstTy::No).to_string()) }), - synthetic, }, ), }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index fcff15650ce..dcd67cb7ebc 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1396,7 +1396,7 @@ pub(crate) enum GenericParamDefKind { Lifetime { outlives: ThinVec<Lifetime> }, Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool }, // Option<Box<String>> makes this type smaller than `Option<String>` would. - Const { ty: Box<Type>, default: Option<Box<String>>, synthetic: bool }, + Const { ty: Box<Type>, default: Option<Box<String>> }, } impl GenericParamDefKind { diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index e94ef517309..ab40c01cb36 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -8,6 +8,9 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use crate::clean; +macro_rules! item_type { + ($($variant:ident = $number:literal,)+) => { + /// Item type. Corresponds to `clean::ItemEnum` variants. /// /// The search index uses item types encoded as smaller numbers which equal to @@ -29,6 +32,44 @@ use crate::clean; #[derive(Copy, PartialEq, Eq, Hash, Clone, Debug, PartialOrd, Ord)] #[repr(u8)] pub(crate) enum ItemType { + $($variant = $number,)+ +} + +impl Serialize for ItemType { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + (*self as u8).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for ItemType { + fn deserialize<D>(deserializer: D) -> Result<ItemType, D::Error> + where + D: Deserializer<'de>, + { + struct ItemTypeVisitor; + impl<'de> de::Visitor<'de> for ItemTypeVisitor { + type Value = ItemType; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "an integer between 0 and 27") + } + fn visit_u64<E: de::Error>(self, v: u64) -> Result<ItemType, E> { + Ok(match v { + $($number => ItemType::$variant,)+ + _ => return Err(E::missing_field("unknown number for `ItemType` enum")), + }) + } + } + deserializer.deserialize_any(ItemTypeVisitor) + } +} + + } +} + +item_type! { Keyword = 0, Primitive = 1, Module = 2, @@ -60,61 +101,6 @@ pub(crate) enum ItemType { Attribute = 27, } -impl Serialize for ItemType { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: Serializer, - { - (*self as u8).serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for ItemType { - fn deserialize<D>(deserializer: D) -> Result<ItemType, D::Error> - where - D: Deserializer<'de>, - { - struct ItemTypeVisitor; - impl<'de> de::Visitor<'de> for ItemTypeVisitor { - type Value = ItemType; - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "an integer between 0 and 25") - } - fn visit_u64<E: de::Error>(self, v: u64) -> Result<ItemType, E> { - Ok(match v { - 0 => ItemType::Keyword, - 1 => ItemType::Primitive, - 2 => ItemType::Module, - 3 => ItemType::ExternCrate, - 4 => ItemType::Import, - 5 => ItemType::Struct, - 6 => ItemType::Enum, - 7 => ItemType::Function, - 8 => ItemType::TypeAlias, - 9 => ItemType::Static, - 10 => ItemType::Trait, - 11 => ItemType::Impl, - 12 => ItemType::TyMethod, - 13 => ItemType::Method, - 14 => ItemType::StructField, - 15 => ItemType::Variant, - 16 => ItemType::Macro, - 17 => ItemType::AssocType, - 18 => ItemType::Constant, - 19 => ItemType::AssocConst, - 20 => ItemType::Union, - 21 => ItemType::ForeignType, - 23 => ItemType::ProcAttribute, - 24 => ItemType::ProcDerive, - 25 => ItemType::TraitAlias, - _ => return Err(E::missing_field("unknown number")), - }) - } - } - deserializer.deserialize_any(ItemTypeVisitor) - } -} - impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { let kind = match &item.kind { diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6db90c9bf2a..b4ef47d1e26 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2812,24 +2812,46 @@ fn render_call_locations<W: fmt::Write>( let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES; let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); - // Look for the example file in the source map if it exists, otherwise return a dummy span - let file_span = (|| { - let source_map = tcx.sess.source_map(); - let crate_src = tcx.sess.local_crate_source_file()?.into_local_path()?; + let source_map = tcx.sess.source_map(); + let files = source_map.files(); + let local = tcx.sess.local_crate_source_file().unwrap(); + + let get_file_start_pos = || { + let crate_src = local.clone().into_local_path()?; let abs_crate_src = crate_src.canonicalize().ok()?; let crate_root = abs_crate_src.parent()?.parent()?; let rel_path = path.strip_prefix(crate_root).ok()?; - let files = source_map.files(); - let file = files.iter().find(|file| match &file.name { - FileName::Real(RealFileName::LocalPath(other_path)) => rel_path == other_path, - _ => false, - })?; - Some(rustc_span::Span::with_root_ctxt( - file.start_pos + BytePos(byte_min), - file.start_pos + BytePos(byte_max), - )) - })() - .unwrap_or(DUMMY_SP); + files + .iter() + .find(|file| match &file.name { + FileName::Real(RealFileName::LocalPath(other_path)) => rel_path == other_path, + _ => false, + }) + .map(|file| file.start_pos) + }; + + // Look for the example file in the source map if it exists, otherwise + // return a span to the local crate's source file + let Some(file_span) = get_file_start_pos() + .or_else(|| { + files + .iter() + .find(|file| match &file.name { + FileName::Real(file_name) => file_name == &local, + _ => false, + }) + .map(|file| file.start_pos) + }) + .map(|start_pos| { + rustc_span::Span::with_root_ctxt( + start_pos + BytePos(byte_min), + start_pos + BytePos(byte_max), + ) + }) + else { + // if the fallback span can't be built, don't render the code for this example + return false; + }; let mut decoration_info = FxIndexMap::default(); decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]); diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 74f646008eb..938ccc7d2c3 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -289,7 +289,7 @@ declare namespace rustdoc { exactModulePath: string, entry: EntryData?, path: PathData?, - type: FunctionData?, + functionData: FunctionData?, deprecated: boolean, parent: { path: PathData, name: string}?, } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index fa812a2b67b..5da37c97c6a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1802,14 +1802,15 @@ class DocSearch { /** * @param {number} id + * @param {boolean} loadFunctionData * @returns {Promise<rustdoc.Row?>} */ - async getRow(id) { - const [name_, entry, path, type] = await Promise.all([ + async getRow(id, loadFunctionData) { + const [name_, entry, path, functionData] = await Promise.all([ this.getName(id), this.getEntryData(id), this.getPathData(id), - this.getFunctionData(id), + loadFunctionData ? this.getFunctionData(id) : null, ]); if (!entry && !path) { return null; @@ -1853,7 +1854,7 @@ class DocSearch { `${exactModulePathData.exactModulePath}::${exactModuleName}`), entry, path, - type, + functionData, deprecated: entry ? entry.deprecated : false, parent: parentName !== null && parentPath !== null ? { name: parentName, path: parentPath } : @@ -2563,11 +2564,11 @@ class DocSearch { name: item.parent.name, ty: item.parent.path.ty, } : undefined, - type: item.type && item.type.functionSignature ? - item.type.functionSignature : + type: item.functionData && item.functionData.functionSignature ? + item.functionData.functionSignature : undefined, - paramNames: item.type && item.type.paramNames ? - item.type.paramNames : + paramNames: item.functionData && item.functionData.paramNames ? + item.functionData.paramNames : undefined, dist: result.dist, path_dist: result.path_dist, @@ -2642,7 +2643,7 @@ class DocSearch { /** * @type {rustdoc.Row?} */ - const item = await this.getRow(result.id); + const item = await this.getRow(result.id, typeInfo !== null); if (!item) { continue; } @@ -3749,7 +3750,7 @@ class DocSearch { is_alias: true, elems: [], // only used in type-based queries returned: [], // only used in type-based queries - original: await this.getRow(alias), + original: await this.getRow(alias, false), }; }; /** @@ -3804,7 +3805,7 @@ class DocSearch { * @returns {Promise<rustdoc.PlainResultObject?>} */ const handleNameSearch = async id => { - const row = await this.getRow(id); + const row = await this.getRow(id, false); if (!row || !row.entry) { return null; } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index f0520716228..6fe94f9d291 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -466,7 +466,7 @@ impl FromClean<clean::GenericParamDefKind> for GenericParamDefKind { default: default.into_json(renderer), is_synthetic: *synthetic, }, - Const { ty, default, synthetic: _ } => GenericParamDefKind::Const { + Const { ty, default } => GenericParamDefKind::Const { type_: ty.into_json(renderer), default: default.as_ref().map(|x| x.as_ref().clone()), }, diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 05d5f21c12c..efa99f181b3 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [dependencies] toml = "0.7" serde = { version = "1.0", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0" anyhow = "1.0.32" flate2 = "1.0.26" xz2 = "0.1.7" diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 72f5eaf8a4b..c3fc09343db 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -53,7 +53,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool { | PatKind::Never | PatKind::Or(_) | PatKind::Err(_) => false, - PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)), + PatKind::Struct(_, a, etc) => etc.is_none() && a.iter().all(|x| unary_pattern(x.pat)), PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a), PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x), PatKind::Expr(_) => true, diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 5a7967bbf94..2705ef20b79 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -287,7 +287,7 @@ fn replace_in_pattern( } return or_pat; }, - PatKind::Struct(path, fields, has_dot_dot) => { + PatKind::Struct(path, fields, dot_dot) => { let fields = fields .iter() .map(|fld| { @@ -311,7 +311,7 @@ fn replace_in_pattern( .collect::<Vec<_>>(); let fields_string = fields.join(", "); - let dot_dot_str = if has_dot_dot { " .." } else { "" }; + let dot_dot_str = if dot_dot.is_some() { " .." } else { "" }; let (sn_pth, _) = snippet_with_context(cx, path.span(), span.ctxt(), "", app); return format!("{sn_pth} {{ {fields_string}{dot_dot_str} }}"); }, diff --git a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs index 2154cd5b24a..ae09c2e87d6 100644 --- a/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs +++ b/src/tools/clippy/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs @@ -7,7 +7,7 @@ use super::REST_PAT_IN_FULLY_BOUND_STRUCTS; pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) { if !pat.span.from_expansion() - && let PatKind::Struct(QPath::Resolved(_, path), fields, true) = pat.kind + && let PatKind::Struct(QPath::Resolved(_, path), fields, Some(_)) = pat.kind && let Some(def_id) = path.res.opt_def_id() && let ty = cx.tcx.type_of(def_id).instantiate_identity() && let ty::Adt(def, _) = ty.kind() diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 2113cb92137..ece29362a39 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -754,7 +754,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { self.ident(name); sub.if_some(|p| self.pat(p)); }, - PatKind::Struct(ref qpath, fields, ignore) => { + PatKind::Struct(ref qpath, fields, etc) => { + let ignore = etc.is_some(); bind!(self, qpath, fields); kind!("Struct(ref {qpath}, {fields}, {ignore})"); self.qpath(qpath, pat); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 8533fa85541..011c9b2f931 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2011,7 +2011,7 @@ pub fn is_expr_identity_of_pat(cx: &LateContext<'_>, pat: &Pat<'_>, expr: &Expr< false } }, - (PatKind::Struct(pat_ident, field_pats, false), ExprKind::Struct(ident, fields, hir::StructTailExpr::None)) + (PatKind::Struct(pat_ident, field_pats, None), ExprKind::Struct(ident, fields, hir::StructTailExpr::None)) if field_pats.len() == fields.len() => { // check ident diff --git a/src/tools/collect-license-metadata/Cargo.toml b/src/tools/collect-license-metadata/Cargo.toml index 7f2e57ced05..edf9e5c5393 100644 --- a/src/tools/collect-license-metadata/Cargo.toml +++ b/src/tools/collect-license-metadata/Cargo.toml @@ -8,5 +8,5 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.65" serde = { version = "1.0.147", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0.85" spdx-rs = "0.5.1" diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index fb71275b03c..cdada5a2230 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -20,22 +20,22 @@ diff = "0.1.10" getopts = "0.2" glob = "0.3.0" home = "0.5.5" -indexmap.workspace = true +indexmap = "2.0.0" miropt-test-tools = { path = "../miropt-test-tools" } rayon = "1.10.0" regex = "1.0" rustfix = "0.8.1" semver = { version = "1.0.23", features = ["serde"] } serde = { version = "1.0", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0" +tracing = "0.1" tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] } -tracing.workspace = true unified-diff = "0.2.1" walkdir = "2" # tidy-alphabetical-end [target.'cfg(unix)'.dependencies] -libc.workspace = true +libc = "0.2" [target.'cfg(windows)'.dependencies] miow = "0.6" diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs index fdd7155c21f..5519ef1af1f 100644 --- a/src/tools/compiletest/src/executor.rs +++ b/src/tools/compiletest/src/executor.rs @@ -13,6 +13,7 @@ use std::sync::{Arc, Mutex, mpsc}; use std::{env, hint, io, mem, panic, thread}; use crate::common::{Config, TestPaths}; +use crate::panic_hook; mod deadline; mod json; @@ -120,6 +121,11 @@ fn run_test_inner( completion_sender: mpsc::Sender<TestCompletion>, ) { let is_capture = !runnable_test.config.nocapture; + + // Install a panic-capture buffer for use by the custom panic hook. + if is_capture { + panic_hook::set_capture_buf(Default::default()); + } let capture_buf = is_capture.then(|| Arc::new(Mutex::new(vec![]))); if let Some(capture_buf) = &capture_buf { @@ -128,6 +134,13 @@ fn run_test_inner( let panic_payload = panic::catch_unwind(move || runnable_test.run()).err(); + if let Some(panic_buf) = panic_hook::take_capture_buf() { + let panic_buf = panic_buf.lock().unwrap_or_else(|e| e.into_inner()); + // For now, forward any captured panic message to (captured) stderr. + // FIXME(Zalathar): Once we have our own output-capture buffer for + // non-panic output, append the panic message to that buffer instead. + eprint!("{panic_buf}"); + } if is_capture { io::set_output_capture(None); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 8737fec80bb..fa84691a46f 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -15,6 +15,7 @@ pub mod directives; pub mod errors; mod executor; mod json; +mod panic_hook; mod raise_fd_limit; mod read2; pub mod runtest; @@ -493,6 +494,8 @@ pub fn opt_str2(maybestr: Option<String>) -> String { pub fn run_tests(config: Arc<Config>) { debug!(?config, "run_tests"); + panic_hook::install_panic_hook(); + // If we want to collect rustfix coverage information, // we first make sure that the coverage file does not exist. // It will be created later on. diff --git a/src/tools/compiletest/src/panic_hook.rs b/src/tools/compiletest/src/panic_hook.rs new file mode 100644 index 00000000000..1661ca6dabe --- /dev/null +++ b/src/tools/compiletest/src/panic_hook.rs @@ -0,0 +1,136 @@ +use std::backtrace::{Backtrace, BacktraceStatus}; +use std::cell::Cell; +use std::fmt::{Display, Write}; +use std::panic::PanicHookInfo; +use std::sync::{Arc, LazyLock, Mutex}; +use std::{env, mem, panic, thread}; + +type PanicHook = Box<dyn Fn(&PanicHookInfo<'_>) + Sync + Send + 'static>; +type CaptureBuf = Arc<Mutex<String>>; + +thread_local!( + static CAPTURE_BUF: Cell<Option<CaptureBuf>> = const { Cell::new(None) }; +); + +/// Installs a custom panic hook that will divert panic output to a thread-local +/// capture buffer, but only for threads that have a capture buffer set. +/// +/// Otherwise, the custom hook delegates to a copy of the default panic hook. +pub(crate) fn install_panic_hook() { + let default_hook = panic::take_hook(); + panic::set_hook(Box::new(move |info| custom_panic_hook(&default_hook, info))); +} + +pub(crate) fn set_capture_buf(buf: CaptureBuf) { + CAPTURE_BUF.set(Some(buf)); +} + +pub(crate) fn take_capture_buf() -> Option<CaptureBuf> { + CAPTURE_BUF.take() +} + +fn custom_panic_hook(default_hook: &PanicHook, info: &panic::PanicHookInfo<'_>) { + // Temporarily taking the capture buffer means that if a panic occurs in + // the subsequent code, that panic will fall back to the default hook. + let Some(buf) = take_capture_buf() else { + // There was no capture buffer, so delegate to the default hook. + default_hook(info); + return; + }; + + let mut out = buf.lock().unwrap_or_else(|e| e.into_inner()); + + let thread = thread::current().name().unwrap_or("(test runner)").to_owned(); + let location = get_location(info); + let payload = payload_as_str(info).unwrap_or("Box<dyn Any>"); + let backtrace = Backtrace::capture(); + + writeln!(out, "\nthread '{thread}' panicked at {location}:\n{payload}").unwrap(); + match backtrace.status() { + BacktraceStatus::Captured => { + let bt = trim_backtrace(backtrace.to_string()); + write!(out, "stack backtrace:\n{bt}",).unwrap(); + } + BacktraceStatus::Disabled => { + writeln!( + out, + "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace", + ) + .unwrap(); + } + _ => {} + } + + drop(out); + set_capture_buf(buf); +} + +fn get_location<'a>(info: &'a PanicHookInfo<'_>) -> &'a dyn Display { + match info.location() { + Some(location) => location, + None => &"(unknown)", + } +} + +/// FIXME(Zalathar): Replace with `PanicHookInfo::payload_as_str` when that's +/// stable in beta. +fn payload_as_str<'a>(info: &'a PanicHookInfo<'_>) -> Option<&'a str> { + let payload = info.payload(); + if let Some(s) = payload.downcast_ref::<&str>() { + Some(s) + } else if let Some(s) = payload.downcast_ref::<String>() { + Some(s) + } else { + None + } +} + +fn rust_backtrace_full() -> bool { + static RUST_BACKTRACE_FULL: LazyLock<bool> = + LazyLock::new(|| matches!(env::var("RUST_BACKTRACE").as_deref(), Ok("full"))); + *RUST_BACKTRACE_FULL +} + +/// On stable, short backtraces are only available to the default panic hook, +/// so if we want something similar we have to resort to string processing. +fn trim_backtrace(full_backtrace: String) -> String { + if rust_backtrace_full() { + return full_backtrace; + } + + let mut buf = String::with_capacity(full_backtrace.len()); + // Don't print any frames until after the first `__rust_end_short_backtrace`. + let mut on = false; + // After the short-backtrace state is toggled, skip its associated "at" if present. + let mut skip_next_at = false; + + let mut lines = full_backtrace.lines(); + while let Some(line) = lines.next() { + if mem::replace(&mut skip_next_at, false) && line.trim_start().starts_with("at ") { + continue; + } + + if line.contains("__rust_end_short_backtrace") { + on = true; + skip_next_at = true; + continue; + } + if line.contains("__rust_begin_short_backtrace") { + on = false; + skip_next_at = true; + continue; + } + + if on { + writeln!(buf, "{line}").unwrap(); + } + } + + writeln!( + buf, + "note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace." + ) + .unwrap(); + + buf +} diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml index e491804c257..36a66f16030 100644 --- a/src/tools/coverage-dump/Cargo.toml +++ b/src/tools/coverage-dump/Cargo.toml @@ -7,9 +7,9 @@ edition = "2021" [dependencies] anyhow = "1.0.71" -itertools.workspace = true +itertools = "0.12" leb128 = "0.2.5" md5 = { package = "md-5" , version = "0.10.5" } miniz_oxide = "0.8.8" regex = "1.8.4" -rustc-demangle.workspace = true +rustc-demangle = "0.1.23" diff --git a/src/tools/features-status-dump/Cargo.toml b/src/tools/features-status-dump/Cargo.toml index d72555da486..b2976f14a01 100644 --- a/src/tools/features-status-dump/Cargo.toml +++ b/src/tools/features-status-dump/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" anyhow = { version = "1" } clap = { version = "4", features = ["derive"] } serde = { version = "1.0.125", features = [ "derive" ] } -serde_json.workspace = true +serde_json = "1.0.59" tidy = { path = "../tidy", features = ["build-metrics"] } diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml index 5edf1f3d88b..bcb3165de45 100644 --- a/src/tools/generate-copyright/Cargo.toml +++ b/src/tools/generate-copyright/Cargo.toml @@ -11,5 +11,5 @@ anyhow = "1.0.65" askama = "0.14.0" cargo_metadata = "0.21" serde = { version = "1.0.147", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0.85" thiserror = "1" diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index 92fde363882..80fc26cbe66 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -8,5 +8,5 @@ jsonpath-rust = "1.0.0" getopts = "0.2" regex = "1.4" shlex = "1.0" -serde_json.workspace = true +serde_json = "1.0" fs-err = "2.5.0" diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 44beaf2ddfd..cc8ecefd530 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -9,7 +9,7 @@ edition = "2021" anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" -rustc-hash.workspace = true +rustc-hash = "2.0.0" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } -serde_json.workspace = true +serde_json = "1.0.85" diff --git a/src/tools/lint-docs/Cargo.toml b/src/tools/lint-docs/Cargo.toml index acafe17cb0c..6e1ab84ed18 100644 --- a/src/tools/lint-docs/Cargo.toml +++ b/src/tools/lint-docs/Cargo.toml @@ -8,6 +8,6 @@ description = "A script to extract the lint documentation for the rustc book." [dependencies] rustc-literal-escaper = "0.0.5" -serde_json.workspace = true -tempfile.workspace = true +serde_json = "1.0.57" +tempfile = "3.1.0" walkdir = "2.3.1" diff --git a/src/tools/llvm-bitcode-linker/Cargo.toml b/src/tools/llvm-bitcode-linker/Cargo.toml index f78f8b618d3..a9210b562f3 100644 --- a/src/tools/llvm-bitcode-linker/Cargo.toml +++ b/src/tools/llvm-bitcode-linker/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] anyhow = "1.0" -tracing.workspace = true -tracing-subscriber = { version = "0.3.0", features = ["std"] } +tracing = "0.1" +tracing-subscriber = {version = "0.3.0", features = ["std"] } clap = { version = "4.3", features = ["derive"] } thiserror = "1.0.24" diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs index 4a87411d755..35b8e20e56b 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs @@ -1,6 +1,4 @@ //@error-in-other-file: aborted -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" #![feature(allocator_api)] use std::alloc::*; diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr index d67dabd6935..bbf5d14a98a 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.stderr @@ -1,13 +1,11 @@ memory allocation of 4 bytes failed error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/alloc.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort() + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC = note: inside `std::alloc::rust_oom` at RUSTLIB/std/src/alloc.rs:LL:CC = note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC = note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC @@ -16,7 +14,7 @@ note: inside `main` --> tests/fail/alloc/alloc_error_handler.rs:LL:CC | LL | handle_alloc_error(Layout::for_value(&0)); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr index a1571173a53..95f79aae6c1 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr @@ -9,13 +9,12 @@ panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -33,7 +32,7 @@ note: inside `main` --> tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC | LL | unsafe { nounwind() } - | ^ + | ^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr index a1571173a53..95f79aae6c1 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr @@ -9,13 +9,12 @@ panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -33,7 +32,7 @@ note: inside `main` --> tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC | LL | unsafe { nounwind() } - | ^ + | ^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr index e755b262474..eaca0d3f012 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr @@ -7,7 +7,7 @@ error: Undefined Behavior: unwinding past a stack frame that does not allow unwi --> tests/fail/function_calls/exported_symbol_bad_unwind2.rs:LL:CC | LL | unsafe { nounwind() } - | ^ Undefined Behavior occurred here + | ^^^^^^^^^^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs index 9d993786d57..aa5a185f110 100644 --- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs +++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs @@ -1,6 +1,4 @@ //@revisions: extern_block definition both -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" //@[definition,both]error-in-other-file: aborted execution diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.rs b/src/tools/miri/tests/fail/panic/abort_unwind.rs index bd819362da4..775cbf62229 100644 --- a/src/tools/miri/tests/fail/panic/abort_unwind.rs +++ b/src/tools/miri/tests/fail/panic/abort_unwind.rs @@ -1,6 +1,4 @@ //@error-in-other-file: the program aborted execution -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" diff --git a/src/tools/miri/tests/fail/panic/abort_unwind.stderr b/src/tools/miri/tests/fail/panic/abort_unwind.stderr index 287f7d5432a..23dbc2fb8f3 100644 --- a/src/tools/miri/tests/fail/panic/abort_unwind.stderr +++ b/src/tools/miri/tests/fail/panic/abort_unwind.stderr @@ -9,13 +9,12 @@ panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -27,7 +26,7 @@ note: inside `main` --> tests/fail/panic/abort_unwind.rs:LL:CC | LL | std::panic::abort_unwind(|| panic!("PANIC!!!")); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs index 4d8f4cb6fb7..88421e84529 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.rs +++ b/src/tools/miri/tests/fail/panic/double_panic.rs @@ -1,5 +1,3 @@ -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr index b76ece7f1e5..edbc0d8fc57 100644 --- a/src/tools/miri/tests/fail/panic/double_panic.stderr +++ b/src/tools/miri/tests/fail/panic/double_panic.stderr @@ -12,13 +12,12 @@ thread 'main' ($TID) panicked at RUSTLIB/core/src/panicking.rs:LL:CC: panic in a destructor during cleanup thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.rs b/src/tools/miri/tests/fail/panic/panic_abort1.rs index 06cb673778a..511b8bddf97 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.rs +++ b/src/tools/miri/tests/fail/panic/panic_abort1.rs @@ -1,6 +1,4 @@ //@error-in-other-file: the program aborted execution -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" //@compile-flags: -C panic=abort fn main() { diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index c469d24287f..c389a9bc075 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -4,14 +4,12 @@ panicking from libstd note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/rt.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC @@ -23,7 +21,7 @@ note: inside `main` --> tests/fail/panic/panic_abort1.rs:LL:CC | LL | std::panic!("panicking from libstd"); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.rs b/src/tools/miri/tests/fail/panic/panic_abort2.rs index c011b3ee7eb..e6c1a130ac9 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.rs +++ b/src/tools/miri/tests/fail/panic/panic_abort2.rs @@ -1,6 +1,4 @@ //@error-in-other-file: the program aborted execution -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" //@compile-flags: -C panic=abort fn main() { diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index bc7918f5f86..5fe2245cbe0 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -4,14 +4,12 @@ thread 'main' ($TID) panicked at tests/fail/panic/panic_abort2.rs:LL:CC: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/rt.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC @@ -23,7 +21,7 @@ note: inside `main` --> tests/fail/panic/panic_abort2.rs:LL:CC | LL | std::panic!("{}-panicking from libstd", 42); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.rs b/src/tools/miri/tests/fail/panic/panic_abort3.rs index 911dc4a44ab..28a28c923fd 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.rs +++ b/src/tools/miri/tests/fail/panic/panic_abort3.rs @@ -1,6 +1,4 @@ //@error-in-other-file: the program aborted execution -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" //@compile-flags: -C panic=abort fn main() { diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index 553bfa61635..cac24ca41c7 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -4,14 +4,12 @@ panicking from libcore note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/rt.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC @@ -23,7 +21,7 @@ note: inside `main` --> tests/fail/panic/panic_abort3.rs:LL:CC | LL | core::panic!("panicking from libcore"); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.rs b/src/tools/miri/tests/fail/panic/panic_abort4.rs index 696fdff7422..248064d14d5 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.rs +++ b/src/tools/miri/tests/fail/panic/panic_abort4.rs @@ -1,6 +1,4 @@ //@error-in-other-file: the program aborted execution -//@normalize-stderr-test: "\| +\^+" -> "| ^" -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" //@compile-flags: -C panic=abort fn main() { diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index 07ecab6661e..21195729ae8 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -4,14 +4,12 @@ thread 'main' ($TID) panicked at tests/fail/panic/panic_abort4.rs:LL:CC: note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/rt.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC - = note: inside `std::process::abort` at RUSTLIB/std/src/process.rs:LL:CC = note: inside `std::rt::__rust_abort` at RUSTLIB/std/src/rt.rs:LL:CC = note: inside `panic_abort::__rust_start_panic` at RUSTLIB/panic_abort/src/lib.rs:LL:CC = note: inside `std::panicking::rust_panic` at RUSTLIB/std/src/panicking.rs:LL:CC @@ -23,7 +21,7 @@ note: inside `main` --> tests/fail/panic/panic_abort4.rs:LL:CC | LL | core::panic!("{}-panicking from libcore", 42); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs index 6119e8604b4..0f7cf189f33 100644 --- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs +++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.rs @@ -1,7 +1,5 @@ //! This is a regression test for <https://github.com/rust-lang/miri/issues/4188>: The precondition //! check in `ptr::swap_nonoverlapping` was incorrectly disabled in Miri. -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution diff --git a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr index 70f5d498da3..c5f6e62b869 100644 --- a/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr +++ b/src/tools/miri/tests/fail/ptr_swap_nonoverlapping.stderr @@ -7,13 +7,12 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -22,7 +21,7 @@ note: inside `main` --> tests/fail/ptr_swap_nonoverlapping.rs:LL:CC | LL | std::ptr::swap_nonoverlapping(ptr, ptr, 1); - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs index 31ae829a2de..421cddca160 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.rs +++ b/src/tools/miri/tests/fail/terminate-terminator.rs @@ -1,6 +1,4 @@ //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000 -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" //@error-in-other-file: aborted execution diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr index 228e2d3de1f..8ae649a392b 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.stderr +++ b/src/tools/miri/tests/fail/terminate-terminator.stderr @@ -11,13 +11,12 @@ panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -36,12 +35,12 @@ note: inside `panic_abort` --> tests/fail/terminate-terminator.rs:LL:CC | LL | has_cleanup(); - | ^ + | ^^^^^^^^^^^^^ note: inside `main` --> tests/fail/terminate-terminator.rs:LL:CC | LL | panic_abort(); - | ^ + | ^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs index f0fbcfd8867..e1c8909fffa 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.rs +++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs @@ -1,6 +1,4 @@ //@error-in-other-file: aborted execution -//@normalize-stderr-test: "\|.*::abort\(\).*" -> "| ABORT()" -//@normalize-stderr-test: "\| +\^+" -> "| ^" //@normalize-stderr-test: "\n +[0-9]+:[^\n]+" -> "" //@normalize-stderr-test: "\n +at [^\n]+" -> "" extern "C" fn panic_abort() { diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr index 1c0f8cb7ec6..cf41c88ce37 100644 --- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr +++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr @@ -9,13 +9,12 @@ panic in a function that cannot unwind stack backtrace: thread caused non-unwinding panic. aborting. error: abnormal termination: the program aborted execution - --> RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC + --> RUSTLIB/std/src/panicking.rs:LL:CC | -LL | ABORT() - | ^ abnormal termination occurred here +LL | crate::process::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: BACKTRACE: - = note: inside `std::sys::pal::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/pal/PLATFORM/mod.rs:LL:CC = note: inside `std::panicking::panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC = note: inside `std::sys::backtrace::__rust_end_short_backtrace::<{closure@std::panicking::panic_handler::{closure#0}}, !>` at RUSTLIB/std/src/sys/backtrace.rs:LL:CC @@ -33,7 +32,7 @@ note: inside `main` --> tests/fail/unwind-action-terminate.rs:LL:CC | LL | panic_abort(); - | ^ + | ^^^^^^^^^^^^^ note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/nix-dev-shell/shell.nix b/src/tools/nix-dev-shell/shell.nix index ad33b121f97..6ca8a7c4652 100644 --- a/src/tools/nix-dev-shell/shell.nix +++ b/src/tools/nix-dev-shell/shell.nix @@ -14,6 +14,7 @@ pkgs.mkShell { packages = [ pkgs.git pkgs.nix + pkgs.glibc.out pkgs.glibc.static x # Get the runtime deps of the x wrapper @@ -23,5 +24,7 @@ pkgs.mkShell { # Avoid creating text files for ICEs. RUSTC_ICE = 0; SSL_CERT_FILE = cacert; + # cargo seems to dlopen libcurl, so we need it in the ld library path + LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath [pkgs.stdenv.cc.cc.lib pkgs.curl]}"; }; } diff --git a/src/tools/opt-dist/Cargo.toml b/src/tools/opt-dist/Cargo.toml index b2833a9d7f1..f4051ae67d7 100644 --- a/src/tools/opt-dist/Cargo.toml +++ b/src/tools/opt-dist/Cargo.toml @@ -15,9 +15,9 @@ fs_extra = "1" camino = "1" tar = "0.4" xz = { version = "0.1", package = "xz2" } -serde_json.workspace = true +serde_json = "1" glob = "0.3" -tempfile.workspace = true +tempfile = "3.5" derive_builder = "0.20" clap = { version = "4", features = ["derive"] } tabled = { version = "0.15", default-features = false, features = ["std"] } diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml index 86ac4b9d7b4..250e0f65a9f 100644 --- a/src/tools/run-make-support/Cargo.toml +++ b/src/tools/run-make-support/Cargo.toml @@ -12,10 +12,10 @@ edition = "2024" # tidy-alphabetical-start bstr = "1.12" gimli = "0.32" -libc.workspace = true +libc = "0.2" object = "0.37" regex = "1.11" -serde_json.workspace = true +serde_json = "1.0" similar = "2.7" wasmparser = { version = "0.236", default-features = false, features = ["std", "features", "validate"] } # tidy-alphabetical-end diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 6555679c394..75e468b3525 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -1175,8 +1175,8 @@ pub(crate) fn format_trait( let mut result = String::with_capacity(128); let header = format!( "{}{}{}{}trait ", - format_constness(constness), format_visibility(context, &item.vis), + format_constness(constness), format_safety(safety), format_auto(is_auto), ); diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs index d212ecf392a..848bd0766e7 100644 --- a/src/tools/rustfmt/src/patterns.rs +++ b/src/tools/rustfmt/src/patterns.rs @@ -303,7 +303,7 @@ impl Rewrite for Pat { qself, path, fields, - rest == ast::PatFieldsRest::Rest, + matches!(rest, ast::PatFieldsRest::Rest(_)), self.span, context, shape, diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index f43733665ed..c1f27de7ed4 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -14,7 +14,7 @@ ignore = "0.4.18" semver = "1.0" serde = { version = "1.0.125", features = ["derive"], optional = true } termcolor = "1.1.3" -rustc-hash.workspace = true +rustc-hash = "2.0.0" fluent-syntax = "0.12" similar = "2.5.0" toml = "0.7.8" diff --git a/tests/codegen-llvm/cffi/c-variadic-ffi.rs b/tests/codegen-llvm/cffi/c-variadic-ffi.rs index 3e99c9fb84e..1dee477e9ed 100644 --- a/tests/codegen-llvm/cffi/c-variadic-ffi.rs +++ b/tests/codegen-llvm/cffi/c-variadic-ffi.rs @@ -14,7 +14,7 @@ //@[arm32] needs-llvm-components: arm #![crate_type = "lib"] #![feature(no_core)] -#![feature(extended_varargs_abi_support, extern_system_varargs)] +#![feature(extern_system_varargs)] #![no_core] extern crate minicore; diff --git a/tests/codegen-llvm/issues/issue-118306.rs b/tests/codegen-llvm/issues/issue-118306.rs index f12dc7cdfe2..934a7687b60 100644 --- a/tests/codegen-llvm/issues/issue-118306.rs +++ b/tests/codegen-llvm/issues/issue-118306.rs @@ -11,7 +11,7 @@ pub fn branchy(input: u64) -> u64 { // CHECK-LABEL: @branchy( // CHECK-NEXT: start: // CHECK-NEXT: [[_2:%.*]] = and i64 [[INPUT:%.*]], 3 - // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} [4 x i64], ptr @switch.table.branchy, i64 0, i64 [[_2]] + // CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds{{( nuw)?}} {{\[4 x i64\]|i64}}, ptr @switch.table.branchy{{(, i64 0)?}}, i64 [[_2]] // CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i64, ptr [[SWITCH_GEP]] // CHECK-NEXT: ret i64 [[SWITCH_LOAD]] match input % 4 { diff --git a/tests/coverage/closure.cov-map b/tests/coverage/closure.cov-map index 5f7e4ce58e9..ee8934f0a84 100644 --- a/tests/coverage/closure.cov-map +++ b/tests/coverage/closure.cov-map @@ -118,21 +118,23 @@ Number of file 0 mappings: 4 Highest counter ID seen: (none) Function name: closure::main::{closure#12} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, a7, 01, 0a, 00, 16] +Raw bytes (15): 0x[01, 01, 00, 02, 00, a7, 01, 01, 00, 09, 00, 00, 0a, 00, 16] Number of files: 1 - file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 167, 10) to (start + 0, 22) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 167, 1) to (start + 0, 9) +- Code(Zero) at (prev + 0, 10) to (start + 0, 22) Highest counter ID seen: (none) Function name: closure::main::{closure#13} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, ad, 01, 11, 00, 1d] +Raw bytes (15): 0x[01, 01, 00, 02, 00, ac, 01, 0d, 00, 15, 00, 01, 11, 00, 1d] Number of files: 1 - file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 173, 17) to (start + 0, 29) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 172, 13) to (start + 0, 21) +- Code(Zero) at (prev + 1, 17) to (start + 0, 29) Highest counter ID seen: (none) Function name: closure::main::{closure#14} @@ -289,30 +291,33 @@ Number of file 0 mappings: 7 Highest counter ID seen: (none) Function name: closure::main::{closure#5} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8c, 01, 46, 00, 4e] +Raw bytes (15): 0x[01, 01, 00, 02, 01, 8c, 01, 3d, 00, 45, 01, 00, 46, 00, 4e] Number of files: 1 - file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 140, 70) to (start + 0, 78) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 140, 61) to (start + 0, 69) +- Code(Counter(0)) at (prev + 0, 70) to (start + 0, 78) Highest counter ID seen: c0 Function name: closure::main::{closure#6} -Raw bytes (10): 0x[01, 01, 00, 01, 01, 8d, 01, 4a, 00, 56] +Raw bytes (15): 0x[01, 01, 00, 02, 01, 8d, 01, 41, 00, 49, 01, 00, 4a, 00, 56] Number of files: 1 - file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 141, 74) to (start + 0, 86) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 141, 65) to (start + 0, 73) +- Code(Counter(0)) at (prev + 0, 74) to (start + 0, 86) Highest counter ID seen: c0 Function name: closure::main::{closure#7} (unused) -Raw bytes (10): 0x[01, 01, 00, 01, 00, 8e, 01, 44, 00, 50] +Raw bytes (15): 0x[01, 01, 00, 02, 00, 8e, 01, 3b, 00, 43, 00, 00, 44, 00, 50] Number of files: 1 - file 0 => $DIR/closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Zero) at (prev + 142, 68) to (start + 0, 80) +Number of file 0 mappings: 2 +- Code(Zero) at (prev + 142, 59) to (start + 0, 67) +- Code(Zero) at (prev + 0, 68) to (start + 0, 80) Highest counter ID seen: (none) Function name: closure::main::{closure#8} (unused) diff --git a/tests/coverage/closure.coverage b/tests/coverage/closure.coverage index 14285269228..d44ecf5a69e 100644 --- a/tests/coverage/closure.coverage +++ b/tests/coverage/closure.coverage @@ -139,9 +139,9 @@ LL| | LL| 1| let short_used_covered_closure_macro = | used_arg: u8 | println!("called"); LL| 1| let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called"); - ^0 + ^0 ^0 LL| 1| let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called"); - ^0 + ^0 ^0 LL| | LL| | LL| | @@ -173,7 +173,7 @@ LL| | LL| 1| let _short_unused_closure_line_break_no_block2 = LL| | | _unused_arg: u8 | - LL| | println!( + LL| 0| println!( LL| 0| "not called" LL| | ) LL| | ; diff --git a/tests/coverage/macro_in_closure.cov-map b/tests/coverage/macro_in_closure.cov-map index 4544aa50143..3529d0c4c32 100644 --- a/tests/coverage/macro_in_closure.cov-map +++ b/tests/coverage/macro_in_closure.cov-map @@ -1,10 +1,11 @@ Function name: macro_in_closure::NO_BLOCK::{closure#0} -Raw bytes (9): 0x[01, 01, 00, 01, 01, 07, 25, 00, 2c] +Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 1c, 00, 24, 01, 00, 25, 00, 2c] Number of files: 1 - file 0 => $DIR/macro_in_closure.rs Number of expressions: 0 -Number of file 0 mappings: 1 -- Code(Counter(0)) at (prev + 7, 37) to (start + 0, 44) +Number of file 0 mappings: 2 +- Code(Counter(0)) at (prev + 7, 28) to (start + 0, 36) +- Code(Counter(0)) at (prev + 0, 37) to (start + 0, 44) Highest counter ID seen: c0 Function name: macro_in_closure::WITH_BLOCK::{closure#0} diff --git a/tests/coverage/rustfmt-skip.cov-map b/tests/coverage/rustfmt-skip.cov-map new file mode 100644 index 00000000000..bb673a411bf --- /dev/null +++ b/tests/coverage/rustfmt-skip.cov-map @@ -0,0 +1,12 @@ +Function name: rustfmt_skip::main +Raw bytes (24): 0x[01, 01, 00, 04, 01, 0a, 01, 00, 0a, 01, 02, 05, 00, 0d, 01, 03, 09, 00, 10, 01, 02, 01, 00, 02] +Number of files: 1 +- file 0 => $DIR/rustfmt-skip.rs +Number of expressions: 0 +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 10, 1) to (start + 0, 10) +- Code(Counter(0)) at (prev + 2, 5) to (start + 0, 13) +- Code(Counter(0)) at (prev + 3, 9) to (start + 0, 16) +- Code(Counter(0)) at (prev + 2, 1) to (start + 0, 2) +Highest counter ID seen: c0 + diff --git a/tests/coverage/rustfmt-skip.coverage b/tests/coverage/rustfmt-skip.coverage new file mode 100644 index 00000000000..b7276cf0ee8 --- /dev/null +++ b/tests/coverage/rustfmt-skip.coverage @@ -0,0 +1,18 @@ + LL| |//@ edition: 2024 + LL| | + LL| |// The presence of `#[rustfmt::skip]` on a function should not cause macros + LL| |// within that function to mysteriously not be instrumented. + LL| |// + LL| |// This test detects problems that can occur when building an expansion tree + LL| |// based on `ExpnData::parent` instead of `ExpnData::call_site`, for example. + LL| | + LL| |#[rustfmt::skip] + LL| 1|fn main() { + LL| | // Ensure a gap between the body start and the first statement. + LL| 1| println!( + LL| | // Keep this on a separate line, to distinguish instrumentation of + LL| | // `println!` from instrumentation of its arguments. + LL| 1| "hello" + LL| | ); + LL| 1|} + diff --git a/tests/coverage/rustfmt-skip.rs b/tests/coverage/rustfmt-skip.rs new file mode 100644 index 00000000000..6f6874c9aa0 --- /dev/null +++ b/tests/coverage/rustfmt-skip.rs @@ -0,0 +1,17 @@ +//@ edition: 2024 + +// The presence of `#[rustfmt::skip]` on a function should not cause macros +// within that function to mysteriously not be instrumented. +// +// This test detects problems that can occur when building an expansion tree +// based on `ExpnData::parent` instead of `ExpnData::call_site`, for example. + +#[rustfmt::skip] +fn main() { + // Ensure a gap between the body start and the first statement. + println!( + // Keep this on a separate line, to distinguish instrumentation of + // `println!` from instrumentation of its arguments. + "hello" + ); +} diff --git a/tests/crashes/140479.rs b/tests/crashes/140479.rs deleted file mode 100644 index ed3ca887546..00000000000 --- a/tests/crashes/140479.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: #140479 -macro_rules! a { ( $( { $ [ $b:c ] } )) => ( $(${ concat(d, $b)} ))} -fn e() { - a!({}) -} diff --git a/tests/mir-opt/building/loop_match_diverges.break_to_block_unit.built.after.mir b/tests/mir-opt/building/loop_match_diverges.break_to_block_unit.built.after.mir new file mode 100644 index 00000000000..6d779e46146 --- /dev/null +++ b/tests/mir-opt/building/loop_match_diverges.break_to_block_unit.built.after.mir @@ -0,0 +1,63 @@ +// MIR for `break_to_block_unit` after built + +fn break_to_block_unit() -> u8 { + let mut _0: u8; + let mut _1: i32; + let mut _2: !; + scope 1 { + debug state => _1; + } + + bb0: { + StorageLive(_1); + _1 = const 0_i32; + FakeRead(ForLet(None), _1); + StorageLive(_2); + goto -> bb1; + } + + bb1: { + falseUnwind -> [real: bb2, unwind: bb10]; + } + + bb2: { + PlaceMention(_1); + _1 = const 2_i32; + goto -> bb5; + } + + bb3: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb4: { + goto -> bb6; + } + + bb5: { + goto -> bb6; + } + + bb6: { + goto -> bb7; + } + + bb7: { + goto -> bb1; + } + + bb8: { + unreachable; + } + + bb9: { + StorageDead(_2); + StorageDead(_1); + return; + } + + bb10 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/loop_match_diverges.infinite_a.built.after.mir b/tests/mir-opt/building/loop_match_diverges.infinite_a.built.after.mir new file mode 100644 index 00000000000..e3766744790 --- /dev/null +++ b/tests/mir-opt/building/loop_match_diverges.infinite_a.built.after.mir @@ -0,0 +1,51 @@ +// MIR for `infinite_a` after built + +fn infinite_a(_1: u8) -> () { + debug state => _1; + let mut _0: (); + let mut _2: !; + let _3: u8; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_2); + goto -> bb1; + } + + bb1: { + falseUnwind -> [real: bb2, unwind: bb7]; + } + + bb2: { + PlaceMention(_1); + StorageLive(_3); + _3 = copy _1; + _1 = copy _3; + StorageDead(_3); + goto -> bb4; + } + + bb3: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb4: { + goto -> bb1; + } + + bb5: { + unreachable; + } + + bb6: { + StorageDead(_2); + return; + } + + bb7 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/loop_match_diverges.rs b/tests/mir-opt/building/loop_match_diverges.rs new file mode 100644 index 00000000000..774e195c33c --- /dev/null +++ b/tests/mir-opt/building/loop_match_diverges.rs @@ -0,0 +1,68 @@ +// skip-filecheck +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +// Test that a #[loop_match] without an explicit break from the loop generates valid MIR. + +enum State { + A, + B, + C, +} + +// EMIT_MIR loop_match_diverges.simple.built.after.mir +fn simple(mut state: State) -> State { + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + State::A => { + #[const_continue] + break 'blk State::B; + } + State::B => { + if true { + #[const_continue] + break 'blk State::C; + } else { + #[const_continue] + break 'blk State::A; + } + } + State::C => break 'a, + } + }; + } + + state +} + +// EMIT_MIR loop_match_diverges.break_to_block_unit.built.after.mir +#[unsafe(no_mangle)] +fn break_to_block_unit() -> u8 { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + _ => 'b: { + break 'b 2; + } + } + } + } +} + +// EMIT_MIR loop_match_diverges.infinite_a.built.after.mir +#[unsafe(no_mangle)] +fn infinite_a(mut state: u8) { + #[loop_match] + loop { + state = 'blk: { + match state { + a => a, + } + } + } +} diff --git a/tests/mir-opt/building/loop_match_diverges.simple.built.after.mir b/tests/mir-opt/building/loop_match_diverges.simple.built.after.mir new file mode 100644 index 00000000000..26476ad7762 --- /dev/null +++ b/tests/mir-opt/building/loop_match_diverges.simple.built.after.mir @@ -0,0 +1,187 @@ +// MIR for `simple` after built + +fn simple(_1: State) -> State { + debug state => _1; + let mut _0: State; + let _2: (); + let mut _3: isize; + let mut _4: !; + let mut _5: isize; + let mut _6: bool; + let mut _7: !; + let mut _8: isize; + let mut _9: !; + let mut _10: isize; + let mut _11: !; + + bb0: { + StorageLive(_2); + goto -> bb1; + } + + bb1: { + falseUnwind -> [real: bb2, unwind: bb37]; + } + + bb2: { + PlaceMention(_1); + _3 = discriminant(_1); + switchInt(move _3) -> [0: bb4, 1: bb6, 2: bb8, otherwise: bb3]; + } + + bb3: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb4: { + falseEdge -> [real: bb11, imaginary: bb6]; + } + + bb5: { + goto -> bb3; + } + + bb6: { + falseEdge -> [real: bb10, imaginary: bb8]; + } + + bb7: { + goto -> bb3; + } + + bb8: { + _2 = const (); + goto -> bb36; + } + + bb9: { + goto -> bb3; + } + + bb10: { + StorageLive(_6); + _6 = const true; + switchInt(move _6) -> [0: bb17, otherwise: bb16]; + } + + bb11: { + _1 = State::B; + _5 = discriminant(_1); + falseEdge -> [real: bb12, imaginary: bb13]; + } + + bb12: { + goto -> bb10; + } + + bb13: { + goto -> bb34; + } + + bb14: { + unreachable; + } + + bb15: { + goto -> bb32; + } + + bb16: { + _1 = State::C; + _8 = discriminant(_1); + falseEdge -> [real: bb18, imaginary: bb19]; + } + + bb17: { + goto -> bb23; + } + + bb18: { + goto -> bb20; + } + + bb19: { + goto -> bb33; + } + + bb20: { + StorageDead(_6); + goto -> bb8; + } + + bb21: { + unreachable; + } + + bb22: { + goto -> bb29; + } + + bb23: { + _1 = State::A; + _10 = discriminant(_1); + falseEdge -> [real: bb24, imaginary: bb25]; + } + + bb24: { + goto -> bb26; + } + + bb25: { + goto -> bb33; + } + + bb26: { + StorageDead(_6); + goto -> bb11; + } + + bb27: { + unreachable; + } + + bb28: { + goto -> bb29; + } + + bb29: { + StorageDead(_6); + goto -> bb32; + } + + bb30: { + unreachable; + } + + bb31: { + goto -> bb32; + } + + bb32: { + goto -> bb35; + } + + bb33: { + StorageDead(_6); + goto -> bb34; + } + + bb34: { + goto -> bb35; + } + + bb35: { + goto -> bb1; + } + + bb36: { + StorageDead(_2); + _0 = move _1; + return; + } + + bb37 (cleanup): { + resume; + } +} diff --git a/tests/rustdoc-gui/scrape-examples-ice-links.goml b/tests/rustdoc-gui/scrape-examples-ice-links.goml new file mode 100644 index 00000000000..1db220e1a32 --- /dev/null +++ b/tests/rustdoc-gui/scrape-examples-ice-links.goml @@ -0,0 +1,6 @@ +// Check that the line number column has the correct layout. +go-to: "file://" + |DOC_PATH| + "/scrape_ice/struct.ObscurelyNamedType1.html" +wait-for: ".scraped-example-title" +assert-attribute: (".scraped-example-title a", {"href": "../src/bar/bar.rs.html#2"}) +click: ".scraped-example-title a" +wait-for-property: ("h1", {"innerText": "bar/\nbar.rs"}) diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index 3f6914a89d6..a3c19d8c6d0 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -71,7 +71,7 @@ assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='sub_mod']" // Only "another_folder" should be "open" in "lib2". assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 12) +assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 13) // We now switch to mobile mode. set-window-size: (600, 600) diff --git a/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.lock b/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.lock new file mode 100644 index 00000000000..03410a0da12 --- /dev/null +++ b/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "scrape_ice" +version = "0.1.0" diff --git a/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.toml b/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.toml new file mode 100644 index 00000000000..076ff38ad23 --- /dev/null +++ b/tests/rustdoc-gui/src/scrape_examples_ice/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "scrape_ice" +version = "0.1.0" +edition = "2024" + +[[example]] +name = "bar" +path = "examples/bar.rs" +doc-scrape-examples = true diff --git a/tests/rustdoc-gui/src/scrape_examples_ice/empty.html b/tests/rustdoc-gui/src/scrape_examples_ice/empty.html new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/tests/rustdoc-gui/src/scrape_examples_ice/empty.html @@ -0,0 +1 @@ + diff --git a/tests/rustdoc-gui/src/scrape_examples_ice/examples/bar.rs b/tests/rustdoc-gui/src/scrape_examples_ice/examples/bar.rs new file mode 100644 index 00000000000..9f05f9e46e8 --- /dev/null +++ b/tests/rustdoc-gui/src/scrape_examples_ice/examples/bar.rs @@ -0,0 +1,3 @@ +fn main() { + let mut bar = scrape_ice::ObscurelyNamedType1::new(); +} diff --git a/tests/rustdoc-gui/src/scrape_examples_ice/src/lib.rs b/tests/rustdoc-gui/src/scrape_examples_ice/src/lib.rs new file mode 100644 index 00000000000..b854c7722c9 --- /dev/null +++ b/tests/rustdoc-gui/src/scrape_examples_ice/src/lib.rs @@ -0,0 +1,9 @@ +//@ run-flags:-Zrustdoc-scrape-examples +//@ compile-flags: --html-after-content empty.html +pub struct ObscurelyNamedType1; + +impl ObscurelyNamedType1 { + pub fn new() -> Self { + ObscurelyNamedType1 + } +} diff --git a/tests/ui/abi/unsupported-varargs-fnptr.rs b/tests/ui/abi/unsupported-varargs-fnptr.rs index 1d23916d039..ac3913b3ef8 100644 --- a/tests/ui/abi/unsupported-varargs-fnptr.rs +++ b/tests/ui/abi/unsupported-varargs-fnptr.rs @@ -6,8 +6,6 @@ // We have to use this flag to force ABI computation of an invalid ABI //@ compile-flags: -Clink-dead-code -#![feature(extended_varargs_abi_support)] - // sometimes fn ptrs with varargs make layout and ABI computation ICE // as found in https://github.com/rust-lang/rust/issues/142107 diff --git a/tests/ui/abi/unsupported-varargs-fnptr.stderr b/tests/ui/abi/unsupported-varargs-fnptr.stderr index 238f2b31330..c05c55df82e 100644 --- a/tests/ui/abi/unsupported-varargs-fnptr.stderr +++ b/tests/ui/abi/unsupported-varargs-fnptr.stderr @@ -1,5 +1,5 @@ error[E0570]: "aapcs" is not a supported ABI for the current target - --> $DIR/unsupported-varargs-fnptr.rs:14:20 + --> $DIR/unsupported-varargs-fnptr.rs:12:20 | LL | fn aapcs(f: extern "aapcs" fn(usize, ...)) { | ^^^^^^^ diff --git a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr index 1faaf4ddce2..aa2343e48a6 100644 --- a/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr +++ b/tests/ui/async-await/dont-suggest-await-on-method-return-mismatch.stderr @@ -3,6 +3,11 @@ error[E0599]: no method named `test` found for opaque type `impl Future<Output = | LL | let x: u32 = foo().test(); | ^^^^ method not found in `impl Future<Output = A>` + | +help: consider `await`ing on the `Future` and calling the method on its `Output` + | +LL | let x: u32 = foo().await.test(); + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs deleted file mode 100644 index 1e0576b2186..00000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ only-x86_64 - -fn efiapi(f: extern "efiapi" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} -fn sysv(f: extern "sysv64" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} -fn win(f: extern "win64" fn(usize, ...)) { - //~^ ERROR: unstable - f(22, 44); -} - -fn main() {} diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr deleted file mode 100644 index 7ef54b639ad..00000000000 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ /dev/null @@ -1,33 +0,0 @@ -error[E0658]: C-variadic functions with the "efiapi" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 - | -LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: C-variadic functions with the "sysv64" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12 - | -LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: C-variadic functions with the "win64" calling convention are unstable - --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 - | -LL | fn win(f: extern "win64" fn(usize, ...)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #100189 <https://github.com/rust-lang/rust/issues/100189> for more information - = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/c-variadic/issue-86053-1.rs b/tests/ui/c-variadic/issue-86053-1.rs index 8eeb99a4cc1..537d0263adf 100644 --- a/tests/ui/c-variadic/issue-86053-1.rs +++ b/tests/ui/c-variadic/issue-86053-1.rs @@ -13,6 +13,6 @@ fn ordering4 < 'a , 'b > ( a : , self , self , self , //~| ERROR unexpected `self` parameter in function //~| ERROR unexpected `self` parameter in function //~| ERROR `...` must be the last argument of a C-variadic function - //~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR cannot find type `F` in this scope } diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr index 3bf8b7ba5d8..675dfd335c4 100644 --- a/tests/ui/c-variadic/issue-86053-1.stderr +++ b/tests/ui/c-variadic/issue-86053-1.stderr @@ -46,7 +46,7 @@ error: `...` must be the last argument of a C-variadic function LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/issue-86053-1.rs:11:12 | LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) { diff --git a/tests/ui/c-variadic/same-program-multiple-abis-arm.rs b/tests/ui/c-variadic/same-program-multiple-abis-arm.rs index 1b0bdecabfb..1445bbb47bb 100644 --- a/tests/ui/c-variadic/same-program-multiple-abis-arm.rs +++ b/tests/ui/c-variadic/same-program-multiple-abis-arm.rs @@ -1,4 +1,3 @@ -#![feature(extended_varargs_abi_support)] //@ run-pass //@ only-arm //@ ignore-thumb (this test uses arm assembly) diff --git a/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs b/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs index b21accb999e..aff8ab613c4 100644 --- a/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs +++ b/tests/ui/c-variadic/same-program-multiple-abis-x86_64.rs @@ -1,4 +1,3 @@ -#![feature(extended_varargs_abi_support)] //@ run-pass //@ only-x86_64 diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs index 800dd580af2..ad4fca8252d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.rs @@ -71,6 +71,6 @@ extern "cmse-nonsecure-entry" fn wrapped_trait_object( } extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR requires `va_list` lang_item } diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr index f0190671b5a..7aeb6969feb 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/generics.stderr @@ -1,4 +1,4 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/generics.rs:73:53 | LL | extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs index f189f02a26d..45c68842093 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.rs +++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs @@ -2,3 +2,9 @@ pub unsafe extern "C" fn test(_: i32, ap: ...) { } //~^ ERROR C-variadic functions are unstable + +trait Trait { + unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + //~^ ERROR C-variadic functions are unstable + //~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention +} diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr index 1b6a8c92af5..e30a2f1ede3 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr @@ -1,3 +1,9 @@ +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention + --> $DIR/feature-gate-c_variadic.rs:7:45 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + | ^^^^^^^ + error[E0658]: C-variadic functions are unstable --> $DIR/feature-gate-c_variadic.rs:3:1 | @@ -8,6 +14,16 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) { } = help: add `#![feature(c_variadic)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: C-variadic functions are unstable + --> $DIR/feature-gate-c_variadic.rs:7:5 + | +LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information + = help: add `#![feature(c_variadic)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/frontmatter/frontmatter-whitespace-1.rs b/tests/ui/frontmatter/frontmatter-whitespace-1.rs index 8b6e2d1af84..3b7f762d26e 100644 --- a/tests/ui/frontmatter/frontmatter-whitespace-1.rs +++ b/tests/ui/frontmatter/frontmatter-whitespace-1.rs @@ -1,7 +1,7 @@ --- //~^ ERROR: invalid preceding whitespace for frontmatter opening +//~^^ ERROR: unclosed frontmatter --- -//~^ ERROR: invalid preceding whitespace for frontmatter close #![feature(frontmatter)] diff --git a/tests/ui/frontmatter/frontmatter-whitespace-1.stderr b/tests/ui/frontmatter/frontmatter-whitespace-1.stderr index 37ece27acb2..f16788fa399 100644 --- a/tests/ui/frontmatter/frontmatter-whitespace-1.stderr +++ b/tests/ui/frontmatter/frontmatter-whitespace-1.stderr @@ -10,17 +10,21 @@ note: frontmatter opening should not be preceded by whitespace LL | --- | ^^ -error: invalid preceding whitespace for frontmatter close - --> $DIR/frontmatter-whitespace-1.rs:3:1 +error: unclosed frontmatter + --> $DIR/frontmatter-whitespace-1.rs:1:3 | -LL | --- - | ^^^^^ +LL | / --- +LL | | +LL | | +LL | | --- +LL | | + | |_^ | -note: frontmatter close should not be preceded by whitespace - --> $DIR/frontmatter-whitespace-1.rs:3:1 +note: frontmatter opening here was not closed + --> $DIR/frontmatter-whitespace-1.rs:1:3 | LL | --- - | ^^ + | ^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/frontmatter/frontmatter-whitespace-2.rs b/tests/ui/frontmatter/frontmatter-whitespace-2.rs index e8c100849b4..7a28e5c1b85 100644 --- a/tests/ui/frontmatter/frontmatter-whitespace-2.rs +++ b/tests/ui/frontmatter/frontmatter-whitespace-2.rs @@ -1,4 +1,5 @@ ---cargo +//~^ ERROR: unclosed frontmatter //@ compile-flags: --crate-type lib @@ -6,10 +7,8 @@ fn foo(x: i32) -> i32 { ---x - //~^ ERROR: invalid preceding whitespace for frontmatter close - //~| ERROR: extra characters after frontmatter close are not allowed + //~^ WARNING: use of a double negation [double_negations] } -//~^ ERROR: unexpected closing delimiter: `}` // this test is for the weird case that valid Rust code can have three dashes // within them and get treated as a frontmatter close. diff --git a/tests/ui/frontmatter/frontmatter-whitespace-2.stderr b/tests/ui/frontmatter/frontmatter-whitespace-2.stderr index ada6af0ec04..2ae63cdc6fe 100644 --- a/tests/ui/frontmatter/frontmatter-whitespace-2.stderr +++ b/tests/ui/frontmatter/frontmatter-whitespace-2.stderr @@ -1,26 +1,30 @@ -error: invalid preceding whitespace for frontmatter close - --> $DIR/frontmatter-whitespace-2.rs:8:1 +error: unclosed frontmatter + --> $DIR/frontmatter-whitespace-2.rs:1:1 | -LL | ---x - | ^^^^^^^^ +LL | / ---cargo +... | +LL | | + | |_^ | -note: frontmatter close should not be preceded by whitespace - --> $DIR/frontmatter-whitespace-2.rs:8:1 +note: frontmatter opening here was not closed + --> $DIR/frontmatter-whitespace-2.rs:1:1 | -LL | ---x - | ^^^^ +LL | ---cargo + | ^^^ -error: extra characters after frontmatter close are not allowed - --> $DIR/frontmatter-whitespace-2.rs:8:1 +warning: use of a double negation + --> $DIR/frontmatter-whitespace-2.rs:9:6 | LL | ---x - | ^^^^^^^^ - -error: unexpected closing delimiter: `}` - --> $DIR/frontmatter-whitespace-2.rs:11:1 + | ^^^ + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value + = note: `#[warn(double_negations)]` on by default +help: add parentheses for clarity | -LL | } - | ^ unexpected closing delimiter +LL | --(-x) + | + + -error: aborting due to 3 previous errors +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/frontmatter/multifrontmatter-2.rs b/tests/ui/frontmatter/multifrontmatter-2.rs index 33cc30cb465..8e5b45a0bf7 100644 --- a/tests/ui/frontmatter/multifrontmatter-2.rs +++ b/tests/ui/frontmatter/multifrontmatter-2.rs @@ -1,12 +1,12 @@ --- --- -//~^ ERROR: invalid preceding whitespace for frontmatter close --- -//~^ ERROR: expected item, found `-` -// FIXME(frontmatter): make this diagnostic better --- +// hyphens only need to be escaped when at the start of a line +//@ check-pass + #![feature(frontmatter)] fn main() {} diff --git a/tests/ui/frontmatter/multifrontmatter-2.stderr b/tests/ui/frontmatter/multifrontmatter-2.stderr deleted file mode 100644 index ed9ac4029e2..00000000000 --- a/tests/ui/frontmatter/multifrontmatter-2.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: invalid preceding whitespace for frontmatter close - --> $DIR/multifrontmatter-2.rs:2:1 - | -LL | --- - | ^^^^ - | -note: frontmatter close should not be preceded by whitespace - --> $DIR/multifrontmatter-2.rs:2:1 - | -LL | --- - | ^ - -error: expected item, found `-` - --> $DIR/multifrontmatter-2.rs:5:2 - | -LL | --- - | ^ expected item - | - = note: for a full list of items that can appear in modules, see <https://doc.rust-lang.org/reference/items.html> - -error: aborting due to 2 previous errors - diff --git a/tests/ui/loop-match/diverges.rs b/tests/ui/loop-match/diverges.rs new file mode 100644 index 00000000000..f1b3ffb2076 --- /dev/null +++ b/tests/ui/loop-match/diverges.rs @@ -0,0 +1,44 @@ +//@ build-pass +//@ compile-flags: -Zvalidate-mir +#![allow(incomplete_features)] +#![feature(loop_match)] +#![crate_type = "lib"] + +// Test that a #[loop_match] without an explicit break from the loop generates valid MIR. + +fn break_to_block_unit() -> u8 { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + _ => 'b: { + break 'b 2; + } + } + } + } +} + +fn break_to_block_value() -> u8 { + let mut state = 0u8; + #[loop_match] + 'a: loop { + state = 'blk: { + match state { + _ => break 'blk state, + } + } + } +} + +fn infinite_a(mut state: u8) { + #[loop_match] + loop { + state = 'blk: { + match state { + a => a, + } + } + } +} diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs new file mode 100644 index 00000000000..d2bd31b06d6 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.rs @@ -0,0 +1,21 @@ +// issue: <https://github.com/rust-lang/rust/issues/140479> +// Ensure a proper compiler error, instead of an ICE occurs. +// FIXME(macro_metavar_expr_concat): this error message could be improved +#![feature(macro_metavar_expr_concat)] + +macro_rules! InRepetition { + ( + $( + $($arg:ident),+ + )+ + ) => { + $( + $( + ${concat(_, $arg)} //~ ERROR nested repetitions with `${concat(...)}` metavariable expressions are not yet supported + )* + )* + }; +} +InRepetition!(other); + +fn main() {} diff --git a/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr new file mode 100644 index 00000000000..ec39ca799e1 --- /dev/null +++ b/tests/ui/macros/macro-metavar-expr-concat/in-repetition.stderr @@ -0,0 +1,8 @@ +error: nested repetitions with `${concat(...)}` metavariable expressions are not yet supported + --> $DIR/in-repetition.rs:14:30 + | +LL | ${concat(_, $arg)} + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs index 78e5c961802..9277994d9b3 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.rs +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.rs @@ -5,6 +5,6 @@ fn main() {} fn foo(_: Bar, ...) -> impl {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR cannot find type `Bar` in this scope //~| ERROR at least one trait must be specified diff --git a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr index 80a8a94aea4..4a1aa49eb6e 100644 --- a/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr +++ b/tests/ui/mir/issue-83499-input-output-iteration-ice.stderr @@ -1,4 +1,4 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/issue-83499-input-output-iteration-ice.rs:7:16 | LL | fn foo(_: Bar, ...) -> impl {} diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index 1cd6d13d56b..e7a0248cffa 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -4,29 +4,29 @@ fn main() {} fn f1_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn f1_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f2_3(..., x: isize) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function extern "C" fn f3_1(x: isize, ...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f3_2(...) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention extern "C" fn f3_3(..., x: isize) {} -//~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function const unsafe extern "C" fn f4_1(x: isize, ...) {} @@ -35,12 +35,12 @@ const unsafe extern "C" fn f4_1(x: isize, ...) {} const extern "C" fn f4_2(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic -//~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic -//~| ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +//~| ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function extern "C" { @@ -52,34 +52,34 @@ struct X; impl X { fn i_f1(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn i_f2(...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn i_f3(..., x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function fn i_f4(..., x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function const fn i_f5(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR functions cannot be both `const` and C-variadic //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { fn t_f1(x: isize, ...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f2(x: isize, ...); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f3(...) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f4(...); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention fn t_f5(..., x: isize) {} - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function fn t_f6(..., x: isize); - //~^ ERROR only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg + //~^ ERROR defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention //~| ERROR `...` must be the last argument of a C-variadic function } diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index b740cef0200..5379045967a 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -1,22 +1,22 @@ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:6:19 | LL | fn f1_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:9:9 | LL | fn f1_2(...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:12:30 | LL | extern "C" fn f2_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:15:20 | LL | extern "C" fn f2_2(...) {} @@ -28,19 +28,19 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:18:20 | LL | extern "C" fn f2_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:22:30 | LL | extern "C" fn f3_1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:25:20 | LL | extern "C" fn f3_2(...) {} @@ -52,7 +52,7 @@ error: `...` must be the last argument of a C-variadic function LL | extern "C" fn f3_3(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:28:20 | LL | extern "C" fn f3_3(..., x: isize) {} @@ -70,7 +70,7 @@ error: functions cannot be both `const` and C-variadic LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:36:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} @@ -91,7 +91,7 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} | | C-variadic because of this | `const` because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:41:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} @@ -103,13 +103,13 @@ error: `...` must be the last argument of a C-variadic function LL | fn e_f2(..., x: isize); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:54:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:56:13 | LL | fn i_f2(...) {} @@ -121,7 +121,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f3(..., x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:58:13 | LL | fn i_f3(..., x: isize, ...) {} @@ -133,7 +133,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn i_f4(..., x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f4(..., x: isize, ...) {} @@ -147,31 +147,31 @@ LL | const fn i_f5(x: isize, ...) {} | | | `const` because of this -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:64:29 | LL | const fn i_f5(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:71:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:73:23 | LL | fn t_f2(x: isize, ...); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:75:13 | LL | fn t_f3(...) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:77:13 | LL | fn t_f4(...); @@ -183,7 +183,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f5(..., x: isize) {} | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:79:13 | LL | fn t_f5(..., x: isize) {} @@ -195,7 +195,7 @@ error: `...` must be the last argument of a C-variadic function LL | fn t_f6(..., x: isize); | ^^^ -error: only foreign, `unsafe extern "C"`, or `unsafe extern "C-unwind"` functions may have a C-variadic arg +error: defining functions with C-variadic arguments is only allowed for free functions with the "C" or "C-unwind" calling convention --> $DIR/variadic-ffi-semantic-restrictions.rs:82:13 | LL | fn t_f6(..., x: isize); diff --git a/tests/ui/privacy/private-field-ty-err.stderr b/tests/ui/privacy/private-field-ty-err.stderr index 17d50f24a94..0eecad14cfc 100644 --- a/tests/ui/privacy/private-field-ty-err.stderr +++ b/tests/ui/privacy/private-field-ty-err.stderr @@ -3,6 +3,11 @@ error[E0616]: field `len` of struct `Foo` is private | LL | if x.len { | ^^^ private field + | +help: a method `len` also exists, call it with parentheses + | +LL | if x.len() { + | ++ error: aborting due to 1 previous error diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 72a9820bb64..4a73a4747ad 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -23,10 +23,10 @@ ast-stats - Path 72 (NN.N%) 1 ast-stats - Struct 72 (NN.N%) 1 ast-stats - Lit 144 (NN.N%) 2 ast-stats - Block 216 (NN.N%) 3 -ast-stats Pat 504 (NN.N%) 7 72 -ast-stats - Struct 72 (NN.N%) 1 -ast-stats - Wild 72 (NN.N%) 1 -ast-stats - Ident 360 (NN.N%) 5 +ast-stats Pat 560 (NN.N%) 7 80 +ast-stats - Struct 80 (NN.N%) 1 +ast-stats - Wild 80 (NN.N%) 1 +ast-stats - Ident 400 (NN.N%) 5 ast-stats GenericParam 480 (NN.N%) 5 96 ast-stats GenericBound 352 (NN.N%) 4 88 ast-stats - Trait 352 (NN.N%) 4 @@ -57,7 +57,7 @@ ast-stats GenericArgs 40 (NN.N%) 1 40 ast-stats - AngleBracketed 40 (NN.N%) 1 ast-stats Crate 40 (NN.N%) 1 40 ast-stats ---------------------------------------------------------------- -ast-stats Total 7_472 129 +ast-stats Total 7_528 129 ast-stats ================================================================ hir-stats ================================================================ hir-stats HIR STATS: input_stats @@ -85,11 +85,11 @@ hir-stats - Ptr 48 (NN.N%) 1 hir-stats - Ref 48 (NN.N%) 1 hir-stats - Path 624 (NN.N%) 13 hir-stats Generics 560 (NN.N%) 10 56 +hir-stats Pat 400 (NN.N%) 5 80 +hir-stats - Struct 80 (NN.N%) 1 +hir-stats - Wild 80 (NN.N%) 1 +hir-stats - Binding 240 (NN.N%) 3 hir-stats GenericParam 400 (NN.N%) 5 80 -hir-stats Pat 360 (NN.N%) 5 72 -hir-stats - Struct 72 (NN.N%) 1 -hir-stats - Wild 72 (NN.N%) 1 -hir-stats - Binding 216 (NN.N%) 3 hir-stats Block 288 (NN.N%) 6 48 hir-stats GenericBound 256 (NN.N%) 4 64 hir-stats - Trait 256 (NN.N%) 4 @@ -119,5 +119,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_584 173 +hir-stats Total 8_624 173 hir-stats ================================================================ diff --git a/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs b/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs new file mode 100644 index 00000000000..39797574b97 --- /dev/null +++ b/tests/ui/suggestions/negative-literal-infered-to-unsigned.rs @@ -0,0 +1,13 @@ +fn main() { + for x in -5..5 { + //~^ ERROR: the trait bound `usize: Neg` is not satisfied + //~| HELP: consider specifying an integer type that can be negative + do_something(x); + } + let x = -5; + //~^ ERROR: the trait bound `usize: Neg` is not satisfied + //~| HELP: consider specifying an integer type that can be negative + do_something(x); +} + +fn do_something(_val: usize) {} diff --git a/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr b/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr new file mode 100644 index 00000000000..b49ea224d2b --- /dev/null +++ b/tests/ui/suggestions/negative-literal-infered-to-unsigned.stderr @@ -0,0 +1,25 @@ +error[E0277]: the trait bound `usize: Neg` is not satisfied + --> $DIR/negative-literal-infered-to-unsigned.rs:2:14 + | +LL | for x in -5..5 { + | ^^ the trait `Neg` is not implemented for `usize` + | +help: consider specifying an integer type that can be negative + | +LL | for x in -5isize..5 { + | +++++ + +error[E0277]: the trait bound `usize: Neg` is not satisfied + --> $DIR/negative-literal-infered-to-unsigned.rs:7:13 + | +LL | let x = -5; + | ^^ the trait `Neg` is not implemented for `usize` + | +help: consider specifying an integer type that can be negative + | +LL | let x = -5isize; + | +++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.rs b/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.rs new file mode 100644 index 00000000000..671f280e814 --- /dev/null +++ b/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.rs @@ -0,0 +1,14 @@ +struct LlamaModel; + +impl LlamaModel { + fn chat_template(&self) -> Result<&str, ()> { + todo!() + } +} + +fn template_from_str(_x: &str) {} + +fn main() { + let model = LlamaModel; + template_from_str(&model.chat_template); //~ ERROR attempted to take value of method `chat_template` on type `LlamaModel` +} diff --git a/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.stderr b/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.stderr new file mode 100644 index 00000000000..7f5dd0617b1 --- /dev/null +++ b/tests/ui/typeck/suggest-method-name-with-maybe-ty-mismatch-146008.stderr @@ -0,0 +1,14 @@ +error[E0615]: attempted to take value of method `chat_template` on type `LlamaModel` + --> $DIR/suggest-method-name-with-maybe-ty-mismatch-146008.rs:13:30 + | +LL | template_from_str(&model.chat_template); + | ^^^^^^^^^^^^^ method, not a field + | +help: use parentheses to call the method + | +LL | template_from_str(&model.chat_template()); + | ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0615`. |
