From 8946711b25d0e7f76f0a517fe0636c74666ccdc9 Mon Sep 17 00:00:00 2001 From: Sasha Pourcelot Date: Sun, 22 Mar 2026 12:24:11 +0000 Subject: [PATCH 01/61] tidy-alphabetical: fix line number in error message --- src/tools/tidy/src/alphabetical.rs | 6 +++++- src/tools/tidy/src/alphabetical/tests.rs | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs index 4ef1775d4bed9..77cbdcbd37aa2 100644 --- a/src/tools/tidy/src/alphabetical.rs +++ b/src/tools/tidy/src/alphabetical.rs @@ -215,7 +215,11 @@ fn check_lines<'a>(path: &Path, content: &'a str, tidy_ctx: &TidyCtx, check: &mu // oh nyooo :( if sorted != section { if !tidy_ctx.is_bless_enabled() { - let base_line_number = content[..offset + start_nl_end].lines().count(); + let pre = &content[..offset + start_nl_end]; + assert_eq!(pre.chars().rev().next(), Some('\n')); + // start_nl_end spans right after the ␤, so it gets ignored by `lines()`, + // but we do want to count it! so we add 1 to the result. + let base_line_number = pre.lines().count() + 1; let line_offset = sorted .lines() .zip(section.lines()) diff --git a/src/tools/tidy/src/alphabetical/tests.rs b/src/tools/tidy/src/alphabetical/tests.rs index c1192986e63f2..96dad53fa359f 100644 --- a/src/tools/tidy/src/alphabetical/tests.rs +++ b/src/tools/tidy/src/alphabetical/tests.rs @@ -115,7 +115,7 @@ fn test_rust_bad() { def // tidy-alphabetical-end "; - bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -127,7 +127,7 @@ fn test_toml_bad() { def # tidy-alphabetical-end "; - bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -141,7 +141,7 @@ fn test_features_bad() { #![feature(def)] tidy-alphabetical-end "; - bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -154,7 +154,7 @@ fn test_indent_bad() { def $ tidy-alphabetical-end "; - bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -170,7 +170,7 @@ fn test_split_bad() { ) && tidy-alphabetical-end "; - bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:4: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -339,7 +339,7 @@ fn test_numeric_bad() { item2 # tidy-alphabetical-end "; - bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:3: line not in alphabetical order (tip: use --bless to sort this list)"); let lines = "\ # tidy-alphabetical-start @@ -347,7 +347,7 @@ fn test_numeric_bad() { zve64d # tidy-alphabetical-end "; - bad(lines, "bad:1: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); let lines = "\ # tidy-alphabetical-start @@ -355,7 +355,7 @@ fn test_numeric_bad() { 00 # tidy-alphabetical-end "; - bad(lines, "bad:1: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); } #[test] @@ -394,7 +394,7 @@ fn multiline() { ); tidy-alphabetical-end "; - bad(lines, "bad:1: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); let lines = "\ tidy-alphabetical-start @@ -406,7 +406,7 @@ fn multiline() { a); tidy-alphabetical-end "; - bad(lines, "bad:1: line not in alphabetical order (tip: use --bless to sort this list)"); + bad(lines, "bad:2: line not in alphabetical order (tip: use --bless to sort this list)"); let lines = "\ force_unwind_tables: Option = (None, parse_opt_bool, [TRACKED], From 5f2790c3412994b7aaef5ccf350030cd6c4a6ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Mar 2026 10:16:12 +0100 Subject: [PATCH 02/61] using rustc in the middle of an attrpath errors --- tests/ui/attributes/rustc-in-attr-path.rs | 9 +++++++++ tests/ui/attributes/rustc-in-attr-path.stderr | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 tests/ui/attributes/rustc-in-attr-path.rs create mode 100644 tests/ui/attributes/rustc-in-attr-path.stderr diff --git a/tests/ui/attributes/rustc-in-attr-path.rs b/tests/ui/attributes/rustc-in-attr-path.rs new file mode 100644 index 0000000000000..302f0239de03d --- /dev/null +++ b/tests/ui/attributes/rustc-in-attr-path.rs @@ -0,0 +1,9 @@ +mod rustc { + pub use std::prelude::v1::test; +} + +#[crate::rustc::test] +//~^ ERROR: attributes starting with `rustc` are reserved for use by the `rustc` compiler +fn foo() {} + +fn main() {} diff --git a/tests/ui/attributes/rustc-in-attr-path.stderr b/tests/ui/attributes/rustc-in-attr-path.stderr new file mode 100644 index 0000000000000..62f96a36480b6 --- /dev/null +++ b/tests/ui/attributes/rustc-in-attr-path.stderr @@ -0,0 +1,8 @@ +error: attributes starting with `rustc` are reserved for use by the `rustc` compiler + --> $DIR/rustc-in-attr-path.rs:5:10 + | +LL | #[crate::rustc::test] + | ^^^^^ + +error: aborting due to 1 previous error + From 043bd767688281d574ea8cc0c368156021baa61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 27 Feb 2026 06:23:06 +0100 Subject: [PATCH 03/61] Make `layout_of` cycles fatal errors --- compiler/rustc_codegen_llvm/src/context.rs | 6 +----- .../src/interpret/eval_context.rs | 3 +-- .../src/hir_ty_lowering/cmse.rs | 3 +-- compiler/rustc_middle/src/ty/layout.rs | 6 +----- .../src/handle_cycle_error.rs | 4 +--- compiler/rustc_transmute/src/layout/tree.rs | 1 - .../html/templates/type_layout.html | 5 ----- tests/ui/layout/layout-cycle.rs | 1 - tests/ui/layout/layout-cycle.stderr | 16 ++------------ tests/ui/layout/post-mono-layout-cycle.stderr | 6 ------ ...ck-overflow-trait-infer-98842.64bit.stderr | 21 ------------------- .../sized/stack-overflow-trait-infer-98842.rs | 4 +--- ...> stack-overflow-trait-infer-98842.stderr} | 13 +++--------- 13 files changed, 11 insertions(+), 78 deletions(-) delete mode 100644 tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr rename tests/ui/sized/{stack-overflow-trait-infer-98842.32bit.stderr => stack-overflow-trait-infer-98842.stderr} (55%) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index e02c4ae6ea695..80d939a25701e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1134,11 +1134,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> { fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { match err { - FnAbiError::Layout( - LayoutError::SizeOverflow(_) - | LayoutError::Cycle(_) - | LayoutError::InvalidSimd { .. }, - ) => { + FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) => { self.tcx.dcx().emit_fatal(Spanned { span, node: err }); } _ => match fn_abi_request { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 0bfe012bfe7a4..04f0e7099d840 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -107,8 +107,7 @@ impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> { | LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. } | LayoutError::TooGeneric(_) - | LayoutError::ReferencesError(_) - | LayoutError::Cycle(_) => {} + | LayoutError::ReferencesError(_) => {} } err_inval!(Layout(err)) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 58c296d92c24e..a1b169c6a1661 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -194,8 +194,7 @@ fn should_emit_layout_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError< | SizeOverflow(..) | InvalidSimd { .. } | NormalizationFailure(..) - | ReferencesError(..) - | Cycle(..) => { + | ReferencesError(..) => { false // not our job to report these } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4ca51c078bef5..46682abc823d8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -260,8 +260,6 @@ pub enum LayoutError<'tcx> { NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), /// A non-layout error is reported elsewhere. ReferencesError(ErrorGuaranteed), - /// A type has cyclic layout, i.e. the type contains itself without indirection. - Cycle(ErrorGuaranteed), } impl<'tcx> fmt::Display for LayoutError<'tcx> { @@ -286,7 +284,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { t, e.get_type_for_failure() ), - LayoutError::Cycle(_) => write!(f, "a cycle occurred during layout computation"), LayoutError::ReferencesError(_) => write!(f, "the type has an unknown layout"), } } @@ -358,8 +355,7 @@ impl<'tcx> SizeSkeleton<'tcx> { Err(err @ LayoutError::TooGeneric(_)) => err, // We can't extract SizeSkeleton info from other layout errors Err( - e @ LayoutError::Cycle(_) - | e @ LayoutError::Unknown(_) + e @ LayoutError::Unknown(_) | e @ LayoutError::SizeOverflow(_) | e @ LayoutError::InvalidSimd { .. } | e @ LayoutError::NormalizationFailure(..) diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index 5676669bf1c0e..22f8ac9837f6d 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -12,7 +12,6 @@ use rustc_middle::bug; use rustc_middle::queries::{QueryVTables, TaggedQueryKey}; use rustc_middle::query::Cycle; use rustc_middle::query::erase::erase_val; -use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::{ErrorGuaranteed, Span}; @@ -203,8 +202,7 @@ fn layout_of<'tcx>(tcx: TyCtxt<'tcx>, cycle: Cycle<'tcx>) -> &'tcx ty::layout::L || create_cycle_error(tcx, &cycle), ); - let guar = diag.emit(); - tcx.arena.alloc(LayoutError::Cycle(guar)) + diag.emit().raise_fatal() } // item_and_field_ids should form a cycle where each field contains the diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 1202ed2384315..1bfe6e94cc3b6 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -282,7 +282,6 @@ pub(crate) mod rustc { | LayoutError::InvalidSimd { .. } | LayoutError::NormalizationFailure(..) => Self::UnknownLayout, LayoutError::SizeOverflow(..) => Self::SizeOverflow, - LayoutError::Cycle(err) => Self::TypeError(*err), } } } diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 49153d58fe98c..4d4222a34956a 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -60,11 +60,6 @@

{# #} Note: Encountered an error during type layout; {#+ #} the type failed to be normalized. {# #}

- {% when Err(LayoutError::Cycle(_)) %} -

{# #} - Note: Encountered an error during type layout; {#+ #} - the type's layout depended on the type's layout itself. {# #} -

{% when Err(LayoutError::InvalidSimd {..}) %}

{# #} Note: Encountered an error during type layout; {#+ #} diff --git a/tests/ui/layout/layout-cycle.rs b/tests/ui/layout/layout-cycle.rs index b38bd52c6ade9..846ce0882cad1 100644 --- a/tests/ui/layout/layout-cycle.rs +++ b/tests/ui/layout/layout-cycle.rs @@ -1,6 +1,5 @@ //@ build-fail //~^ ERROR: cycle detected when computing layout of -//~? ERROR: a cycle occurred during layout computation // Issue #111176 -- ensure that we do not emit ICE on layout cycles diff --git a/tests/ui/layout/layout-cycle.stderr b/tests/ui/layout/layout-cycle.stderr index e05ff614567c4..28c35d431226e 100644 --- a/tests/ui/layout/layout-cycle.stderr +++ b/tests/ui/layout/layout-cycle.stderr @@ -6,18 +6,6 @@ note: cycle used when const-evaluating + checking `core::mem::SizedTypePropertie --> $SRC_DIR/core/src/mem/mod.rs:LL:COL = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0080]: a cycle occurred during layout computation - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL - | - = note: evaluation of `> as std::mem::SizedTypeProperties>::SIZE` failed here - -note: the above error was encountered while instantiating `fn std::mem::size_of::>>` - --> $DIR/layout-cycle.rs:26:5 - | -LL | mem::size_of::>() - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0080, E0391. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr index 7f246b3d409ad..b9b1b988499e6 100644 --- a/tests/ui/layout/post-mono-layout-cycle.stderr +++ b/tests/ui/layout/post-mono-layout-cycle.stderr @@ -5,12 +5,6 @@ error[E0391]: cycle detected when computing layout of `Wrapper<()>` = note: cycle used when computing layout of `core::option::Option>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -note: the above error was encountered while instantiating `fn abi::<()>` - --> $DIR/post-mono-layout-cycle.rs:19:5 - | -LL | abi::(None); - | ^^^^^^^^^^^^^^ - error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr deleted file mode 100644 index d097b809b5698..0000000000000 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0391]: cycle detected when computing layout of `Foo` - | - = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... - = note: ...which again requires computing layout of `Foo`, completing the cycle -note: cycle used when const-evaluating + checking `_` - --> $DIR/stack-overflow-trait-infer-98842.rs:14:1 - | -LL | const _: *const Foo = 0 as _; - | ^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0080]: a cycle occurred during layout computation - --> $DIR/stack-overflow-trait-infer-98842.rs:14:1 - | -LL | const _: *const Foo = 0 as _; - | ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0080, E0391. -For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs index 1c9f6c593f447..d6522e3cfb643 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs @@ -2,8 +2,7 @@ // issue: rust-lang/rust#98842 //@ check-fail //@ edition:2021 -//@ stderr-per-bitwidth -//~^^^^^ ERROR cycle detected when computing layout of `Foo` +//~^^^^ ERROR cycle detected when computing layout of `Foo` // If the inner `Foo` is named through an associated type, // the "infinite size" error does not occur. @@ -12,6 +11,5 @@ struct Foo(<&'static Foo as ::core::ops::Deref>::Target); // and it will infinitely recurse somewhere trying to figure out the // size of this pointer (is my guess): const _: *const Foo = 0 as _; -//~^ ERROR a cycle occurred during layout computation pub fn main() {} diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr similarity index 55% rename from tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr rename to tests/ui/sized/stack-overflow-trait-infer-98842.stderr index d097b809b5698..5557a6fc45b89 100644 --- a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr +++ b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr @@ -3,19 +3,12 @@ error[E0391]: cycle detected when computing layout of `Foo` = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`... = note: ...which again requires computing layout of `Foo`, completing the cycle note: cycle used when const-evaluating + checking `_` - --> $DIR/stack-overflow-trait-infer-98842.rs:14:1 + --> $DIR/stack-overflow-trait-infer-98842.rs:13:1 | LL | const _: *const Foo = 0 as _; | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0080]: a cycle occurred during layout computation - --> $DIR/stack-overflow-trait-infer-98842.rs:14:1 - | -LL | const _: *const Foo = 0 as _; - | ^^^^^^^^^^^^^^^^^^^ evaluation of `_` failed here - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0080, E0391. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0391`. From 4fd1d9713af32df00514bb57e5e888b84d34291d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 16 Mar 2026 22:18:59 +0100 Subject: [PATCH 04/61] Skip ICE message for fatal errors --- src/tools/miri/src/eval.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 1e75df7d278fb..cf4f7d689ac22 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -10,6 +10,7 @@ use std::{iter, thread}; use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::FatalErrorMarker; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutCx}; @@ -477,7 +478,11 @@ pub fn eval_entry<'tcx>( let res: thread::Result> = panic::catch_unwind(AssertUnwindSafe(|| ecx.run_threads())); let res = res.unwrap_or_else(|panic_payload| { - ecx.handle_ice(); + // rustc "handles" some errors by unwinding with FatalErrorMarker + // (after emitting suitable diagnostics), so do not treat those as ICEs. + if !panic_payload.is::() { + ecx.handle_ice(); + } panic::resume_unwind(panic_payload) }); // Obtain the result of the execution. This is always an `Err`, but that doesn't necessarily From db30a36c8edb360eb16de681ff07972980dfbba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 16 Mar 2026 22:19:21 +0100 Subject: [PATCH 05/61] Update tests --- src/tools/miri/tests/fail/layout_cycle.rs | 3 +-- src/tools/miri/tests/fail/layout_cycle.stderr | 11 ++--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/tools/miri/tests/fail/layout_cycle.rs b/src/tools/miri/tests/fail/layout_cycle.rs index 3e0dd881db84e..8d5f1914d0c32 100644 --- a/src/tools/miri/tests/fail/layout_cycle.rs +++ b/src/tools/miri/tests/fail/layout_cycle.rs @@ -1,5 +1,4 @@ -//@error-in-other-file: a cycle occurred during layout computation -//~^ ERROR: cycle detected when computing layout of +//~ ERROR: cycle detected when computing layout of use std::mem; diff --git a/src/tools/miri/tests/fail/layout_cycle.stderr b/src/tools/miri/tests/fail/layout_cycle.stderr index dae6934931228..f8d555e5a10b8 100644 --- a/src/tools/miri/tests/fail/layout_cycle.stderr +++ b/src/tools/miri/tests/fail/layout_cycle.stderr @@ -9,13 +9,6 @@ LL | const SIZE: usize = intrinsics::size_of::(); | ^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0080]: a cycle occurred during layout computation - --> RUSTLIB/core/src/mem/mod.rs:LL:CC - | -LL | const SIZE: usize = intrinsics::size_of::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `> as std::mem::SizedTypeProperties>::SIZE` failed here - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0080, E0391. -For more information about an error, try `rustc --explain E0080`. +For more information about this error, try `rustc --explain E0391`. From 3250d8d28bc6a15ea239ce928b15c3fb4292493e Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Thu, 26 Mar 2026 19:55:26 +0530 Subject: [PATCH 06/61] Move 3 files (2 .rs and 1 .stderr) from ui/issues to ui/transmute --- .../transmute-associated-type-to-slice.rs} | 0 .../transmute-associated-type-to-slice.stderr} | 0 .../issue-23477.rs => transmute/transmute-slice-to-dst.rs} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-28625.rs => transmute/transmute-associated-type-to-slice.rs} (100%) rename tests/ui/{issues/issue-28625.stderr => transmute/transmute-associated-type-to-slice.stderr} (100%) rename tests/ui/{issues/issue-23477.rs => transmute/transmute-slice-to-dst.rs} (100%) diff --git a/tests/ui/issues/issue-28625.rs b/tests/ui/transmute/transmute-associated-type-to-slice.rs similarity index 100% rename from tests/ui/issues/issue-28625.rs rename to tests/ui/transmute/transmute-associated-type-to-slice.rs diff --git a/tests/ui/issues/issue-28625.stderr b/tests/ui/transmute/transmute-associated-type-to-slice.stderr similarity index 100% rename from tests/ui/issues/issue-28625.stderr rename to tests/ui/transmute/transmute-associated-type-to-slice.stderr diff --git a/tests/ui/issues/issue-23477.rs b/tests/ui/transmute/transmute-slice-to-dst.rs similarity index 100% rename from tests/ui/issues/issue-23477.rs rename to tests/ui/transmute/transmute-slice-to-dst.rs From 58ceac1edd17de578b1d9275139b6a4dd6dd4272 Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Thu, 26 Mar 2026 19:59:01 +0530 Subject: [PATCH 07/61] Add issue link at the top in file tests/ui/transmute/transmute-slice-to-dst.rs --- tests/ui/transmute/transmute-slice-to-dst.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/transmute/transmute-slice-to-dst.rs b/tests/ui/transmute/transmute-slice-to-dst.rs index fa69a1d762682..c1f77bee284dd 100644 --- a/tests/ui/transmute/transmute-slice-to-dst.rs +++ b/tests/ui/transmute/transmute-slice-to-dst.rs @@ -1,3 +1,4 @@ +//! regression test for //@ build-pass //@ compile-flags: -g From e0f17b9f4459f56050b8be4067217aa39a416054 Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Thu, 26 Mar 2026 20:06:49 +0530 Subject: [PATCH 08/61] Add issue link, and update trait and type names for better readability --- .../transmute-associated-type-to-slice.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/ui/transmute/transmute-associated-type-to-slice.rs b/tests/ui/transmute/transmute-associated-type-to-slice.rs index 54ed408e74881..9521a944391cc 100644 --- a/tests/ui/transmute/transmute-associated-type-to-slice.rs +++ b/tests/ui/transmute/transmute-associated-type-to-slice.rs @@ -1,19 +1,20 @@ +//! regression test for //@ normalize-stderr: "\d+ bits" -> "N bits" -trait Bar { - type Bar; +trait MyTrait { + type MyType; } -struct ArrayPeano { - data: T::Bar, +struct ArrayPeano { + data: T::MyType, } -fn foo(a: &ArrayPeano) -> &[T] where T: Bar { +fn foo(a: &ArrayPeano) -> &[T] where T: MyTrait { unsafe { std::mem::transmute(a) } //~ ERROR cannot transmute between types of different sizes } -impl Bar for () { - type Bar = (); +impl MyTrait for () { + type MyType = (); } fn main() { From a261c8c16e9a8c61086b13c8ffa33ff6ea136343 Mon Sep 17 00:00:00 2001 From: ujjwalVishwakarma2006 <2023ucs0116@iitjammu.ac.in> Date: Thu, 26 Mar 2026 20:07:20 +0530 Subject: [PATCH 09/61] Add updated .stderr file --- tests/ui/transmute/transmute-associated-type-to-slice.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/transmute/transmute-associated-type-to-slice.stderr b/tests/ui/transmute/transmute-associated-type-to-slice.stderr index 3600622a45424..ada3153165e57 100644 --- a/tests/ui/transmute/transmute-associated-type-to-slice.stderr +++ b/tests/ui/transmute/transmute-associated-type-to-slice.stderr @@ -1,5 +1,5 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-sized types - --> $DIR/issue-28625.rs:12:14 + --> $DIR/transmute-associated-type-to-slice.rs:13:14 | LL | unsafe { std::mem::transmute(a) } | ^^^^^^^^^^^^^^^^^^^ From f1797f8cf4ed1bad69309f445d55a4f8ef749ac0 Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sat, 28 Mar 2026 14:28:02 -0400 Subject: [PATCH 10/61] Moved and renamed issue-34571.rs to enum/enum_u8_variant.rs --- tests/ui/{issues/issue-34571.rs => enum/enum_u8_variant.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-34571.rs => enum/enum_u8_variant.rs} (100%) diff --git a/tests/ui/issues/issue-34571.rs b/tests/ui/enum/enum_u8_variant.rs similarity index 100% rename from tests/ui/issues/issue-34571.rs rename to tests/ui/enum/enum_u8_variant.rs From 6d8c10ebca0bcb628bfcfead2b62e5aa784faed5 Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sat, 28 Mar 2026 14:32:22 -0400 Subject: [PATCH 11/61] Added description and orignal issue link to enum_u8_variant.rs --- tests/ui/enum/enum_u8_variant.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/enum/enum_u8_variant.rs b/tests/ui/enum/enum_u8_variant.rs index 1242a9e2b5c01..67ea59085a946 100644 --- a/tests/ui/enum/enum_u8_variant.rs +++ b/tests/ui/enum/enum_u8_variant.rs @@ -1,4 +1,6 @@ //@ run-pass +//Test that checks pattern matching works correctly on a repr(u8) enum whose only variant contains an inner 'u8' field +//https://github.com/rust-lang/rust/issues/34571 #[repr(u8)] enum Foo { Foo(#[allow(dead_code)] u8), From 09e48be115db26b2c29349dcaade646f0bde7525 Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sat, 28 Mar 2026 20:58:22 -0400 Subject: [PATCH 12/61] Moved and renamed issue-49973.rs to layout/opt-repr-i32-min.rs --- tests/ui/{issues/issue-49973.rs => layout/opt-repr-i32-min.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-49973.rs => layout/opt-repr-i32-min.rs} (100%) diff --git a/tests/ui/issues/issue-49973.rs b/tests/ui/layout/opt-repr-i32-min.rs similarity index 100% rename from tests/ui/issues/issue-49973.rs rename to tests/ui/layout/opt-repr-i32-min.rs From 49ea8ce8f52f5667fc3024407b187873554c6b1e Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sat, 28 Mar 2026 21:03:45 -0400 Subject: [PATCH 13/61] Added link and test description for opt-repr-i32-min.rs --- tests/ui/layout/opt-repr-i32-min.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/layout/opt-repr-i32-min.rs b/tests/ui/layout/opt-repr-i32-min.rs index c8f7c8ea32fe7..4c5831ff04904 100644 --- a/tests/ui/layout/opt-repr-i32-min.rs +++ b/tests/ui/layout/opt-repr-i32-min.rs @@ -1,4 +1,6 @@ //@ run-pass +// Tests that Option niche optimisation does not incorrectly use i32::MIN as the None niche when a repr(i32) enum variant already holds that value. +// github.com/rust-lang/rust/issues/49973 #[derive(Debug)] #[repr(i32)] enum E { From 16c3d975e008b900d84cc2848606b01cea592d76 Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sun, 29 Mar 2026 21:19:32 -0400 Subject: [PATCH 14/61] Moved and renamed issue-38160 to macros/macro-const-stringify.rs --- .../issue-38160.rs => macros/macro-const-stringify.rs} | 5 ----- 1 file changed, 5 deletions(-) rename tests/ui/{issues/issue-38160.rs => macros/macro-const-stringify.rs} (98%) diff --git a/tests/ui/issues/issue-38160.rs b/tests/ui/macros/macro-const-stringify.rs similarity index 98% rename from tests/ui/issues/issue-38160.rs rename to tests/ui/macros/macro-const-stringify.rs index 0395aea63ee97..810f5e0c7f966 100644 --- a/tests/ui/issues/issue-38160.rs +++ b/tests/ui/macros/macro-const-stringify.rs @@ -1,19 +1,14 @@ //@ check-pass - trait MyTrait { const MY_CONST: &'static str; } - macro_rules! my_macro { () => { struct MyStruct; - impl MyTrait for MyStruct { const MY_CONST: &'static str = stringify!(abc); } } } - my_macro!(); - fn main() {} From c0e8750beac073b8d377db2d608fba45ff1e1cba Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Sun, 29 Mar 2026 21:22:14 -0400 Subject: [PATCH 15/61] Added issue link and description to macro-const-stringify.rs --- tests/ui/macros/macro-const-stringify.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui/macros/macro-const-stringify.rs b/tests/ui/macros/macro-const-stringify.rs index 810f5e0c7f966..e2a110ffd09c6 100644 --- a/tests/ui/macros/macro-const-stringify.rs +++ b/tests/ui/macros/macro-const-stringify.rs @@ -1,4 +1,6 @@ //@ check-pass +//Tests to check that a macro generating an impl block with stringify for a trait associated const +//https://github.com/rust-lang/rust/issues/38160 trait MyTrait { const MY_CONST: &'static str; } From 9bdf217810e77b7d58e43030dd61a65172ab1354 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 31 Mar 2026 12:51:12 -0500 Subject: [PATCH 16/61] rustdoc: seperate methods and associated functions in sidebar --- src/librustdoc/clean/types.rs | 9 ++ src/librustdoc/html/render/sidebar.rs | 132 ++++++++++++-------- tests/rustdoc-gui/hash-item-expansion.goml | 4 +- tests/rustdoc-gui/sidebar-mobile.goml | 2 +- tests/rustdoc-html/sidebar/sidebar-items.rs | 8 ++ tests/rustdoc-html/typedef.rs | 2 +- 6 files changed, 103 insertions(+), 54 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ad70fc1096691..7d40bc95ec089 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -465,6 +465,15 @@ impl Item { .unwrap_or(false) } + /// Returns true if item is an associated function with a `self` parameter. + pub(crate) fn has_self_param(&self) -> bool { + if let ItemKind::MethodItem(box Function { decl, .. }, _) = &self.inner.kind { + decl.receiver_type().is_some() + } else { + false + } + } + pub(crate) fn span(&self, tcx: TyCtxt<'_>) -> Option { let kind = match &self.kind { ItemKind::StrippedItem(k) => k, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index a4535792ac3ce..d40c9501cabc1 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -433,6 +433,7 @@ fn sidebar_assoc_items<'a>( let mut assoc_consts = Vec::new(); let mut assoc_types = Vec::new(); + let mut assoc_fns = Vec::new(); let mut methods = Vec::new(); if let Some(v) = cache.impls.get(&did) { let mut used_links = FxHashSet::default(); @@ -443,7 +444,12 @@ fn sidebar_assoc_items<'a>( for impl_ in v.iter().map(|i| i.inner_impl()).filter(|i| i.trait_.is_none()) { assoc_consts.extend(get_associated_constants(impl_, used_links_bor)); assoc_types.extend(get_associated_types(impl_, used_links_bor)); - methods.extend(get_methods(impl_, false, used_links_bor, false, cx.tcx())); + methods.extend(get_methods( + impl_, + GetMethodsMode::AlsoCollectAssocFns { assoc_fns: &mut assoc_fns }, + used_links_bor, + cx.tcx(), + )); } // We want links' order to be reproducible so we don't use unstable sort. assoc_consts.sort(); @@ -462,6 +468,11 @@ fn sidebar_assoc_items<'a>( "associatedtype", assoc_types, ), + LinkBlock::new( + Link::new("implementations", "Associated Functions"), + "method", + assoc_fns, + ), LinkBlock::new(Link::new("implementations", "Methods"), "method", methods), ]; @@ -546,7 +557,15 @@ fn sidebar_deref_methods<'a>( i.inner_impl().trait_.is_none() && real_target.is_doc_subtype_of(&i.inner_impl().for_, c) }) - .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx())) + .flat_map(|i| { + get_methods( + i.inner_impl(), + GetMethodsMode::Deref { deref_mut }, + used_links, + cx.tcx(), + ) + .collect::>() + }) .collect::>(); if !ret.is_empty() { let id = if let Some(target_def_id) = real_target.def_id(c) { @@ -734,69 +753,82 @@ fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { format!("{url}-{add}") } +enum GetMethodsMode<'r, 'l> { + Deref { deref_mut: bool }, + AlsoCollectAssocFns { assoc_fns: &'r mut Vec> }, +} + fn get_methods<'a>( i: &'a clean::Impl, - for_deref: bool, + mut mode: GetMethodsMode<'_, 'a>, used_links: &mut FxHashSet, - deref_mut: bool, tcx: TyCtxt<'_>, -) -> Vec> { - i.items - .iter() - .filter_map(|item| { - if let Some(ref name) = item.name - && item.is_method() - && (!for_deref || super::should_render_item(item, deref_mut, tcx)) - { - Some(Link::new( +) -> impl Iterator> { + i.items.iter().filter_map(move |item| { + if let Some(ref name) = item.name + && item.is_method() + { + let mut build_link = || { + Link::new( get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)), name.as_str(), - )) - } else { - None + ) + }; + match &mut mode { + &mut GetMethodsMode::Deref { deref_mut } => { + if super::should_render_item(item, deref_mut, tcx) { + Some(build_link()) + } else { + None + } + } + GetMethodsMode::AlsoCollectAssocFns { assoc_fns } => { + if item.has_self_param() { + Some(build_link()) + } else { + assoc_fns.push(build_link()); + None + } + } } - }) - .collect() + } else { + None + } + }) } fn get_associated_constants<'a>( i: &'a clean::Impl, used_links: &mut FxHashSet, -) -> Vec> { - i.items - .iter() - .filter_map(|item| { - if let Some(ref name) = item.name - && item.is_associated_const() - { - Some(Link::new( - get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)), - name.as_str(), - )) - } else { - None - } - }) - .collect() +) -> impl Iterator> { + i.items.iter().filter_map(|item| { + if let Some(ref name) = item.name + && item.is_associated_const() + { + Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)), + name.as_str(), + )) + } else { + None + } + }) } fn get_associated_types<'a>( i: &'a clean::Impl, used_links: &mut FxHashSet, -) -> Vec> { - i.items - .iter() - .filter_map(|item| { - if let Some(ref name) = item.name - && item.is_associated_type() - { - Some(Link::new( - get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)), - name.as_str(), - )) - } else { - None - } - }) - .collect() +) -> impl Iterator> { + i.items.iter().filter_map(|item| { + if let Some(ref name) = item.name + && item.is_associated_type() + { + Some(Link::new( + get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocType)), + name.as_str(), + )) + } else { + None + } + }) } diff --git a/tests/rustdoc-gui/hash-item-expansion.goml b/tests/rustdoc-gui/hash-item-expansion.goml index a7a5c3cb48345..8661641206685 100644 --- a/tests/rustdoc-gui/hash-item-expansion.goml +++ b/tests/rustdoc-gui/hash-item-expansion.goml @@ -5,7 +5,7 @@ assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"ope // We first check that the impl block is open by default. assert-attribute: ("#implementations-list details", {"open": ""}) // To ensure that we will click on the currently hidden method. -assert-text: (".sidebar-elems section .block li > a", "must_use") -click: ".sidebar-elems section .block li > a" +assert-text: (".sidebar-elems section ul:nth-of-type(2) li > a", "must_use") +click: ".sidebar-elems ul:nth-of-type(2) li > a" // We check that the impl block was opened as expected so that we can see the method. assert-attribute: ("#implementations-list > details", {"open": ""}) diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index 3183650b555a8..61c1555fbc0e3 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -48,7 +48,7 @@ assert-property: ("rustdoc-topbar", {"clientHeight": "45"}) // Check that clicking an element from the sidebar scrolls to the right place // so the target is not obscured by the topbar. click: ".sidebar-menu-toggle" -click: ".sidebar-elems section .block li > a" +click: ".sidebar-elems section ul:nth-of-type(2) li > a" assert-position: ("#method\.must_use", {"y": 45}) // Check that the bottom-most item on the sidebar menu can be scrolled fully into view. diff --git a/tests/rustdoc-html/sidebar/sidebar-items.rs b/tests/rustdoc-html/sidebar/sidebar-items.rs index 6e13457796e5e..bd0893dac3e36 100644 --- a/tests/rustdoc-html/sidebar/sidebar-items.rs +++ b/tests/rustdoc-html/sidebar/sidebar-items.rs @@ -42,6 +42,14 @@ pub struct Bar { waza: u32, } +//@ has foo/struct.Bar.html +//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#implementations"]' 'Associated Functions' +//@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#implementations"]' 'Methods' +impl Bar { + pub fn method(&self) {} + pub fn assoc_fn() {} +} + //@ has foo/enum.En.html //@ has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants' //@ has - '//*[@class="sidebar-elems"]//section//a' 'Foo' diff --git a/tests/rustdoc-html/typedef.rs b/tests/rustdoc-html/typedef.rs index 3fdc2788bcacf..4eae3c7258213 100644 --- a/tests/rustdoc-html/typedef.rs +++ b/tests/rustdoc-html/typedef.rs @@ -13,7 +13,7 @@ impl MyStruct { //@ has - '//*[@class="impl"]//h3[@class="code-header"]' 'impl MyTrait for MyAlias' //@ hasraw - 'Alias docstring' //@ has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias' -//@ has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods' +//@ has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Associated Functions' //@ has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations' /// Alias docstring pub type MyAlias = MyStruct; From 147d11099f47c4013cff1d8d67d5d8da722b7fe9 Mon Sep 17 00:00:00 2001 From: Aryan Dubey Date: Tue, 31 Mar 2026 15:36:37 -0400 Subject: [PATCH 17/61] fixing tidy issues --- tests/ui/enum/enum_u8_variant.rs | 3 ++- tests/ui/layout/opt-repr-i32-min.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ui/enum/enum_u8_variant.rs b/tests/ui/enum/enum_u8_variant.rs index 67ea59085a946..f61d42cd2bf01 100644 --- a/tests/ui/enum/enum_u8_variant.rs +++ b/tests/ui/enum/enum_u8_variant.rs @@ -1,5 +1,6 @@ //@ run-pass -//Test that checks pattern matching works correctly on a repr(u8) enum whose only variant contains an inner 'u8' field +//Test that checks pattern matching works correctly on a repr(u8) enum +// whose only variant contains an inner 'u8' field //https://github.com/rust-lang/rust/issues/34571 #[repr(u8)] enum Foo { diff --git a/tests/ui/layout/opt-repr-i32-min.rs b/tests/ui/layout/opt-repr-i32-min.rs index 4c5831ff04904..10e54c633ae03 100644 --- a/tests/ui/layout/opt-repr-i32-min.rs +++ b/tests/ui/layout/opt-repr-i32-min.rs @@ -1,5 +1,6 @@ //@ run-pass -// Tests that Option niche optimisation does not incorrectly use i32::MIN as the None niche when a repr(i32) enum variant already holds that value. +// Tests that Option niche optimisation does not incorrectly use i32::MIN +// as the None niche when a repr(i32) enum variant already holds that value. // github.com/rust-lang/rust/issues/49973 #[derive(Debug)] #[repr(i32)] From 8277043ea3a47a0279ed166b3d8d95a32a2baece Mon Sep 17 00:00:00 2001 From: mu001999 Date: Wed, 1 Apr 2026 10:48:35 +0800 Subject: [PATCH 18/61] Avoid creating async return opaques for foreign async fns --- compiler/rustc_resolve/src/def_collector.rs | 7 +++++-- .../bad-external-async-fn-issue-146754.rs | 8 +++++++ .../bad-external-async-fn-issue-146754.stderr | 21 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ui/extern/bad-external-async-fn-issue-146754.rs create mode 100644 tests/ui/extern/bad-external-async-fn-issue-146754.stderr diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index de36f01b6d0e5..0acc42a6efbe1 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -209,12 +209,15 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_fn(&mut self, fn_kind: FnKind<'a>, _: &AttrVec, span: Span, _: NodeId) { match fn_kind { FnKind::Fn( - _ctxt, + ctxt, _vis, Fn { sig: FnSig { header, decl, span: _ }, ident, generics, contract, body, .. }, - ) if let Some(coroutine_kind) = header.coroutine_kind => { + ) if let Some(coroutine_kind) = header.coroutine_kind + // Foreign ones are denied, so don't create them here. + && ctxt != visit::FnCtxt::Foreign => + { self.visit_ident(ident); self.visit_fn_header(header); self.visit_generics(generics); diff --git a/tests/ui/extern/bad-external-async-fn-issue-146754.rs b/tests/ui/extern/bad-external-async-fn-issue-146754.rs new file mode 100644 index 0000000000000..394341c129654 --- /dev/null +++ b/tests/ui/extern/bad-external-async-fn-issue-146754.rs @@ -0,0 +1,8 @@ +//@ edition:2024 +#![crate_type = "lib"] + +unsafe extern "C" { + async fn function() -> [(); || {}]; + //~^ ERROR functions in `extern` blocks cannot have `async` qualifier + //~^^ ERROR mismatched types +} diff --git a/tests/ui/extern/bad-external-async-fn-issue-146754.stderr b/tests/ui/extern/bad-external-async-fn-issue-146754.stderr new file mode 100644 index 0000000000000..2a04b23630430 --- /dev/null +++ b/tests/ui/extern/bad-external-async-fn-issue-146754.stderr @@ -0,0 +1,21 @@ +error: functions in `extern` blocks cannot have `async` qualifier + --> $DIR/bad-external-async-fn-issue-146754.rs:5:5 + | +LL | unsafe extern "C" { + | ----------------- in this `extern` block +LL | async fn function() -> [(); || {}]; + | ^^^^^ help: remove the `async` qualifier + +error[E0308]: mismatched types + --> $DIR/bad-external-async-fn-issue-146754.rs:5:33 + | +LL | async fn function() -> [(); || {}]; + | ^^^^^ expected `usize`, found closure + | + = note: expected type `usize` + found closure `{closure@$DIR/bad-external-async-fn-issue-146754.rs:5:33: 5:35}` + = note: array length can only be `usize` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 910677fcc625fcff770158b4184ff64e4b57320c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Apr 2026 16:38:30 +1100 Subject: [PATCH 19/61] Rename `HirCtx` as `Hcx`. PR #154634 recently renamed many type parameters that impl `HashStableContext` as `Hcx`. It missed a few that are named `HirCtx`. This commit renames them. --- compiler/rustc_hir/src/stable_hash_impls.rs | 36 ++++++++++----------- compiler/rustc_middle/src/hir/mod.rs | 4 +-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 58649a694880b..d2d6529619662 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -13,48 +13,48 @@ use crate::lints::DelayedLints; /// instead of implementing everything in `rustc_middle`. pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {} -impl ToStableHashKey for BodyId { +impl ToStableHashKey for BodyId { type KeyType = (DefPathHash, ItemLocalId); #[inline] - fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + fn to_stable_hash_key(&self, hcx: &Hcx) -> (DefPathHash, ItemLocalId) { let BodyId { hir_id } = *self; hir_id.to_stable_hash_key(hcx) } } -impl ToStableHashKey for ItemId { +impl ToStableHashKey for ItemId { type KeyType = DefPathHash; #[inline] - fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { + fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash { self.owner_id.def_id.to_stable_hash_key(hcx) } } -impl ToStableHashKey for TraitItemId { +impl ToStableHashKey for TraitItemId { type KeyType = DefPathHash; #[inline] - fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { + fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash { self.owner_id.def_id.to_stable_hash_key(hcx) } } -impl ToStableHashKey for ImplItemId { +impl ToStableHashKey for ImplItemId { type KeyType = DefPathHash; #[inline] - fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { + fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash { self.owner_id.def_id.to_stable_hash_key(hcx) } } -impl ToStableHashKey for ForeignItemId { +impl ToStableHashKey for ForeignItemId { type KeyType = DefPathHash; #[inline] - fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash { + fn to_stable_hash_key(&self, hcx: &Hcx) -> DefPathHash { self.owner_id.def_id.to_stable_hash_key(hcx) } } @@ -66,8 +66,8 @@ impl ToStableHashKey for ForeignItemId // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". -impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { +impl<'tcx, Hcx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { + fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { // We ignore the `nodes` and `bodies` fields since these refer to information included in // `hash` which is hashed in the collector and used for the crate hash. // `local_id_to_def_id` is also ignored because is dependent on the body, then just hashing @@ -78,15 +78,15 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for OwnerNodes<' } } -impl HashStable for DelayedLints { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { +impl HashStable for DelayedLints { + fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { let DelayedLints { opt_hash, .. } = *self; opt_hash.unwrap().hash_stable(hcx, hasher); } } -impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { +impl<'tcx, Hcx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { + fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `opt_hash` which is // hashed in the collector and used for the crate hash. let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self; @@ -94,8 +94,8 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable for AttributeMap } } -impl HashStable for HashIgnoredAttrId { - fn hash_stable(&self, _hcx: &mut HirCtx, _hasher: &mut StableHasher) { +impl HashStable for HashIgnoredAttrId { + fn hash_stable(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) { /* we don't hash HashIgnoredAttrId, we ignore them */ } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index ad56e462d2934..dfce7e0917608 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -77,8 +77,8 @@ impl<'hir> Crate<'hir> { } } -impl HashStable for Crate<'_> { - fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { +impl HashStable for Crate<'_> { + fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { let Crate { opt_hir_hash, .. } = self; opt_hir_hash.unwrap().hash_stable(hcx, hasher) } From d9a8a553cd601d6c25f7557021a01ea0370738bb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Apr 2026 16:51:01 +1100 Subject: [PATCH 20/61] Reorder `use`/`mod` items in `rustc_session`. They're in multiple sections with no rhyme or reason. --- compiler/rustc_session/src/lib.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 1741dde90f5cf..29192f267ed3a 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -11,28 +11,24 @@ #![recursion_limit = "256"] // tidy-alphabetical-end -pub mod errors; - -pub mod utils; +pub use getopts; pub use lint::{declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass}; pub use rustc_lint_defs as lint; -pub mod parse; +pub use session::*; pub mod code_stats; +pub mod errors; +pub mod parse; +pub mod utils; #[macro_use] pub mod config; pub mod cstore; pub mod filesearch; mod macros; mod options; +pub mod output; pub mod search_paths; - mod session; -pub use session::*; - -pub mod output; - -pub use getopts; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro From 1a9a284ad253fb0fd1d52e880789dc6848599d93 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 1 Apr 2026 16:41:28 +1100 Subject: [PATCH 21/61] Simplify `HashStableContext`. `derive(HashStable_Generic)` generates impls like this: ``` impl<__CTX> HashStable<__CTX> for ExpnKind where __CTX: crate::HashStableContext { fn hash_stable(&self, hcx : &mut __CTX, __hasher: &mut StableHasher) { ... } } ``` This is used for crates that are upstream of `rustc_middle`. The `crate::HashStableContext` bound means every crate that uses `derive(HashStable_Generic)` must provide (or import) a trait `HashStableContext` which `rustc_middle` then impls. In `rustc_span` this trait is sensible, with three methods. In other crates, this trait is empty, and there is the following trait hierarchy: ``` rustc_session::HashStableContext | | | rustc_hir::HashStableContext | / \ rustc_ast::HashStableContext rustc_abi::HashStableContext | rustc_span::HashStableContext ``` All very strange and unnecessary. This commit changes `derive(HashStable_Generic)` to use `rustc_span::HashStableContext` instead of `crate::HashStableContext`. This eliminates the need for all the empty `HashStableContext` traits and impls. Much better. --- compiler/rustc_abi/src/lib.rs | 6 ------ compiler/rustc_ast/src/ast.rs | 5 +++-- compiler/rustc_ast/src/lib.rs | 5 ----- compiler/rustc_ast/src/tokenstream.rs | 4 ++-- compiler/rustc_hir/src/def.rs | 4 ++-- compiler/rustc_hir/src/lib.rs | 1 - compiler/rustc_hir/src/stable_hash_impls.rs | 24 +++++++++------------ compiler/rustc_hir_id/src/lib.rs | 4 ++-- compiler/rustc_lint_defs/src/lib.rs | 4 ++-- compiler/rustc_macros/src/hash_stable.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/ich/hcx.rs | 9 ++------ compiler/rustc_session/src/config.rs | 5 +++-- compiler/rustc_session/src/lib.rs | 5 ----- compiler/rustc_span/src/lib.rs | 8 +++---- compiler/rustc_target/src/lib.rs | 2 -- 16 files changed, 32 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 253dff6f8e75c..42e272fdafb5d 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -67,12 +67,6 @@ pub use layout::{FIRST_VARIANT, FieldIdx, LayoutCalculator, LayoutCalculatorErro #[cfg(feature = "nightly")] pub use layout::{Layout, TyAbiInterface, TyAndLayout}; -/// Requirements for a `StableHashingContext` to be used in this crate. -/// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in `rustc_middle`. -#[cfg(feature = "nightly")] -pub trait HashStableContext {} - #[derive(Clone, Copy, PartialEq, Eq, Default)] #[cfg_attr( feature = "nightly", diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 71ec1c5042fda..87633cade1b6a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -31,7 +31,8 @@ use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable}; pub use rustc_span::AttrId; use rustc_span::{ - ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Spanned, Symbol, kw, respan, sym, + ByteSymbol, DUMMY_SP, ErrorGuaranteed, HashStableContext, Ident, Span, Spanned, Symbol, kw, + respan, sym, }; use thin_vec::{ThinVec, thin_vec}; @@ -120,7 +121,7 @@ impl PartialEq<&[Symbol]> for Path { } } -impl HashStable for Path { +impl HashStable for Path { fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { self.segments.len().hash_stable(hcx, hasher); for segment in &self.segments { diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index ac3e77b0b5d6f..4178db1bfb09d 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -36,8 +36,3 @@ pub mod visit; pub use self::ast::*; pub use self::ast_traits::{AstNodeWrapper, HasAttrs, HasNodeId, HasTokens}; - -/// Requirements for a `StableHashingContext` to be used in this crate. -/// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_span::HashStableContext {} diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 8953391ac58bf..06bd6f03e9350 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -14,7 +14,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync; use rustc_macros::{Decodable, Encodable, HashStable_Generic, Walkable}; use rustc_serialize::{Decodable, Encodable}; -use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym}; +use rustc_span::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, Symbol, sym}; use thin_vec::ThinVec; use crate::ast::AttrStyle; @@ -826,7 +826,7 @@ impl FromIterator for TokenStream { impl HashStable for TokenStream where - Hcx: crate::HashStableContext, + Hcx: HashStableContext, { fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { for sub_tt in self.iter() { diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 78bd709dd4844..cae8bb89233b2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -8,9 +8,9 @@ use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_data_structures::unord::UnordMap; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; -use rustc_span::Symbol; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::hygiene::MacroKind; +use rustc_span::{HashStableContext, Symbol}; use crate::definitions::DefPathData; use crate::hir; @@ -712,7 +712,7 @@ impl IntoDiagArg for Namespace { } } -impl ToStableHashKey for Namespace { +impl ToStableHashKey for Namespace { type KeyType = Namespace; #[inline] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 9c2fec8677854..c2d9f879cd601 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -43,7 +43,6 @@ pub use hir::*; pub use lang_items::{LangItem, LanguageItems}; pub use rustc_ast::attr::version::*; pub use stability::*; -pub use stable_hash_impls::HashStableContext; pub use target::{MethodKind, Target}; arena_types!(rustc_arena::declare_arena); diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index d2d6529619662..a157fc0ccbb0c 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,4 +1,5 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_span::HashStableContext; use rustc_span::def_id::DefPathHash; use crate::HashIgnoredAttrId; @@ -8,12 +9,7 @@ use crate::hir::{ use crate::hir_id::ItemLocalId; use crate::lints::DelayedLints; -/// Requirements for a `StableHashingContext` to be used in this crate. -/// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStableContext {} - -impl ToStableHashKey for BodyId { +impl ToStableHashKey for BodyId { type KeyType = (DefPathHash, ItemLocalId); #[inline] @@ -23,7 +19,7 @@ impl ToStableHashKey for BodyId { } } -impl ToStableHashKey for ItemId { +impl ToStableHashKey for ItemId { type KeyType = DefPathHash; #[inline] @@ -32,7 +28,7 @@ impl ToStableHashKey for ItemId { } } -impl ToStableHashKey for TraitItemId { +impl ToStableHashKey for TraitItemId { type KeyType = DefPathHash; #[inline] @@ -41,7 +37,7 @@ impl ToStableHashKey for TraitItemId { } } -impl ToStableHashKey for ImplItemId { +impl ToStableHashKey for ImplItemId { type KeyType = DefPathHash; #[inline] @@ -50,7 +46,7 @@ impl ToStableHashKey for ImplItemId { } } -impl ToStableHashKey for ForeignItemId { +impl ToStableHashKey for ForeignItemId { type KeyType = DefPathHash; #[inline] @@ -66,7 +62,7 @@ impl ToStableHashKey for ForeignItemId { // want to pick up on a reference changing its target, so we hash the NodeIds // in "DefPath Mode". -impl<'tcx, Hcx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { +impl<'tcx, Hcx: HashStableContext> HashStable for OwnerNodes<'tcx> { fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { // We ignore the `nodes` and `bodies` fields since these refer to information included in // `hash` which is hashed in the collector and used for the crate hash. @@ -78,14 +74,14 @@ impl<'tcx, Hcx: crate::HashStableContext> HashStable for OwnerNodes<'tcx> { } } -impl HashStable for DelayedLints { +impl HashStable for DelayedLints { fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { let DelayedLints { opt_hash, .. } = *self; opt_hash.unwrap().hash_stable(hcx, hasher); } } -impl<'tcx, Hcx: crate::HashStableContext> HashStable for AttributeMap<'tcx> { +impl<'tcx, Hcx: HashStableContext> HashStable for AttributeMap<'tcx> { fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { // We ignore the `map` since it refers to information included in `opt_hash` which is // hashed in the collector and used for the crate hash. @@ -94,7 +90,7 @@ impl<'tcx, Hcx: crate::HashStableContext> HashStable for AttributeMap<'tcx> } } -impl HashStable for HashIgnoredAttrId { +impl HashStable for HashIgnoredAttrId { fn hash_stable(&self, _hcx: &mut Hcx, _hasher: &mut StableHasher) { /* we don't hash HashIgnoredAttrId, we ignore them */ } diff --git a/compiler/rustc_hir_id/src/lib.rs b/compiler/rustc_hir_id/src/lib.rs index ffff3f979f9e3..064ce4ed4cafe 100644 --- a/compiler/rustc_hir_id/src/lib.rs +++ b/compiler/rustc_hir_id/src/lib.rs @@ -8,7 +8,7 @@ use std::fmt::{self, Debug}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; -pub use rustc_span::HashStableContext; +use rustc_span::HashStableContext; use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] @@ -176,7 +176,7 @@ pub const CRATE_HIR_ID: HirId = pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID }; -impl ToStableHashKey for HirId { +impl ToStableHashKey for HirId { type KeyType = (DefPathHash, ItemLocalId); #[inline] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index af1d1854fa5a0..1c86d553f9b6a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -8,11 +8,11 @@ use rustc_data_structures::stable_hasher::{ HashStable, StableCompare, StableHasher, ToStableHashKey, }; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; -use rustc_hir_id::{HashStableContext, HirId, ItemLocalId}; +use rustc_hir_id::{HirId, ItemLocalId}; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::DefPathHash; pub use rustc_span::edition::Edition; -use rustc_span::{Ident, Span, Symbol, sym}; +use rustc_span::{HashStableContext, Ident, Span, Symbol, sym}; use serde::{Deserialize, Serialize}; pub use self::Level::*; diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index fa67adb406ed2..adb93e375c32c 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -84,7 +84,7 @@ fn hash_stable_derive_with_mode( match mode { HashStableMode::Normal => {} HashStableMode::Generic => { - s.add_where_predicate(parse_quote! { __CTX: crate::HashStableContext }); + s.add_where_predicate(parse_quote! { __CTX: ::rustc_span::HashStableContext }); } HashStableMode::NoContext => {} } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index dfce7e0917608..814b333cfb0f8 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -21,7 +21,7 @@ use rustc_hir::lints::DelayedLint; use rustc_hir::*; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable}; -use rustc_span::{ErrorGuaranteed, ExpnId, Span}; +use rustc_span::{ErrorGuaranteed, ExpnId, HashStableContext, Span}; use crate::query::Providers; use crate::ty::{ResolverAstLowering, TyCtxt}; diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs index 2e118dc3359fa..0e1cee2970f71 100644 --- a/compiler/rustc_middle/src/ich/hcx.rs +++ b/compiler/rustc_middle/src/ich/hcx.rs @@ -6,7 +6,7 @@ use rustc_hir::definitions::DefPathHash; use rustc_session::Session; use rustc_session::cstore::Untracked; use rustc_span::source_map::SourceMap; -use rustc_span::{CachingSourceMapView, DUMMY_SP, Pos, Span}; +use rustc_span::{CachingSourceMapView, DUMMY_SP, HashStableContext, Pos, Span}; // Very often, we are hashing something that does not need the `CachingSourceMapView`, so we // initialize it lazily. @@ -73,7 +73,7 @@ impl<'a> StableHashingContext<'a> { } } -impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { +impl<'a> HashStableContext for StableHashingContext<'a> { /// Hashes a span in a stable way. We can't directly hash the span's `BytePos` fields (that /// would be similar to hashing pointers, since those are just offsets into the `SourceMap`). /// Instead, we hash the (file name, line, column) triple, which stays the same even if the @@ -189,8 +189,3 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> { ); } } - -impl<'a> rustc_abi::HashStableContext for StableHashingContext<'a> {} -impl<'a> rustc_ast::HashStableContext for StableHashingContext<'a> {} -impl<'a> rustc_hir::HashStableContext for StableHashingContext<'a> {} -impl<'a> rustc_session::HashStableContext for StableHashingContext<'a> {} diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index e37247d7dd837..1e95482a8c7e6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -23,7 +23,8 @@ use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic}; use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; use rustc_span::source_map::FilePathMapping; use rustc_span::{ - FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym, + FileName, HashStableContext, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, + Symbol, sym, }; use rustc_target::spec::{ FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo, @@ -38,7 +39,7 @@ use crate::errors::FileWriteFail; pub use crate::options::*; use crate::search_paths::SearchPath; use crate::utils::CanonicalizedPath; -use crate::{EarlyDiagCtxt, HashStableContext, Session, filesearch, lint}; +use crate::{EarlyDiagCtxt, Session, filesearch, lint}; mod cfg; mod externs; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 29192f267ed3a..04e12f1afce68 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -29,8 +29,3 @@ mod options; pub mod output; pub mod search_paths; mod session; - -/// Requirements for a `StableHashingContext` to be used in this crate. -/// This is a hack to allow using the `HashStable_Generic` derive macro -/// instead of implementing everything in `rustc_middle`. -pub trait HashStableContext: rustc_ast::HashStableContext + rustc_hir::HashStableContext {} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 6794ffb311e32..97de708290fb4 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2796,10 +2796,10 @@ impl InnerSpan { } } -/// Requirements for a `StableHashingContext` to be used in this crate. -/// -/// This is a hack to allow using the [`HashStable_Generic`] derive macro -/// instead of implementing everything in rustc_middle. +/// This trait lets `HashStable` and `derive(HashStable_Generic)` be used in +/// this crate (and other crates upstream of `rustc_middle`), while leaving +/// certain operations to be defined in `rustc_middle` where more things are +/// visible. pub trait HashStableContext { /// The main event: stable hashing of a span. fn span_hash_stable(&mut self, span: Span, hasher: &mut StableHasher); diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 1dc62cb3659cc..d46802bf45d1a 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -24,8 +24,6 @@ pub mod target_features; #[cfg(test)] mod tests; -use rustc_abi::HashStableContext; - /// The name of rustc's own place to organize libraries. /// /// Used to be `rustc`, now the default is `rustlib`. From e18dd4a9925015045bbb54e0291d0bf060cdcf43 Mon Sep 17 00:00:00 2001 From: Makai Date: Mon, 16 Mar 2026 22:07:03 +0800 Subject: [PATCH 22/61] add `TypeFlags::HAS_NON_REGION_ERROR` and `TypeFlags::HAS_RE_ERROR` --- compiler/rustc_middle/src/ty/region.rs | 2 +- compiler/rustc_type_ir/src/flags.rs | 31 +++++++++++++++----------- compiler/rustc_type_ir/src/visit.rs | 19 ++++++++++++++++ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index a497501ef19d5..798b98c5def5c 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -291,7 +291,7 @@ impl<'tcx> Region<'tcx> { } ty::ReError(_) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_ERROR; + flags = flags | TypeFlags::HAS_RE_ERROR; } } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 6962a7ab1d727..f311298119649 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -91,19 +91,24 @@ bitflags::bitflags! { | TypeFlags::HAS_TY_INHERENT.bits() | TypeFlags::HAS_CT_PROJECTION.bits(); + /// Is a type or const error reachable? + const HAS_NON_REGION_ERROR = 1 << 15; + /// Is a region error reachable? + const HAS_RE_ERROR = 1 << 16; /// Is an error type/lifetime/const reachable? - const HAS_ERROR = 1 << 15; + const HAS_ERROR = TypeFlags::HAS_NON_REGION_ERROR.bits() + | TypeFlags::HAS_RE_ERROR.bits(); /// Does this have any region that "appears free" in the type? /// Basically anything but `ReBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 16; + const HAS_FREE_REGIONS = 1 << 17; /// Does this have any `ReBound` regions? - const HAS_RE_BOUND = 1 << 17; + const HAS_RE_BOUND = 1 << 18; /// Does this have any `Bound` types? - const HAS_TY_BOUND = 1 << 18; + const HAS_TY_BOUND = 1 << 19; /// Does this have any `ConstKind::Bound` consts? - const HAS_CT_BOUND = 1 << 19; + const HAS_CT_BOUND = 1 << 20; /// Does this have any bound variables? /// Used to check if a global bound is safe to evaluate. const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits() @@ -111,7 +116,7 @@ bitflags::bitflags! { | TypeFlags::HAS_CT_BOUND.bits(); /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 20; + const HAS_RE_ERASED = 1 << 21; /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? @@ -123,19 +128,19 @@ bitflags::bitflags! { | TypeFlags::HAS_CT_INFER.bits(); /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 21; + const HAS_TY_FRESH = 1 << 22; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 22; + const HAS_CT_FRESH = 1 << 23; /// Does this have any binders with bound vars (e.g. that need to be anonymized)? - const HAS_BINDER_VARS = 1 << 23; + const HAS_BINDER_VARS = 1 << 24; /// Does this type have any coroutines in it? - const HAS_TY_CORO = 1 << 24; + const HAS_TY_CORO = 1 << 25; /// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`? - const HAS_CANONICAL_BOUND = 1 << 25; + const HAS_CANONICAL_BOUND = 1 << 26; } } @@ -240,7 +245,7 @@ impl FlagComputation { | ty::Str | ty::Foreign(..) => {} - ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + ty::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR), ty::Param(_) => { self.add_flags(TypeFlags::HAS_TY_PARAM); @@ -489,7 +494,7 @@ impl FlagComputation { } } ty::ConstKind::Expr(e) => self.add_args(e.args().as_slice()), - ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), + ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_NON_REGION_ERROR), } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 1ee4bff6b7a11..cfb4588965368 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -279,6 +279,8 @@ pub trait TypeVisitableExt: TypeVisitable { fn error_reported(&self) -> Result<(), I::ErrorGuaranteed>; + fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed>; + fn has_non_region_param(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PARAM - TypeFlags::HAS_RE_PARAM) } @@ -352,6 +354,11 @@ pub trait TypeVisitableExt: TypeVisitable { fn still_further_specializable(&self) -> bool { self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } + + /// True if a type or const error is reachable + fn has_non_region_error(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR) + } } impl> TypeVisitableExt for T { @@ -376,6 +383,18 @@ impl> TypeVisitableExt for T { Ok(()) } } + + fn non_region_error_reported(&self) -> Result<(), I::ErrorGuaranteed> { + if self.has_non_region_error() { + if let ControlFlow::Break(guar) = self.visit_with(&mut HasErrorVisitor) { + Err(guar) + } else { + panic!("type flags said there was an non region error, but now there is not") + } + } else { + Ok(()) + } + } } #[derive(Debug, PartialEq, Eq, Copy, Clone)] From 339fb64d1c751de5d781f4c8d51ae37b613ba644 Mon Sep 17 00:00:00 2001 From: Makai Date: Mon, 16 Mar 2026 22:08:32 +0800 Subject: [PATCH 23/61] skip early return for region-only errors in projection types --- .../src/traits/project.rs | 4 +++- .../dropck-after-failed-type-lowering.rs | 3 ++- .../dropck-after-failed-type-lowering.stderr | 24 ++++++++++++++++--- .../unsized/thin-ptr-to-unsized-projection.rs | 6 +++++ .../thin-ptr-to-unsized-projection.stderr | 23 ++++++++++++++++++ 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 tests/ui/unsized/thin-ptr-to-unsized-projection.rs create mode 100644 tests/ui/unsized/thin-ptr-to-unsized-projection.stderr diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 3df5c9e33438a..72d3ba9629f4d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -659,7 +659,9 @@ fn project<'cx, 'tcx>( ))); } - if let Err(guar) = obligation.predicate.error_reported() { + // We can still compute a projection type when there are only region errors, + // but type/const errors require early return. + if let Err(guar) = obligation.predicate.non_region_error_reported() { return Ok(Projected::Progress(Progress::error_for_term( selcx.tcx(), obligation.predicate, diff --git a/tests/ui/dropck/dropck-after-failed-type-lowering.rs b/tests/ui/dropck/dropck-after-failed-type-lowering.rs index 2441e26fec96c..ee55e0dcaa491 100644 --- a/tests/ui/dropck/dropck-after-failed-type-lowering.rs +++ b/tests/ui/dropck/dropck-after-failed-type-lowering.rs @@ -3,11 +3,12 @@ trait B { type C<'a>; fn d() -> F { + //~^ ERROR: the trait bound `E: B` is not satisfied todo!() } } struct F { - h: Option<::C>, + h: Option<::C>, //~ ERROR: the trait bound `G: B` is not satisfied //~^ ERROR missing generics for associated type `B::C` } diff --git a/tests/ui/dropck/dropck-after-failed-type-lowering.stderr b/tests/ui/dropck/dropck-after-failed-type-lowering.stderr index 56ea72de0c5f2..0922d2e4340e8 100644 --- a/tests/ui/dropck/dropck-after-failed-type-lowering.stderr +++ b/tests/ui/dropck/dropck-after-failed-type-lowering.stderr @@ -1,5 +1,5 @@ error[E0107]: missing generics for associated type `B::C` - --> $DIR/dropck-after-failed-type-lowering.rs:10:25 + --> $DIR/dropck-after-failed-type-lowering.rs:11:25 | LL | h: Option<::C>, | ^ expected 1 lifetime argument @@ -14,6 +14,24 @@ help: add missing lifetime argument LL | h: Option<::C<'a>>, | ++++ -error: aborting due to 1 previous error +error[E0277]: the trait bound `G: B` is not satisfied + --> $DIR/dropck-after-failed-type-lowering.rs:11:8 + | +LL | h: Option<::C>, + | ^^^^^^^^^^^^^^^^^^^ the trait `B` is not implemented for `G` + | +help: consider restricting type parameter `G` with trait `B` + | +LL | struct F { + | +++ + +error[E0277]: the trait bound `E: B` is not satisfied + --> $DIR/dropck-after-failed-type-lowering.rs:5:18 + | +LL | fn d() -> F { + | ^^^^ the trait `B` is not implemented for `E` + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0277. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/unsized/thin-ptr-to-unsized-projection.rs b/tests/ui/unsized/thin-ptr-to-unsized-projection.rs new file mode 100644 index 0000000000000..79918e6a0722d --- /dev/null +++ b/tests/ui/unsized/thin-ptr-to-unsized-projection.rs @@ -0,0 +1,6 @@ +// This is a regression test for +struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice + //~^ ERROR: missing lifetime specifier [E0106] +const _: *const Foo = 0 as _; + //~^ ERROR: cannot cast `i32` to a pointer that is wide [E0606] +fn main() {} diff --git a/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr b/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr new file mode 100644 index 0000000000000..256523c4a47ec --- /dev/null +++ b/tests/ui/unsized/thin-ptr-to-unsized-projection.stderr @@ -0,0 +1,23 @@ +error[E0106]: missing lifetime specifier + --> $DIR/thin-ptr-to-unsized-projection.rs:2:17 + | +LL | struct Foo<'a>(<& /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice + | ^ expected named lifetime parameter + | +help: consider using the `'a` lifetime + | +LL | struct Foo<'a>(<&'a /*'a*/ [fn()] as core::ops::Deref>::Target); // adding the lifetime solves the ice + | ++ + +error[E0606]: cannot cast `i32` to a pointer that is wide + --> $DIR/thin-ptr-to-unsized-projection.rs:4:28 + | +LL | const _: *const Foo = 0 as _; + | - ^ creating a `*const Foo<'_>` requires both an address and a length + | | + | consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0106, E0606. +For more information about an error, try `rustc --explain E0106`. From fec09987324f37dda32c79f12d2d8c342805ae11 Mon Sep 17 00:00:00 2001 From: Nik Revenco Date: Thu, 26 Mar 2026 21:46:14 +0000 Subject: [PATCH 24/61] Export `derive` at `core::derive` and `std::derive` --- library/core/src/lib.rs | 2 ++ library/core/src/macros/mod.rs | 2 +- library/core/src/prelude/v1.rs | 6 +++++- library/std/src/lib.rs | 2 ++ library/std/src/prelude/v1.rs | 6 +++++- tests/ui/imports/global-derive-path.rs | 10 ++++++++++ 6 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/ui/imports/global-derive-path.rs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 35f93d8fb33b2..d10d86077bb8c 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -227,6 +227,8 @@ pub mod autodiff { #[unstable(feature = "contracts", issue = "128044")] pub mod contracts; +#[unstable(feature = "derive_macro_global_path", issue = "154645")] +pub use crate::macros::builtin::derive; #[stable(feature = "cfg_select", since = "1.95.0")] pub use crate::macros::cfg_select; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 7f35e94d3df30..33397e56b86c5 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1720,7 +1720,7 @@ pub(crate) mod builtin { /// /// See [the reference] for more info. /// - /// [the reference]: ../../../reference/attributes/derive.html + /// [the reference]: ../reference/attributes/derive.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] pub macro derive($item:item) { diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs index f2eb047d342bc..6122ab12ec351 100644 --- a/library/core/src/prelude/v1.rs +++ b/library/core/src/prelude/v1.rs @@ -120,9 +120,13 @@ pub use crate::trace_macros; // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use crate::macros::builtin::{ - alloc_error_handler, bench, derive, global_allocator, test, test_case, + alloc_error_handler, bench, global_allocator, test, test_case, }; +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use crate::macros::builtin::derive; + #[unstable(feature = "derive_const", issue = "118304")] pub use crate::macros::builtin::derive_const; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c8c8a6c897142..c6e5176dd1bbb 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -704,6 +704,8 @@ pub use core::cfg_select; reason = "`concat_bytes` is not stable enough for use and is subject to change" )] pub use core::concat_bytes; +#[unstable(feature = "derive_macro_global_path", issue = "154645")] +pub use core::derive; #[stable(feature = "matches_macro", since = "1.42.0")] #[allow(deprecated, deprecated_in_future)] pub use core::matches; diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs index ee57e031c959c..aeefec8b9e084 100644 --- a/library/std/src/prelude/v1.rs +++ b/library/std/src/prelude/v1.rs @@ -115,9 +115,13 @@ pub use core::prelude::v1::trace_macros; // (no public module for them to be re-exported from). #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] pub use core::prelude::v1::{ - alloc_error_handler, bench, derive, global_allocator, test, test_case, + alloc_error_handler, bench, global_allocator, test, test_case, }; +#[stable(feature = "builtin_macro_prelude", since = "1.38.0")] +#[doc(no_inline)] +pub use core::prelude::v1::derive; + #[unstable(feature = "derive_const", issue = "118304")] pub use core::prelude::v1::derive_const; diff --git a/tests/ui/imports/global-derive-path.rs b/tests/ui/imports/global-derive-path.rs new file mode 100644 index 0000000000000..5f0a6bb86bf30 --- /dev/null +++ b/tests/ui/imports/global-derive-path.rs @@ -0,0 +1,10 @@ +//@ edition: 2024 +//@ check-pass +#![crate_type = "lib"] +#![feature(derive_macro_global_path)] + +#[::core::derive(Clone)] +struct Y; + +#[::std::derive(Clone)] +struct X; From 12f8364d4d65f0641464b3afc8e12d705ddd2344 Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Wed, 1 Apr 2026 09:22:42 +0200 Subject: [PATCH 25/61] Introduce #[diagnostic::on_move] on `Arc` This annotates the `Arc` type with the diagnostic attribute `#[diagnostic::on_move]`. Now when a moved `Arc` is borrowed, a suggestion to clone it is made, with a label explaining why. --- library/alloc/src/lib.rs | 1 + library/alloc/src/sync.rs | 5 +++++ tests/ui/moves/arc-consumed-in-looped-closure.rs | 3 ++- tests/ui/moves/arc-consumed-in-looped-closure.stderr | 6 ++++-- tests/ui/moves/no-capture-arc.rs | 2 +- tests/ui/moves/no-capture-arc.stderr | 5 +++-- tests/ui/moves/no-reuse-move-arc.fixed | 2 +- tests/ui/moves/no-reuse-move-arc.rs | 2 +- tests/ui/moves/no-reuse-move-arc.stderr | 5 +++-- 9 files changed, 21 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index bcd9e092a310f..aff10c4320fe1 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -111,6 +111,7 @@ #![feature(core_intrinsics)] #![feature(deprecated_suggestion)] #![feature(deref_pure_trait)] +#![feature(diagnostic_on_move)] #![feature(dispatch_from_dyn)] #![feature(ergonomic_clones)] #![feature(error_generic_member_access)] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b3e49af868b8c..af1eaf2015e9d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -261,6 +261,11 @@ macro_rules! acquire { #[rustc_diagnostic_item = "Arc"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_insignificant_dtor] +#[diagnostic::on_move( + message = "the type `{Self}` does not implement `Copy`", + label = "this move could be avoided by cloning the original `{Self}`, which is inexpensive", + note = "consider using `Arc::clone`" +)] pub struct Arc< T: ?Sized, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.rs b/tests/ui/moves/arc-consumed-in-looped-closure.rs index 8700c78508476..6016850838d3c 100644 --- a/tests/ui/moves/arc-consumed-in-looped-closure.rs +++ b/tests/ui/moves/arc-consumed-in-looped-closure.rs @@ -19,7 +19,7 @@ impl ThreadPool { } fn main() { - let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE move occurs because + let results = Arc::new(Mutex::new(Vec::new())); //~ NOTE this move could be avoided by cloning the original `Arc`, which is inexpensive let pool = ThreadPool { workers: vec![], queue: Arc::new(()), @@ -29,6 +29,7 @@ fn main() { // let results = Arc::clone(&results); // Forgot this. pool.execute(move || { //~ ERROR E0382 //~^ NOTE value moved into closure here, in previous iteration of loop + //~| NOTE consider using `Arc::clone` //~| HELP consider cloning the value before moving it into the closure let mut r = results.lock().unwrap(); //~ NOTE use occurs due to use in closure r.push(i); diff --git a/tests/ui/moves/arc-consumed-in-looped-closure.stderr b/tests/ui/moves/arc-consumed-in-looped-closure.stderr index 47d6fd6cbad3b..462eb274ce5af 100644 --- a/tests/ui/moves/arc-consumed-in-looped-closure.stderr +++ b/tests/ui/moves/arc-consumed-in-looped-closure.stderr @@ -1,8 +1,8 @@ -error[E0382]: use of moved value: `results` +error[E0382]: the type `Arc` does not implement `Copy` --> $DIR/arc-consumed-in-looped-closure.rs:30:22 | LL | let results = Arc::new(Mutex::new(Vec::new())); - | ------- move occurs because `results` has type `Arc>>`, which does not implement the `Copy` trait + | ------- this move could be avoided by cloning the original `Arc`, which is inexpensive ... LL | for i in 0..20 { | -------------- inside of this loop @@ -13,12 +13,14 @@ LL | pool.execute(move || { LL | let mut r = results.lock().unwrap(); | ------- use occurs due to use in closure | + = note: consider using `Arc::clone` help: consider cloning the value before moving it into the closure | LL ~ let value = results.clone(); LL ~ pool.execute(move || { LL | LL | +LL | LL ~ let mut r = value.lock().unwrap(); | diff --git a/tests/ui/moves/no-capture-arc.rs b/tests/ui/moves/no-capture-arc.rs index 9c957a4e01b41..eea9858532d4c 100644 --- a/tests/ui/moves/no-capture-arc.rs +++ b/tests/ui/moves/no-capture-arc.rs @@ -9,7 +9,7 @@ fn main() { assert_eq!((*arc_v)[3], 4); }); - assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` + assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy` println!("{:?}", *arc_v); } diff --git a/tests/ui/moves/no-capture-arc.stderr b/tests/ui/moves/no-capture-arc.stderr index 6d4a867fa88d0..e0fce32ba7fc0 100644 --- a/tests/ui/moves/no-capture-arc.stderr +++ b/tests/ui/moves/no-capture-arc.stderr @@ -1,8 +1,8 @@ -error[E0382]: borrow of moved value: `arc_v` +error[E0382]: the type `Arc` does not implement `Copy` --> $DIR/no-capture-arc.rs:12:18 | LL | let arc_v = Arc::new(v); - | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait + | ----- this move could be avoided by cloning the original `Arc`, which is inexpensive LL | LL | thread::spawn(move|| { | ------ value moved into closure here @@ -12,6 +12,7 @@ LL | assert_eq!((*arc_v)[3], 4); LL | assert_eq!((*arc_v)[2], 3); | ^^^^^ value borrowed here after move | + = note: consider using `Arc::clone` = note: borrow occurs due to deref coercion to `Vec` help: consider cloning the value before moving it into the closure | diff --git a/tests/ui/moves/no-reuse-move-arc.fixed b/tests/ui/moves/no-reuse-move-arc.fixed index a5dac8cc14bf2..c9094cb78a391 100644 --- a/tests/ui/moves/no-reuse-move-arc.fixed +++ b/tests/ui/moves/no-reuse-move-arc.fixed @@ -11,7 +11,7 @@ fn main() { assert_eq!((*value)[3], 4); }); - assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` + assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy` println!("{:?}", *arc_v); } diff --git a/tests/ui/moves/no-reuse-move-arc.rs b/tests/ui/moves/no-reuse-move-arc.rs index 0d67aa56489ce..29452220aebcc 100644 --- a/tests/ui/moves/no-reuse-move-arc.rs +++ b/tests/ui/moves/no-reuse-move-arc.rs @@ -10,7 +10,7 @@ fn main() { assert_eq!((*arc_v)[3], 4); }); - assert_eq!((*arc_v)[2], 3); //~ ERROR borrow of moved value: `arc_v` + assert_eq!((*arc_v)[2], 3); //~ ERROR the type `Arc` does not implement `Copy` println!("{:?}", *arc_v); } diff --git a/tests/ui/moves/no-reuse-move-arc.stderr b/tests/ui/moves/no-reuse-move-arc.stderr index aff979af905e4..8f56b32f96a89 100644 --- a/tests/ui/moves/no-reuse-move-arc.stderr +++ b/tests/ui/moves/no-reuse-move-arc.stderr @@ -1,8 +1,8 @@ -error[E0382]: borrow of moved value: `arc_v` +error[E0382]: the type `Arc` does not implement `Copy` --> $DIR/no-reuse-move-arc.rs:13:18 | LL | let arc_v = Arc::new(v); - | ----- move occurs because `arc_v` has type `Arc>`, which does not implement the `Copy` trait + | ----- this move could be avoided by cloning the original `Arc`, which is inexpensive LL | LL | thread::spawn(move|| { | ------ value moved into closure here @@ -12,6 +12,7 @@ LL | assert_eq!((*arc_v)[3], 4); LL | assert_eq!((*arc_v)[2], 3); | ^^^^^ value borrowed here after move | + = note: consider using `Arc::clone` = note: borrow occurs due to deref coercion to `Vec` help: consider cloning the value before moving it into the closure | From 253c03aa9d1e810cc4226fce7ccb1431dd4108d0 Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Tue, 31 Mar 2026 17:57:34 +0100 Subject: [PATCH 26/61] Add a test for a past ICE when calling a const fn with the wrong number of arguments --- .../ice-extra-args-fn-abi-issue-127423.rs | 18 +++++++++ .../ice-extra-args-fn-abi-issue-127423.stderr | 39 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs create mode 100644 tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs new file mode 100644 index 0000000000000..4b87ae6080698 --- /dev/null +++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs @@ -0,0 +1,18 @@ +// #127423: ICE: assertion failed: sig.c_variadic || extra_args.is_empty() +// Calling a const fn with the wrong number of arguments where the function has +// an unresolved type should not trigger an ICE. +// issue: rust-lang/rust#127423 + +#![allow(dead_code)] + +const fn add(a: &'self isize) -> usize { + //~^ ERROR use of undeclared lifetime name `'self` + //~| ERROR lifetimes cannot use keyword names + Qux + y + //~^ ERROR cannot find value `Qux` in this scope + //~| ERROR cannot find value `y` in this scope +} + +const ARR: [i32; add(1, 2)] = [5, 6, 7]; + +pub fn main() {} diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr new file mode 100644 index 0000000000000..a5b2f5a578150 --- /dev/null +++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr @@ -0,0 +1,39 @@ +error: lifetimes cannot use keyword names + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:18 + | +LL | const fn add(a: &'self isize) -> usize { + | ^^^^^ + +error[E0261]: use of undeclared lifetime name `'self` + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:18 + | +LL | const fn add(a: &'self isize) -> usize { + | ^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'self` here + | +LL | const fn add<'self>(a: &'self isize) -> usize { + | +++++++ + +error[E0425]: cannot find value `Qux` in this scope + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:11:5 + | +LL | Qux + y + | ^^^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:11:11 + | +LL | Qux + y + | ^ + | +help: a local variable with a similar name exists + | +LL - Qux + y +LL + Qux + a + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0261, E0425. +For more information about an error, try `rustc --explain E0261`. From a7a7938d2e08d8ad78cd999d344ce9419cc65c52 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:31:35 +0200 Subject: [PATCH 27/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `inline::load_attrs` function --- src/librustdoc/clean/inline.rs | 7 ++++--- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 09b2bc5dcef1d..1b4bcc18ca9a8 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -218,10 +218,10 @@ pub(crate) fn try_inline_glob( } } -pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [hir::Attribute] { +pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [hir::Attribute] { // FIXME: all uses should use `find_attr`! #[allow(deprecated)] - cx.tcx.get_all_attrs(did) + tcx.get_all_attrs(did) } pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec { @@ -623,7 +623,8 @@ pub(crate) fn build_impl( // doesn't matter at this point. // // We need to pass this empty `CfgInfo` because `merge_attrs` is used when computing the `cfg`. - let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs, &mut CfgInfo::default()); + let (merged_attrs, cfg) = + merge_attrs(cx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default()); trace!("merged_attrs={merged_attrs:?}"); trace!( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f54339429fa58..e0fcd3184f36d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -184,7 +184,7 @@ fn generate_item_with_correct_attrs( import_ids: &[LocalDefId], renamed: Option, ) -> Item { - let target_attrs = inline::load_attrs(cx, def_id); + let target_attrs = inline::load_attrs(cx.tcx, def_id); let attrs = if !import_ids.is_empty() { let mut attrs = Vec::with_capacity(import_ids.len()); let mut is_inline = false; @@ -196,7 +196,7 @@ fn generate_item_with_correct_attrs( // cfgs on the path up until the glob can be removed, and only cfgs on the globbed item // itself matter), for non-inlined re-exports see #85043. let import_is_inline = find_attr!( - inline::load_attrs(cx, import_id.to_def_id()), + inline::load_attrs(cx.tcx, import_id.to_def_id()), Doc(d) if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) ) || (is_glob_import(cx.tcx, import_id) @@ -2663,7 +2663,7 @@ fn get_all_import_attributes<'hir>( .iter() .flat_map(|reexport| reexport.id()) { - let import_attrs = inline::load_attrs(cx, def_id); + let import_attrs = inline::load_attrs(cx.tcx, def_id); if first { // This is the "original" reexport so we get all its attributes without filtering them. attrs = import_attrs.iter().map(|attr| (Cow::Borrowed(attr), Some(def_id))).collect(); diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index f73db253af062..3b4a2c752ca01 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -64,7 +64,7 @@ impl CfgPropagator<'_, '_> { && let Some(mut next_def_id) = item.item_id.as_local_def_id() { while let Some(parent_def_id) = self.cx.tcx.opt_local_parent(next_def_id) { - let x = load_attrs(self.cx, parent_def_id.to_def_id()); + let x = load_attrs(self.cx.tcx, parent_def_id.to_def_id()); add_only_cfg_attributes(&mut attrs, x); next_def_id = parent_def_id; } From 65fbfa4e814cf9097856f10f4c2821b0298a970b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:34:55 +0200 Subject: [PATCH 28/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `inline::merge_attrs` function --- src/librustdoc/clean/inline.rs | 11 ++++------- src/librustdoc/passes/propagate_doc_cfg.rs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1b4bcc18ca9a8..5b9f8a14506ee 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -416,7 +416,7 @@ pub(crate) fn build_impls( } pub(crate) fn merge_attrs( - cx: &mut DocContext<'_>, + tcx: TyCtxt<'_>, old_attrs: &[hir::Attribute], new_attrs: Option<(&[hir::Attribute], Option)>, cfg_info: &mut CfgInfo, @@ -434,13 +434,10 @@ pub(crate) fn merge_attrs( } else { Attributes::from_hir(&both) }, - extract_cfg_from_attrs(both.iter(), cx.tcx, cfg_info), + extract_cfg_from_attrs(both.iter(), tcx, cfg_info), ) } else { - ( - Attributes::from_hir(old_attrs), - extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, cfg_info), - ) + (Attributes::from_hir(old_attrs), extract_cfg_from_attrs(old_attrs.iter(), tcx, cfg_info)) } } @@ -624,7 +621,7 @@ pub(crate) fn build_impl( // // We need to pass this empty `CfgInfo` because `merge_attrs` is used when computing the `cfg`. let (merged_attrs, cfg) = - merge_attrs(cx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default()); + merge_attrs(cx.tcx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default()); trace!("merged_attrs={merged_attrs:?}"); trace!( diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 3b4a2c752ca01..92798bb9bb011 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -71,7 +71,7 @@ impl CfgPropagator<'_, '_> { } let (_, cfg) = merge_attrs( - self.cx, + self.cx.tcx, item.attrs.other_attrs.as_slice(), Some((&attrs, None)), &mut self.cfg_info, From 9f95c3830d8a12874dd398a9efc62ab34d6bf907 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:39:42 +0200 Subject: [PATCH 29/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `utils::display_macro_source` function --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/utils.rs | 15 +++++---------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 5b9f8a14506ee..58951fee8b7a6 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -779,7 +779,7 @@ fn build_macro( // kinds LoadedMacro::MacroDef { def, .. } => match macro_kinds { MacroKinds::BANG => clean::MacroItem(clean::Macro { - source: utils::display_macro_source(cx, name, &def), + source: utils::display_macro_source(cx.tcx, name, &def), macro_rules: def.macro_rules, }), MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e0fcd3184f36d..1e109e03afcc4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2861,7 +2861,7 @@ fn clean_maybe_renamed_item<'tcx>( // FIXME: handle attributes and derives that aren't proc macros, and macros with // multiple kinds ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro { - source: display_macro_source(cx, name, macro_def), + source: display_macro_source(cx.tcx, name, macro_def), macro_rules: macro_def.macro_rules, }), ItemKind::Macro(_, _, MacroKinds::ATTR) => { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 834b73997c959..992d78332b933 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -602,26 +602,21 @@ fn render_macro_arms<'a>( out } -pub(super) fn display_macro_source( - cx: &mut DocContext<'_>, - name: Symbol, - def: &ast::MacroDef, -) -> String { +pub(super) fn display_macro_source(tcx: TyCtxt<'_>, name: Symbol, def: &ast::MacroDef) -> String { // Extract the spans of all matchers. They represent the "interface" of the macro. let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]); if def.macro_rules { - format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ";")) + format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(tcx, matchers, ";")) } else { if matchers.len() <= 1 { format!( "macro {name}{matchers} {{\n ...\n}}", - matchers = matchers - .map(|matcher| render_macro_matcher(cx.tcx, matcher)) - .collect::(), + matchers = + matchers.map(|matcher| render_macro_matcher(tcx, matcher)).collect::(), ) } else { - format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ",")) + format!("macro {name} {{\n{arms}}}", arms = render_macro_arms(tcx, matchers, ",")) } } } From f3ba2c41e63ac58ae8aafbe7725db6b5e6021d00 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:41:59 +0200 Subject: [PATCH 30/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `inline::build_macro` function --- src/librustdoc/clean/inline.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 58951fee8b7a6..a8fb32b550856 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -137,7 +137,7 @@ pub(crate) fn try_inline( }) } Res::Def(DefKind::Macro(kinds), did) => { - let mac = build_macro(cx, did, name, kinds); + let mac = build_macro(cx.tcx, did, name, kinds); // FIXME: handle attributes and derives that aren't proc macros, and macros with // multiple kinds @@ -769,17 +769,17 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St } fn build_macro( - cx: &mut DocContext<'_>, + tcx: TyCtxt<'_>, def_id: DefId, name: Symbol, macro_kinds: MacroKinds, ) -> clean::ItemKind { - match CStore::from_tcx(cx.tcx).load_macro_untracked(cx.tcx, def_id) { + match CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id) { // FIXME: handle attributes and derives that aren't proc macros, and macros with multiple // kinds LoadedMacro::MacroDef { def, .. } => match macro_kinds { MacroKinds::BANG => clean::MacroItem(clean::Macro { - source: utils::display_macro_source(cx.tcx, name, &def), + source: utils::display_macro_source(tcx, name, &def), macro_rules: def.macro_rules, }), MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro { From 58077cc37ab38a4e7a8c3ad5d378e3bf83def129 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:49:22 +0200 Subject: [PATCH 31/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `clean::clean_middle_region` function --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 14 +++++++------- src/librustdoc/clean/utils.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index a8fb32b550856..566159ecfa040 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -388,8 +388,8 @@ pub(crate) fn build_impls( attrs: Option<(&[hir::Attribute], Option)>, ret: &mut Vec, ) { - let _prof_timer = cx.tcx.sess.prof.generic_activity("build_inherent_impls"); let tcx = cx.tcx; + let _prof_timer = tcx.sess.prof.generic_activity("build_inherent_impls"); // for each implementation of an item represented by `did`, build the clean::Item for that impl for &did in tcx.inherent_impls(did).iter() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e109e03afcc4..86db3521babaf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -350,9 +350,9 @@ pub(crate) fn clean_middle_const<'tcx>( pub(crate) fn clean_middle_region<'tcx>( region: ty::Region<'tcx>, - cx: &mut DocContext<'tcx>, + tcx: TyCtxt<'tcx>, ) -> Option { - region.get_name(cx.tcx).map(Lifetime) + region.get_name(tcx).map(Lifetime) } fn clean_where_predicate<'tcx>( @@ -436,9 +436,9 @@ fn clean_region_outlives_predicate<'tcx>( let ty::OutlivesPredicate(a, b) = pred; WherePredicate::RegionPredicate { - lifetime: clean_middle_region(a, cx).expect("failed to clean lifetime"), + lifetime: clean_middle_region(a, cx.tcx).expect("failed to clean lifetime"), bounds: vec![GenericBound::Outlives( - clean_middle_region(b, cx).expect("failed to clean bounds"), + clean_middle_region(b, cx.tcx).expect("failed to clean bounds"), )], } } @@ -452,7 +452,7 @@ fn clean_type_outlives_predicate<'tcx>( WherePredicate::BoundPredicate { ty: clean_middle_ty(pred.rebind(ty), cx, None, None), bounds: vec![GenericBound::Outlives( - clean_middle_region(lt, cx).expect("failed to clean lifetimes"), + clean_middle_region(lt, cx.tcx).expect("failed to clean lifetimes"), )], bound_params: Vec::new(), } @@ -2067,7 +2067,7 @@ pub(crate) fn clean_middle_ty<'tcx>( RawPointer(mutbl, Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None))) } ty::Ref(r, ty, mutbl) => BorrowedRef { - lifetime: clean_middle_region(r, cx), + lifetime: clean_middle_region(r, cx.tcx), mutability: mutbl, type_: Box::new(clean_middle_ty( bound_ty.rebind(ty), @@ -2301,7 +2301,7 @@ fn clean_middle_opaque_bounds<'tcx>( let trait_ref = match bound_predicate.skip_binder() { ty::ClauseKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref), ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => { - return clean_middle_region(reg, cx).map(GenericBound::Outlives); + return clean_middle_region(reg, cx.tcx).map(GenericBound::Outlives); } _ => return None, }; diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 992d78332b933..c0cb2f501c348 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -135,7 +135,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( match arg.skip_binder().kind() { GenericArgKind::Lifetime(lt) => Some(GenericArg::Lifetime( - clean_middle_region(lt, cx).unwrap_or(Lifetime::elided()), + clean_middle_region(lt, cx.tcx).unwrap_or(Lifetime::elided()), )), GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty( arg.rebind(ty), From 5a48d5e8cfa37049bec7c2205a20061b34571a56 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:51:55 +0200 Subject: [PATCH 32/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `clean::clean_region_outlives_predicate` function --- src/librustdoc/clean/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 86db3521babaf..f3d657be00543 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -394,7 +394,7 @@ pub(crate) fn clean_predicate<'tcx>( let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { ty::ClauseKind::Trait(pred) => clean_poly_trait_predicate(bound_predicate.rebind(pred), cx), - ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx)), + ty::ClauseKind::RegionOutlives(pred) => Some(clean_region_outlives_predicate(pred, cx.tcx)), ty::ClauseKind::TypeOutlives(pred) => { Some(clean_type_outlives_predicate(bound_predicate.rebind(pred), cx)) } @@ -431,14 +431,14 @@ fn clean_poly_trait_predicate<'tcx>( fn clean_region_outlives_predicate<'tcx>( pred: ty::RegionOutlivesPredicate<'tcx>, - cx: &mut DocContext<'tcx>, + tcx: TyCtxt<'tcx>, ) -> WherePredicate { let ty::OutlivesPredicate(a, b) = pred; WherePredicate::RegionPredicate { - lifetime: clean_middle_region(a, cx.tcx).expect("failed to clean lifetime"), + lifetime: clean_middle_region(a, tcx).expect("failed to clean lifetime"), bounds: vec![GenericBound::Outlives( - clean_middle_region(b, cx.tcx).expect("failed to clean bounds"), + clean_middle_region(b, tcx).expect("failed to clean bounds"), )], } } From d77a2ea613bebf410a3920ccd0681b3c102f8b6a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 14:58:05 +0200 Subject: [PATCH 33/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `clean::clean_proc_macro` function --- src/librustdoc/clean/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f3d657be00543..96fc753bff661 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1001,12 +1001,12 @@ fn clean_proc_macro<'tcx>( item: &hir::Item<'tcx>, name: &mut Symbol, kind: MacroKind, - cx: &mut DocContext<'tcx>, + tcx: TyCtxt<'tcx>, ) -> ItemKind { if kind != MacroKind::Derive { return ProcMacroItem(ProcMacro { kind, helpers: vec![] }); } - let attrs = cx.tcx.hir_attrs(item.hir_id()); + let attrs = tcx.hir_attrs(item.hir_id()); let Some((trait_name, helper_attrs)) = find_attr!(attrs, ProcMacroDerive { trait_name, helper_attrs, ..} => (*trait_name, helper_attrs)) else { return ProcMacroItem(ProcMacro { kind, helpers: vec![] }); @@ -1037,7 +1037,7 @@ fn clean_fn_or_proc_macro<'tcx>( }; match macro_kind { - Some(kind) => clean_proc_macro(item, name, kind, cx), + Some(kind) => clean_proc_macro(item, name, kind, cx.tcx), None => { let mut func = clean_function(cx, sig, generics, ParamsSrc::Body(body_id)); clean_fn_decl_legacy_const_generics(&mut func, attrs); @@ -2865,10 +2865,10 @@ fn clean_maybe_renamed_item<'tcx>( macro_rules: macro_def.macro_rules, }), ItemKind::Macro(_, _, MacroKinds::ATTR) => { - clean_proc_macro(item, &mut name, MacroKind::Attr, cx) + clean_proc_macro(item, &mut name, MacroKind::Attr, cx.tcx) } ItemKind::Macro(_, _, MacroKinds::DERIVE) => { - clean_proc_macro(item, &mut name, MacroKind::Derive, cx) + clean_proc_macro(item, &mut name, MacroKind::Derive, cx.tcx) } ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"), // proc macros can have a name set by attributes From 3520351527bb60ad91d038b9f51adacd29baa8ac Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:04:34 +0200 Subject: [PATCH 34/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `Type::from_def_id_and_parts` function --- src/librustdoc/clean/mod.rs | 24 ++++++++++++------------ src/librustdoc/clean/types.rs | 4 ++-- src/librustdoc/clean/utils.rs | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 96fc753bff661..9910cd2bd0201 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1248,7 +1248,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext RequiredAssocTypeItem(generics, bounds) } }; - Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx) + Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx.tcx) }) } @@ -1289,7 +1289,7 @@ pub(crate) fn clean_impl_item<'tcx>( } }; - Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx) + Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx.tcx) }) } @@ -1517,7 +1517,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } }; - Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx) + Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx.tcx) } fn first_non_private_clean_path<'tcx>( @@ -2399,7 +2399,7 @@ pub(crate) fn clean_field_with_def_id( ty: Type, cx: &mut DocContext<'_>, ) -> Item { - Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx) + Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx.tcx) } pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item { @@ -2422,7 +2422,7 @@ pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_ variant.def_id, Some(variant.name), VariantItem(Variant { kind, discriminant }), - cx, + cx.tcx, ) } @@ -2499,7 +2499,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>( variant.def_id, Some(variant.name), VariantItem(Variant { kind, discriminant }), - cx, + cx.tcx, ) } @@ -2907,7 +2907,7 @@ fn clean_maybe_renamed_item<'tcx>( fn clean_variant<'tcx>(variant: &hir::Variant<'tcx>, cx: &mut DocContext<'tcx>) -> Item { let kind = VariantItem(clean_variant_data(&variant.data, &variant.disr_expr, cx)); - Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx) + Item::from_def_id_and_parts(variant.def_id.to_def_id(), Some(variant.ident.name), kind, cx.tcx) } fn clean_impl<'tcx>( @@ -2928,7 +2928,7 @@ fn clean_impl<'tcx>( def_id.to_def_id(), None, PlaceholderImplItem, - cx, + tcx, )]; } Some(clean_trait_ref(&t.trait_ref, cx)) @@ -2983,7 +2983,7 @@ fn clean_impl<'tcx>( }, is_deprecated, })); - Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx) + Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, tcx) }; if let Some(type_alias) = type_alias { ret.push(make_item(trait_.clone(), type_alias, items.clone())); @@ -3031,7 +3031,7 @@ fn clean_extern_crate<'tcx>( krate_owner_def_id.to_def_id(), Some(name), ExternCrateItem { src: orig_name }, - cx, + cx.tcx, )] } @@ -3160,14 +3160,14 @@ fn clean_use_statement_inner<'tcx>( import_def_id.to_def_id(), None, ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)), - cx, + cx.tcx, )); return items; } Import::new_simple(name, resolve_use_source(cx, path), true) }; - vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx)] + vec![Item::from_def_id_and_parts(import_def_id.to_def_id(), None, ImportItem(inner), cx.tcx)] } fn clean_maybe_renamed_foreign_item<'tcx>( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ad70fc1096691..e49efec9d2c40 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -514,10 +514,10 @@ impl Item { def_id: DefId, name: Option, kind: ItemKind, - cx: &mut DocContext<'_>, + tcx: TyCtxt<'_>, ) -> Item { #[allow(deprecated)] - let hir_attrs = cx.tcx.get_all_attrs(def_id); + let hir_attrs = tcx.get_all_attrs(def_id); Self::from_def_id_and_attrs_and_parts( def_id, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index c0cb2f501c348..2f859d2c3b4e8 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -72,14 +72,14 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { def_id, Some(prim.as_sym()), ItemKind::PrimitiveItem(prim), - cx, + cx.tcx, ) })); m.items.extend(keywords.map(|(def_id, kw)| { - Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx) + Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::KeywordItem, cx.tcx) })); m.items.extend(documented_attributes.into_iter().map(|(def_id, kw)| { - Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx) + Item::from_def_id_and_parts(def_id, Some(kw), ItemKind::AttributeItem, cx.tcx) })); } From 509a444d39edc5875f537e6e996646566a374556 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:11:13 +0200 Subject: [PATCH 35/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `clean::clean_field_with_def_id` function --- src/librustdoc/clean/mod.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9910cd2bd0201..8b0c9fad9f688 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2376,7 +2376,12 @@ fn clean_middle_opaque_bounds<'tcx>( } pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item { - clean_field_with_def_id(field.def_id.to_def_id(), field.ident.name, clean_ty(field.ty, cx), cx) + clean_field_with_def_id( + field.def_id.to_def_id(), + field.ident.name, + clean_ty(field.ty, cx), + cx.tcx, + ) } pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) -> Item { @@ -2389,7 +2394,7 @@ pub(crate) fn clean_middle_field(field: &ty::FieldDef, cx: &mut DocContext<'_>) Some(field.did), None, ), - cx, + cx.tcx, ) } @@ -2397,9 +2402,9 @@ pub(crate) fn clean_field_with_def_id( def_id: DefId, name: Symbol, ty: Type, - cx: &mut DocContext<'_>, + tcx: TyCtxt<'_>, ) -> Item { - Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), cx.tcx) + Item::from_def_id_and_parts(def_id, Some(name), StructFieldItem(ty), tcx) } pub(crate) fn clean_variant_def(variant: &ty::VariantDef, cx: &mut DocContext<'_>) -> Item { @@ -2463,7 +2468,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>( field.did, field.name, clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None), - cx, + cx.tcx, ) }) .collect(), @@ -2488,7 +2493,7 @@ pub(crate) fn clean_variant_def_with_args<'tcx>( field.did, field.name, clean_middle_ty(ty::Binder::dummy(ty), cx, Some(field.did), None), - cx, + cx.tcx, ) }) .collect(), From 822579e6e4f6c71f5feb5b5635c82803aa55a55e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:22:31 +0200 Subject: [PATCH 36/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `types::GenericBound` methods --- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/mod.rs | 8 ++++---- src/librustdoc/clean/simplify.rs | 4 ++-- src/librustdoc/clean/types.rs | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 566159ecfa040..53655cbe5c200 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -289,7 +289,7 @@ pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait { supertrait_bounds.retain(|b| { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. - !b.is_meta_sized_bound(cx) + !b.is_meta_sized_bound(cx.tcx) }); clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds } @@ -302,7 +302,7 @@ fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias { bounds.retain(|b| { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. - !b.is_meta_sized_bound(cx) + !b.is_meta_sized_bound(cx.tcx) }); clean::TraitAlias { generics, bounds } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8b0c9fad9f688..33da99f65407c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -898,10 +898,10 @@ fn clean_ty_generics_inner<'tcx>( for (idx, mut bounds) in impl_trait { let mut has_sized = false; bounds.retain(|b| { - if b.is_sized_bound(cx) { + if b.is_sized_bound(cx.tcx) { has_sized = true; false - } else if b.is_meta_sized_bound(cx) { + } else if b.is_meta_sized_bound(cx.tcx) { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. false @@ -1459,7 +1459,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo bounds.retain(|b| { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. - !b.is_meta_sized_bound(cx) + !b.is_meta_sized_bound(cx.tcx) }); // Our Sized/?Sized bound didn't get handled when creating the generics @@ -1467,7 +1467,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo // (some of them may have come from the trait). If we do have a sized // bound, we remove it, and if we don't then we add the `?Sized` bound // at the end. - match bounds.iter().position(|b| b.is_sized_bound(cx)) { + match bounds.iter().position(|b| b.is_sized_bound(cx.tcx)) { Some(i) => { bounds.remove(i); } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 6fb878ea54856..c0ee741503ad9 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -139,10 +139,10 @@ pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generi return true; }; - if bounds.iter().any(|b| b.is_sized_bound(cx)) { + if bounds.iter().any(|b| b.is_sized_bound(cx.tcx)) { sized_params.insert(*param); false - } else if bounds.iter().any(|b| b.is_meta_sized_bound(cx)) { + } else if bounds.iter().any(|b| b.is_meta_sized_bound(cx.tcx)) { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. false diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index e49efec9d2c40..cd5a3346b26d0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1119,20 +1119,20 @@ impl GenericBound { matches!(self, Self::TraitBound(..)) } - pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { - self.is_bounded_by_lang_item(cx, LangItem::Sized) + pub(crate) fn is_sized_bound(&self, tcx: TyCtxt<'_>) -> bool { + self.is_bounded_by_lang_item(tcx, LangItem::Sized) } - pub(crate) fn is_meta_sized_bound(&self, cx: &DocContext<'_>) -> bool { - self.is_bounded_by_lang_item(cx, LangItem::MetaSized) + pub(crate) fn is_meta_sized_bound(&self, tcx: TyCtxt<'_>) -> bool { + self.is_bounded_by_lang_item(tcx, LangItem::MetaSized) } - fn is_bounded_by_lang_item(&self, cx: &DocContext<'_>, lang_item: LangItem) -> bool { + fn is_bounded_by_lang_item(&self, tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { if let GenericBound::TraitBound( PolyTrait { ref trait_, .. }, rustc_hir::TraitBoundModifiers::NONE, ) = *self - && cx.tcx.is_lang_item(trait_.def_id(), lang_item) + && tcx.is_lang_item(trait_.def_id(), lang_item) { return true; } From e2f3f78593f79488808d6f9eb6dca8e2f4bab57d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:29:09 +0200 Subject: [PATCH 37/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `clean::clean_bound_vars` function --- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 53655cbe5c200..96e15eac0a920 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -312,7 +312,7 @@ pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box( GenericBound::TraitBound( PolyTrait { trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints), - generic_params: clean_bound_vars(poly_trait_ref.bound_vars(), cx), + generic_params: clean_bound_vars(poly_trait_ref.bound_vars(), cx.tcx), }, hir::TraitBoundModifiers::NONE, ) @@ -2080,7 +2080,7 @@ pub(crate) fn clean_middle_ty<'tcx>( // FIXME: should we merge the outer and inner binders somehow? let sig = bound_ty.skip_binder().fn_sig(cx.tcx); let decl = clean_poly_fn_sig(cx, None, sig); - let generic_params = clean_bound_vars(sig.bound_vars(), cx); + let generic_params = clean_bound_vars(sig.bound_vars(), cx.tcx); BareFunction(Box::new(BareFunctionDecl { safety: sig.safety(), @@ -2090,7 +2090,7 @@ pub(crate) fn clean_middle_ty<'tcx>( })) } ty::UnsafeBinder(inner) => { - let generic_params = clean_bound_vars(inner.bound_vars(), cx); + let generic_params = clean_bound_vars(inner.bound_vars(), cx.tcx); let ty = clean_middle_ty(inner.into(), cx, None, None); UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty })) } @@ -3238,13 +3238,13 @@ fn clean_assoc_item_constraint<'tcx>( fn clean_bound_vars<'tcx>( bound_vars: &ty::List>, - cx: &mut DocContext<'tcx>, + tcx: TyCtxt<'tcx>, ) -> Vec { bound_vars .into_iter() .filter_map(|var| match var { ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id)) => { - let name = cx.tcx.item_name(def_id); + let name = tcx.item_name(def_id); if name != kw::UnderscoreLifetime { Some(GenericParamDef::lifetime(def_id, name)) } else { @@ -3252,7 +3252,7 @@ fn clean_bound_vars<'tcx>( } } ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id)) => { - let name = cx.tcx.item_name(def_id); + let name = tcx.item_name(def_id); Some(GenericParamDef { name, def_id, From 28ca36d4853d2af68f334197624e885805c1cc76 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:41:36 +0200 Subject: [PATCH 38/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `simplify` functions --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/librustdoc/clean/simplify.rs | 15 ++++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 847e688d03d0a..fc61103d939fb 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -203,7 +203,7 @@ fn clean_param_env<'tcx>( let mut generics = clean::Generics { params, where_predicates }; simplify::sized_bounds(cx, &mut generics); - generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates); + generics.where_predicates = simplify::where_clauses(cx.tcx, generics.where_predicates); generics } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 11481c25862d6..6bb585aa8933a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -925,7 +925,7 @@ fn clean_ty_generics_inner<'tcx>( if let Some(proj) = impl_trait_proj.remove(&idx) { for (trait_did, name, rhs) in proj { let rhs = clean_middle_term(rhs, cx); - simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs); + simplify::merge_bounds(cx.tcx, &mut bounds, trait_did, name, &rhs); } } @@ -939,7 +939,7 @@ fn clean_ty_generics_inner<'tcx>( let mut generics = Generics { params, where_predicates }; simplify::sized_bounds(cx, &mut generics); - generics.where_predicates = simplify::where_clauses(cx, generics.where_predicates); + generics.where_predicates = simplify::where_clauses(cx.tcx, generics.where_predicates); generics } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index c0ee741503ad9..154f31e89dbff 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -15,12 +15,13 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::DefId; +use rustc_middle::ty::TyCtxt; use crate::clean; use crate::clean::{GenericArgs as PP, WherePredicate as WP}; use crate::core::DocContext; -pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVec { +pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec) -> ThinVec { // First, partition the where clause into its separate components. // // We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to @@ -47,7 +48,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVe // general bound predicates. equalities.retain(|(lhs, rhs)| { let Some((bounds, _)) = tybounds.get_mut(&lhs.self_type) else { return true }; - merge_bounds(cx, bounds, lhs.trait_.as_ref().unwrap().def_id(), lhs.assoc.clone(), rhs) + merge_bounds(tcx, bounds, lhs.trait_.as_ref().unwrap().def_id(), lhs.assoc.clone(), rhs) }); // And finally, let's reassemble everything @@ -65,7 +66,7 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec) -> ThinVe } pub(crate) fn merge_bounds( - cx: &clean::DocContext<'_>, + tcx: TyCtxt<'_>, bounds: &mut [clean::GenericBound], trait_did: DefId, assoc: clean::PathSegment, @@ -79,7 +80,7 @@ pub(crate) fn merge_bounds( // If this QPath's trait `trait_did` is the same as, or a supertrait // of, the bound's trait `did` then we can keep going, otherwise // this is just a plain old equality bound. - if !trait_is_same_or_supertrait(cx, trait_ref.trait_.def_id(), trait_did) { + if !trait_is_same_or_supertrait(tcx, trait_ref.trait_.def_id(), trait_did) { return false; } let last = trait_ref.trait_.segments.last_mut().expect("segments were empty"); @@ -108,15 +109,15 @@ pub(crate) fn merge_bounds( }) } -fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool { +fn trait_is_same_or_supertrait(tcx: TyCtxt<'_>, child: DefId, trait_: DefId) -> bool { if child == trait_ { return true; } - let predicates = cx.tcx.explicit_super_predicates_of(child); + let predicates = tcx.explicit_super_predicates_of(child); predicates .iter_identity_copied() .filter_map(|(pred, _)| Some(pred.as_trait_clause()?.def_id())) - .any(|did| trait_is_same_or_supertrait(cx, did, trait_)) + .any(|did| trait_is_same_or_supertrait(tcx, did, trait_)) } pub(crate) fn sized_bounds(cx: &mut DocContext<'_>, generics: &mut clean::Generics) { From d1f11b23ca69387b8c52b9d0066937d547fe21ea Mon Sep 17 00:00:00 2001 From: Jacob Adam Date: Wed, 1 Apr 2026 14:38:56 +0100 Subject: [PATCH 39/61] Change the test comment per PR review feedback --- tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs | 5 +---- tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs index 4b87ae6080698..67aed9122e89f 100644 --- a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs +++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.rs @@ -1,7 +1,4 @@ -// #127423: ICE: assertion failed: sig.c_variadic || extra_args.is_empty() -// Calling a const fn with the wrong number of arguments where the function has -// an unresolved type should not trigger an ICE. -// issue: rust-lang/rust#127423 +//! Regression test for https://github.com/rust-lang/rust/issues/127423 #![allow(dead_code)] diff --git a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr index a5b2f5a578150..f01e9bd51357d 100644 --- a/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr +++ b/tests/ui/consts/ice-extra-args-fn-abi-issue-127423.stderr @@ -1,11 +1,11 @@ error: lifetimes cannot use keyword names - --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:18 + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:5:18 | LL | const fn add(a: &'self isize) -> usize { | ^^^^^ error[E0261]: use of undeclared lifetime name `'self` - --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:18 + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:5:18 | LL | const fn add(a: &'self isize) -> usize { | ^^^^^ undeclared lifetime @@ -16,13 +16,13 @@ LL | const fn add<'self>(a: &'self isize) -> usize { | +++++++ error[E0425]: cannot find value `Qux` in this scope - --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:11:5 + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:5 | LL | Qux + y | ^^^ not found in this scope error[E0425]: cannot find value `y` in this scope - --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:11:11 + --> $DIR/ice-extra-args-fn-abi-issue-127423.rs:8:11 | LL | Qux + y | ^ From 14aa3a904226d3e018e410407252869a9af0c0cb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:46:03 +0200 Subject: [PATCH 40/61] Remove unused `DocContext` argument in `clean_middle_const` --- src/librustdoc/clean/mod.rs | 5 ++--- src/librustdoc/clean/utils.rs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6bb585aa8933a..768831d4e40ec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -342,7 +342,6 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind pub(crate) fn clean_middle_const<'tcx>( constant: ty::Binder<'tcx, ty::Const<'tcx>>, - _cx: &mut DocContext<'tcx>, ) -> ConstantKind { // FIXME: instead of storing the stringified expression, store `self` directly instead. ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } @@ -464,7 +463,7 @@ fn clean_middle_term<'tcx>( ) -> Term { match term.skip_binder().kind() { ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None, None)), - ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)), + ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c))), } } @@ -479,7 +478,7 @@ fn clean_hir_term<'tcx>( // FIXME(generic_const_items): this should instantiate with the alias item's args let ty = cx.tcx.type_of(assoc_item.unwrap()).instantiate_identity(); let ct = lower_const_arg_for_rustdoc(cx.tcx, c, ty); - Term::Constant(clean_middle_const(ty::Binder::dummy(ct), cx)) + Term::Constant(clean_middle_const(ty::Binder::dummy(ct))) } } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 2f859d2c3b4e8..846b22dc4b475 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -148,7 +148,7 @@ pub(crate) fn clean_middle_generic_args<'tcx>( }), ))), GenericArgKind::Const(ct) => { - Some(GenericArg::Const(Box::new(clean_middle_const(arg.rebind(ct), cx)))) + Some(GenericArg::Const(Box::new(clean_middle_const(arg.rebind(ct))))) } } }; From 4b39934646c01de8dd50c59c003d71b2f0bb3c7b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 15:55:17 +0200 Subject: [PATCH 41/61] Replace `DocContext` argument with `TyCtxt` in rustdoc `utils::print_const` function --- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/clean/utils.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 768831d4e40ec..d6c57dd1639bb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1830,7 +1830,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); let ct = cx.tcx.normalize_erasing_regions(typing_env, ct); - print_const(cx, ct) + print_const(cx.tcx, ct) } hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) @@ -1839,7 +1839,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T | hir::ConstArgKind::Array(..) | hir::ConstArgKind::Literal { .. } => { let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, cx.tcx.types.usize); - print_const(cx, ct) + print_const(cx.tcx, ct) } }; Array(Box::new(clean_ty(ty, cx)), length.into()) @@ -2059,7 +2059,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ), ty::Array(ty, n) => { let n = cx.tcx.normalize_erasing_regions(cx.typing_env(), n); - let n = print_const(cx, n); + let n = print_const(cx.tcx, n); Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None, None)), n.into()) } ty::RawPtr(ty, mutbl) => { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 846b22dc4b475..2284b815a09a9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -347,13 +347,13 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { }) } -pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { +pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String { match n.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => { if let Some(def) = def.as_local() { - rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def) + rendered_const(tcx, tcx.hir_body_owned_by(def), def) } else { - inline::print_inlined_const(cx.tcx, def) + inline::print_inlined_const(tcx, def) } } // array lengths are obviously usize From 0b941ed495342e0bccd6c408b7e1c58074f43e94 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 1 Apr 2026 16:11:05 +0200 Subject: [PATCH 42/61] Last `DocContext`/`TyCtxt` cleanup --- src/librustdoc/clean/mod.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d6c57dd1639bb..67eee30e99a9f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -184,7 +184,8 @@ fn generate_item_with_correct_attrs( import_ids: &[LocalDefId], renamed: Option, ) -> Item { - let target_attrs = inline::load_attrs(cx.tcx, def_id); + let tcx = cx.tcx; + let target_attrs = inline::load_attrs(tcx, def_id); let attrs = if !import_ids.is_empty() { let mut attrs = Vec::with_capacity(import_ids.len()); let mut is_inline = false; @@ -196,11 +197,11 @@ fn generate_item_with_correct_attrs( // cfgs on the path up until the glob can be removed, and only cfgs on the globbed item // itself matter), for non-inlined re-exports see #85043. let import_is_inline = find_attr!( - inline::load_attrs(cx.tcx, import_id.to_def_id()), + inline::load_attrs(tcx, import_id.to_def_id()), Doc(d) if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) - ) || (is_glob_import(cx.tcx, import_id) - && (cx.document_hidden() || !cx.tcx.is_doc_hidden(def_id))); + ) || (is_glob_import(tcx, import_id) + && (cx.document_hidden() || !tcx.is_doc_hidden(def_id))); attrs.extend(get_all_import_attributes(cx, import_id, def_id, is_inline)); is_inline = is_inline || import_is_inline; } @@ -1458,7 +1459,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo bounds.retain(|b| { // FIXME(sized-hierarchy): Always skip `MetaSized` bounds so that only `?Sized` // is shown and none of the new sizedness traits leak into documentation. - !b.is_meta_sized_bound(cx.tcx) + !b.is_meta_sized_bound(tcx) }); // Our Sized/?Sized bound didn't get handled when creating the generics @@ -1466,7 +1467,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo // (some of them may have come from the trait). If we do have a sized // bound, we remove it, and if we don't then we add the `?Sized` bound // at the end. - match bounds.iter().position(|b| b.is_sized_bound(cx.tcx)) { + match bounds.iter().position(|b| b.is_sized_bound(tcx)) { Some(i) => { bounds.remove(i); } @@ -1516,7 +1517,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo } }; - Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, cx.tcx) + Item::from_def_id_and_parts(assoc_item.def_id, Some(assoc_item.name()), kind, tcx) } fn first_non_private_clean_path<'tcx>( @@ -2767,12 +2768,8 @@ fn clean_maybe_renamed_item<'tcx>( import_ids: &[LocalDefId], ) -> Vec { use hir::ItemKind; - fn get_name( - cx: &DocContext<'_>, - item: &hir::Item<'_>, - renamed: Option, - ) -> Option { - renamed.or_else(|| cx.tcx.hir_opt_name(item.hir_id())) + fn get_name(tcx: TyCtxt<'_>, item: &hir::Item<'_>, renamed: Option) -> Option { + renamed.or_else(|| tcx.hir_opt_name(item.hir_id())) } let def_id = item.owner_id.to_def_id(); @@ -2789,7 +2786,7 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Use(path, kind) => { return clean_use_statement( item, - get_name(cx, item, renamed), + get_name(cx.tcx, item, renamed), path, kind, cx, @@ -2799,7 +2796,7 @@ fn clean_maybe_renamed_item<'tcx>( _ => {} } - let mut name = get_name(cx, item, renamed).unwrap(); + let mut name = get_name(cx.tcx, item, renamed).unwrap(); let kind = match item.kind { ItemKind::Static(mutability, _, ty, body_id) => StaticItem(Static { From 98688ef1f93ede0a6f0b71287f6c16e1b114a61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 1 Apr 2026 17:01:56 +0200 Subject: [PATCH 43/61] Simplify feature gating checks & macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * utilize Kleene `?` two avoid having two macro matchers with almost identical body * inline `gate_legacy` since it only has one use and since it shouldn't be used anywhere else anyway * remove unnecessary explicit borrows of the visitor * replace `if let Some(spans) = spans.get(…) { for span in …` with `for &span in spans.get(…).into_iter().flatten()` to avoid rightward drift and explicit dereferences * rename `gate_all_legacy…` to `soft_gate_all_legacy…` since it's not a "proper" gate that issues an error but merely one that emits a warning --- compiler/rustc_ast_passes/src/feature_gate.rs | 232 +++++++----------- 1 file changed, 89 insertions(+), 143 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 830eb3d6d8170..84f07aa8ae521 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -14,31 +14,22 @@ use crate::errors; /// The common case. macro_rules! gate { - ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ + ($visitor:expr, $feature:ident, $span:expr, $explain:expr $(, $help:expr)?) => {{ if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) { - feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit(); - } - }}; - ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{ - if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) { - feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit(); + feature_err($visitor.sess, sym::$feature, $span, $explain) + $(.with_help($help))? + .emit(); } }}; } /// The unusual case, where the `has_feature` condition is non-standard. macro_rules! gate_alt { - ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{ + ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr $(, $notes:expr)?) => {{ if !$has_feature && !$span.allows_unstable($name) { - feature_err(&$visitor.sess, $name, $span, $explain).emit(); - } - }}; - ($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr, $notes: expr) => {{ - if !$has_feature && !$span.allows_unstable($name) { - let mut diag = feature_err(&$visitor.sess, $name, $span, $explain); - for note in $notes { - diag.note(*note); - } + #[allow(unused_mut)] + let mut diag = feature_err($visitor.sess, $name, $span, $explain); + $(for ¬e in $notes { diag.note(note); })? diag.emit(); } }}; @@ -51,21 +42,12 @@ macro_rules! gate_multi { let spans: Vec<_> = $spans.filter(|span| !span.allows_unstable(sym::$feature)).collect(); if !spans.is_empty() { - feature_err(&$visitor.sess, sym::$feature, spans, $explain).emit(); + feature_err($visitor.sess, sym::$feature, spans, $explain).emit(); } } }}; } -/// The legacy case. -macro_rules! gate_legacy { - ($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{ - if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) { - feature_warn(&$visitor.sess, sym::$feature, $span, $explain); - } - }}; -} - pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) { PostExpansionVisitor { sess, features }.visit_attribute(attr) } @@ -89,14 +71,14 @@ impl<'a> PostExpansionVisitor<'a> { if let ast::TyKind::ImplTrait(..) = ty.kind { if self.in_associated_ty { gate!( - &self.vis, + self.vis, impl_trait_in_assoc_type, ty.span, "`impl Trait` in associated types is unstable" ); } else { gate!( - &self.vis, + self.vis, type_alias_impl_trait, ty.span, "`impl Trait` in type aliases is unstable" @@ -211,7 +193,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { if item.has_name(sym::simd) { gate!( - &self, + self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy" @@ -224,7 +206,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) => { if let ast::ImplPolarity::Negative(span) = of_trait.polarity { gate!( - &self, + self, negative_impls, span.to(of_trait.trait_ref.path.span), "negative trait bounds are not fully implemented; \ @@ -233,26 +215,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } if let ast::Defaultness::Default(_) = of_trait.defaultness { - gate!(&self, specialization, i.span, "specialization is unstable"); + gate!(self, specialization, i.span, "specialization is unstable"); } } ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => { - gate!( - &self, - auto_traits, - i.span, - "auto traits are experimental and possibly buggy" - ); + gate!(self, auto_traits, i.span, "auto traits are experimental and possibly buggy"); } ast::ItemKind::TraitAlias(..) => { - gate!(&self, trait_alias, i.span, "trait aliases are experimental"); + gate!(self, trait_alias, i.span, "trait aliases are experimental"); } ast::ItemKind::MacroDef(_, ast::MacroDef { macro_rules: false, .. }) => { let msg = "`macro` is experimental"; - gate!(&self, decl_macro, i.span, msg); + gate!(self, decl_macro, i.span, msg); } ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { @@ -264,7 +241,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }) => { // Make sure this is only allowed if the feature gate is enabled. // #![feature(min_generic_const_args)] - gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable"); + gate!(self, min_generic_const_args, i.span, "top-level `type const` are unstable"); } _ => {} @@ -280,7 +257,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm.")); if links_to_llvm { gate!( - &self, + self, link_llvm_intrinsics, i.span, "linking to LLVM intrinsics is experimental" @@ -288,7 +265,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } ast::ForeignItemKind::TyAlias(..) => { - gate!(&self, extern_types, i.span, "extern types are experimental"); + gate!(self, extern_types, i.span, "extern types are experimental"); } ast::ForeignItemKind::MacCall(..) => {} } @@ -303,10 +280,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.check_late_bound_lifetime_defs(&fn_ptr_ty.generic_params); } ast::TyKind::Never => { - gate!(&self, never_type, ty.span, "the `!` type is experimental"); + gate!(self, never_type, ty.span, "the `!` type is experimental"); } ast::TyKind::Pat(..) => { - gate!(&self, pattern_types, ty.span, "pattern types are unstable"); + gate!(self, pattern_types, ty.span, "pattern types are unstable"); } _ => {} } @@ -339,7 +316,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { && let ast::FnRetTy::Ty(ref ty) = generic_args.output && matches!(ty.kind, ast::TyKind::Never) { - gate!(&self, never_type, ty.span, "the `!` type is experimental"); + gate!(self, never_type, ty.span, "the `!` type is experimental"); } visit::walk_generic_args(self, args); } @@ -348,7 +325,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { match e.kind { ast::ExprKind::TryBlock(_, None) => { // `try { ... }` is old and is only gated post-expansion here. - gate!(&self, try_blocks, e.span, "`try` expression is experimental"); + gate!(self, try_blocks, e.span, "`try` expression is experimental"); } ast::ExprKind::TryBlock(_, Some(_)) => { // `try_blocks_heterogeneous` is new, and gated pre-expansion instead. @@ -359,10 +336,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { .. }) => match suffix { Some(sym::f16) => { - gate!(&self, f16, e.span, "the type `f16` is unstable") + gate!(self, f16, e.span, "the type `f16` is unstable") } Some(sym::f128) => { - gate!(&self, f128, e.span, "the type `f128` is unstable") + gate!(self, f128, e.span, "the type `f128` is unstable") } _ => (), }, @@ -381,7 +358,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }; if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind { gate!( - &self, + self, half_open_range_patterns_in_slices, pat.span, "`X..` patterns in slices are experimental" @@ -390,7 +367,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } PatKind::Box(..) => { - gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental"); + gate!(self, box_patterns, pattern.span, "box pattern syntax is experimental"); } _ => {} } @@ -412,7 +389,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() { - gate!(&self, c_variadic, span, "C-variadic functions are unstable"); + gate!(self, c_variadic, span, "C-variadic functions are unstable"); } visit::walk_fn(self, fn_kind) @@ -424,7 +401,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate!( - &self, + self, associated_type_defaults, i.span, "associated type defaults are unstable" @@ -441,18 +418,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { }) => { // Make sure this is only allowed if the feature gate is enabled. // #![feature(min_generic_const_args)] - gate!( - &self, - min_generic_const_args, - i.span, - "associated `type const` are unstable" - ); + gate!(self, min_generic_const_args, i.span, "associated `type const` are unstable"); // Make sure associated `type const` defaults in traits are only allowed // if the feature gate is enabled. // #![feature(associated_type_defaults)] if ctxt == AssocCtxt::Trait && rhs.is_some() { gate!( - &self, + self, associated_type_defaults, i.span, "associated type defaults are unstable" @@ -486,18 +458,9 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { let spans = sess.psess.gated_spans.spans.borrow(); macro_rules! gate_all { - ($gate:ident, $msg:literal) => { - if let Some(spans) = spans.get(&sym::$gate) { - for span in spans { - gate!(&visitor, $gate, *span, $msg); - } - } - }; - ($gate:ident, $msg:literal, $help:literal) => { - if let Some(spans) = spans.get(&sym::$gate) { - for span in spans { - gate!(&visitor, $gate, *span, $msg, $help); - } + ($feature:ident, $explain:literal $(, $help:literal)?) => { + for &span in spans.get(&sym::$feature).into_iter().flatten() { + gate!(visitor, $feature, span, $explain $(, $help)?); } }; } @@ -513,18 +476,15 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "consider removing `for<...>`" ); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); - // yield can be enabled either by `coroutines` or `gen_blocks` - if let Some(spans) = spans.get(&sym::yield_expr) { - for span in spans { - if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) - && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) - && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) - { - // Emit yield_expr as the error, since that will be sufficient. You can think of it - // as coroutines and gen_blocks imply yield_expr. - feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental") - .emit(); - } + // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`. + for &span in spans.get(&sym::yield_expr).into_iter().flatten() { + if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) + && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) + && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) + { + // Emit yield_expr as the error, since that will be sufficient. You can think of it + // as coroutines and gen_blocks imply yield_expr. + feature_err(visitor.sess, sym::yield_expr, span, "yield syntax is experimental").emit(); } } gate_all!(gen_blocks, "gen blocks are experimental"); @@ -546,41 +506,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(postfix_match, "postfix match is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental"); - // associated_const_equality is stabilized as part of min_generic_const_args - if let Some(spans) = spans.get(&sym::associated_const_equality) { - for span in spans { - if !visitor.features.min_generic_const_args() - && !span.allows_unstable(sym::min_generic_const_args) - { - feature_err( - &visitor.sess, - sym::min_generic_const_args, - *span, - "associated const equality is incomplete", - ) - .emit(); - } - } + // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. + for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() { + gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete"); } // `mgca_type_const_syntax` is part of `min_generic_const_args` so either // or both are enabled we don't need to emit a feature error. - if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) { - for span in spans { - if visitor.features.min_generic_const_args() - || visitor.features.mgca_type_const_syntax() - || span.allows_unstable(sym::min_generic_const_args) - || span.allows_unstable(sym::mgca_type_const_syntax) - { - continue; - } - feature_err( - &visitor.sess, - sym::min_generic_const_args, - *span, - "`type const` syntax is experimental", - ) - .emit(); + for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() { + if visitor.features.min_generic_const_args() + || visitor.features.mgca_type_const_syntax() + || span.allows_unstable(sym::min_generic_const_args) + || span.allows_unstable(sym::mgca_type_const_syntax) + { + continue; } + feature_err( + visitor.sess, + sym::min_generic_const_args, + span, + "`type const` syntax is experimental", + ) + .emit(); } gate_all!(global_registration, "global registration is experimental"); @@ -599,30 +545,28 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(impl_restriction, "`impl` restrictions are experimental"); if !visitor.features.never_patterns() { - if let Some(spans) = spans.get(&sym::never_patterns) { - for &span in spans { - if span.allows_unstable(sym::never_patterns) { - continue; - } - let sm = sess.source_map(); - // We gate two types of spans: the span of a `!` pattern, and the span of a - // match arm without a body. For the latter we want to give the user a normal - // error. - if let Ok(snippet) = sm.span_to_snippet(span) - && snippet == "!" - { - feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") - .emit(); - } else { - let suggestion = span.shrink_to_hi(); - sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion }); - } + for &span in spans.get(&sym::never_patterns).into_iter().flatten() { + if span.allows_unstable(sym::never_patterns) { + continue; + } + let sm = sess.source_map(); + // We gate two types of spans: the span of a `!` pattern, and the span of a + // match arm without a body. For the latter we want to give the user a normal + // error. + if let Ok(snippet) = sm.span_to_snippet(span) + && snippet == "!" + { + feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") + .emit(); + } else { + let suggestion = span.shrink_to_hi(); + sess.dcx().emit_err(errors::MatchArmWithNoBody { span, suggestion }); } } } if !visitor.features.negative_bounds() { - for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() { + for &span in spans.get(&sym::negative_bounds).into_iter().flatten() { sess.dcx().emit_err(errors::NegativeBoundUnsupported { span }); } } @@ -631,19 +575,21 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { // and subsequently disabled (with the non-early gating readded). // We emit an early future-incompatible warning for these. // New syntax gates should go above here to get a hard error gate. - macro_rules! gate_all_legacy_dont_use { - ($gate:ident, $msg:literal) => { - for span in spans.get(&sym::$gate).unwrap_or(&vec![]) { - gate_legacy!(&visitor, $gate, *span, $msg); + macro_rules! soft_gate_all_legacy_dont_use { + ($feature:ident, $explain:literal) => { + for &span in spans.get(&sym::$feature).into_iter().flatten() { + if !visitor.features.$feature() && !span.allows_unstable(sym::$feature) { + feature_warn(&visitor.sess, sym::$feature, span, $explain); + } } }; } - gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); - gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); - gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); - gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); - gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); + soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); + soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); + soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); + soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); + soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); visit::walk_crate(&mut visitor, krate); } From dd96eff7690df4d7c83176e2a3ab081b09f985c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 1 Apr 2026 14:28:01 +0200 Subject: [PATCH 44/61] Sort pre-expansion gates and add more visible disclaimers --- compiler/rustc_ast_passes/src/feature_gate.rs | 145 +++++++++++------- .../precise-capturing/bound-modifiers.stderr | 20 +-- 2 files changed, 97 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 84f07aa8ae521..d8ace8e38634c 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -59,6 +59,15 @@ struct PostExpansionVisitor<'a> { features: &'a Features, } +// ----------------------------------------------------------------------------- +// POST-EXPANSION FEATURE GATES FOR UNSTABLE ATTRIBUTES ETC. +// **LEGACY** POST-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY** +// ----------------------------------------------------------------------------- + +// IMPORTANT: Don't add any new post-expansion feature gates for new unstable syntax! +// It's a legacy mechanism for them. +// Instead, register a pre-expansion feature gate using `gate_all` in fn `check_crate`. + impl<'a> PostExpansionVisitor<'a> { /// Feature gate `impl Trait` inside `type Alias = $type_expr;`. fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) { @@ -448,6 +457,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } +// ----------------------------------------------------------------------------- + pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { maybe_stage_features(sess, features, krate); check_incompatible_features(sess, features); @@ -456,6 +467,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { let mut visitor = PostExpansionVisitor { sess, features }; + // ----------------------------------------------------------------------------- + // PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX + // ----------------------------------------------------------------------------- + let spans = sess.psess.gated_spans.spans.borrow(); macro_rules! gate_all { ($feature:ident, $explain:literal $(, $help:literal)?) => { @@ -464,54 +479,63 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } }; } + + // tidy-alphabetical-start + gate_all!(async_for_loop, "`for await` loops are experimental"); + gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); + gate_all!(const_block_items, "const block items are experimental"); + gate_all!(const_closures, "const closures are experimental"); + gate_all!(const_trait_impl, "const trait impls are experimental"); + gate_all!(contracts, "contracts are incomplete"); + gate_all!(contracts_internals, "contract internal machinery is for internal use only"); + gate_all!(coroutines, "coroutine syntax is experimental"); + gate_all!(default_field_values, "default values on fields are experimental"); + gate_all!(ergonomic_clones, "ergonomic clones are experimental"); + gate_all!(explicit_tail_calls, "`become` expression is experimental"); + gate_all!(final_associated_functions, "`final` on trait functions is experimental"); + gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); + gate_all!(frontmatter, "frontmatters are experimental"); + gate_all!(gen_blocks, "gen blocks are experimental"); + gate_all!(generic_const_items, "generic const items are experimental"); + gate_all!(global_registration, "global registration is experimental"); + gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); + gate_all!(impl_restriction, "`impl` restrictions are experimental"); + gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental"); + gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); + gate_all!(mut_ref, "mutable by-reference bindings are experimental"); + gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); + gate_all!(postfix_match, "postfix match is experimental"); + gate_all!(return_type_notation, "return type notation is experimental"); + gate_all!(super_let, "`super let` is experimental"); + gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental"); + gate_all!(unsafe_binders, "unsafe binder types are experimental"); + gate_all!(unsafe_fields, "`unsafe` fields are experimental"); + gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); + gate_all!(yeet_expr, "`do yeet` expression is experimental"); + // tidy-alphabetical-end + gate_all!( async_trait_bounds, "`async` trait bounds are unstable", "use the desugared name of the async trait, such as `AsyncFn`" ); - gate_all!(async_for_loop, "`for await` loops are experimental"); gate_all!( closure_lifetime_binder, "`for<...>` binders for closures are experimental", "consider removing `for<...>`" ); - gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); - // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`. - for &span in spans.get(&sym::yield_expr).into_iter().flatten() { - if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) - && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) - && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) - { - // Emit yield_expr as the error, since that will be sufficient. You can think of it - // as coroutines and gen_blocks imply yield_expr. - feature_err(visitor.sess, sym::yield_expr, span, "yield syntax is experimental").emit(); - } - } - gate_all!(gen_blocks, "gen blocks are experimental"); - gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!( half_open_range_patterns_in_slices, "half-open range patterns in slices are unstable" ); - gate_all!(try_blocks_heterogeneous, "`try bikeshed` expression is experimental"); - gate_all!(yeet_expr, "`do yeet` expression is experimental"); - gate_all!(const_closures, "const closures are experimental"); - gate_all!(builtin_syntax, "`builtin #` syntax is unstable"); - gate_all!(ergonomic_clones, "ergonomic clones are experimental"); - gate_all!(explicit_tail_calls, "`become` expression is experimental"); - gate_all!(generic_const_items, "generic const items are experimental"); - gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); - gate_all!(default_field_values, "default values on fields are experimental"); - gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); - gate_all!(postfix_match, "postfix match is experimental"); - gate_all!(mut_ref, "mutable by-reference bindings are experimental"); - gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental"); - // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. + + // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. for &span in spans.get(&sym::associated_const_equality).into_iter().flatten() { gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete"); } - // `mgca_type_const_syntax` is part of `min_generic_const_args` so either - // or both are enabled we don't need to emit a feature error. + + // `mgca_type_const_syntax` is part of `min_generic_const_args` so if + // either or both are enabled we don't need to emit a feature error. for &span in spans.get(&sym::mgca_type_const_syntax).into_iter().flatten() { if visitor.features.min_generic_const_args() || visitor.features.mgca_type_const_syntax() @@ -529,33 +553,23 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { .emit(); } - gate_all!(global_registration, "global registration is experimental"); - gate_all!(return_type_notation, "return type notation is experimental"); - gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); - gate_all!(unsafe_fields, "`unsafe` fields are experimental"); - gate_all!(unsafe_binders, "unsafe binder types are experimental"); - gate_all!(contracts, "contracts are incomplete"); - gate_all!(contracts_internals, "contract internal machinery is for internal use only"); - gate_all!(where_clause_attrs, "attributes in `where` clause are unstable"); - gate_all!(super_let, "`super let` is experimental"); - gate_all!(frontmatter, "frontmatters are experimental"); - gate_all!(coroutines, "coroutine syntax is experimental"); - gate_all!(const_block_items, "const block items are experimental"); - gate_all!(final_associated_functions, "`final` on trait functions is experimental"); - gate_all!(impl_restriction, "`impl` restrictions are experimental"); + // Negative bounds are *super* internal. + // Under no circumstances do we want to advertise the feature name to users! + if !visitor.features.negative_bounds() { + for &span in spans.get(&sym::negative_bounds).into_iter().flatten() { + sess.dcx().emit_err(errors::NegativeBoundUnsupported { span }); + } + } if !visitor.features.never_patterns() { for &span in spans.get(&sym::never_patterns).into_iter().flatten() { if span.allows_unstable(sym::never_patterns) { continue; } - let sm = sess.source_map(); // We gate two types of spans: the span of a `!` pattern, and the span of a // match arm without a body. For the latter we want to give the user a normal // error. - if let Ok(snippet) = sm.span_to_snippet(span) - && snippet == "!" - { + if let Ok("!") = sess.source_map().span_to_snippet(span).as_deref() { feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental") .emit(); } else { @@ -565,16 +579,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { } } - if !visitor.features.negative_bounds() { - for &span in spans.get(&sym::negative_bounds).into_iter().flatten() { - sess.dcx().emit_err(errors::NegativeBoundUnsupported { span }); + // Yield exprs can be enabled either by `yield_expr`, by `coroutines` or by `gen_blocks`. + for &span in spans.get(&sym::yield_expr).into_iter().flatten() { + if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) + && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) + && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) + { + // Only mentioned `yield_expr` in the diagnostic since that'll be sufficient. + // You can think of it as `coroutines` and `gen_blocks` implying `yield_expr`. + feature_err(visitor.sess, sym::yield_expr, span, "yield syntax is experimental").emit(); } } - // All uses of `gate_all_legacy_dont_use!` below this point were added in #65742, - // and subsequently disabled (with the non-early gating readded). - // We emit an early future-incompatible warning for these. - // New syntax gates should go above here to get a hard error gate. + // ----------------------------------------------------------------------------- + // **LEGACY** SOFT PRE-EXPANSION FEATURE GATES FOR UNSTABLE SYNTAX **LEGACY** + // ----------------------------------------------------------------------------- + + // IMPORTANT: Do not extend the list below! New syntax should go above and use `gate_all`. + + // FIXME(#154045): Migrate all of these to erroring feature gates and + // remove the corresponding post-expansion feature gates. + macro_rules! soft_gate_all_legacy_dont_use { ($feature:ident, $explain:literal) => { for &span in spans.get(&sym::$feature).into_iter().flatten() { @@ -585,11 +610,15 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { }; } + // tidy-alphabetical-start + soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); - soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); + soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); - soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); + // tidy-alphabetical-end + + // ----------------------------------------------------------------------------- visit::walk_crate(&mut visitor, krate); } diff --git a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr index deab31c251f83..4a0532284c176 100644 --- a/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr +++ b/tests/ui/impl-trait/precise-capturing/bound-modifiers.stderr @@ -46,6 +46,16 @@ error[E0405]: cannot find trait `r#use` in this scope LL | fn binder() -> impl Sized + for<'a> use<> {} | ^^^ not found in this scope +error[E0658]: const trait impls are experimental + --> $DIR/bound-modifiers.rs:12:32 + | +LL | fn constness() -> impl Sized + const use<> {} + | ^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` 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]: `async` trait bounds are unstable --> $DIR/bound-modifiers.rs:7:32 | @@ -57,16 +67,6 @@ LL | fn asyncness() -> impl Sized + async use<> {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: use the desugared name of the async trait, such as `AsyncFn` -error[E0658]: const trait impls are experimental - --> $DIR/bound-modifiers.rs:12:32 - | -LL | fn constness() -> impl Sized + const use<> {} - | ^^^^^ - | - = note: see issue #143874 for more information - = help: add `#![feature(const_trait_impl)]` 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 10 previous errors Some errors have detailed explanations: E0405, E0658. From 394012bcd28612217ba6d54ad8948e143974d16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 29 Mar 2026 14:36:35 +0200 Subject: [PATCH 45/61] Emit pre-expansion feature gate warning for negative impls --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 ++-- compiler/rustc_parse/src/parser/item.rs | 1 + tests/ui/auto-traits/ungated-impl.rs | 7 ------ tests/ui/auto-traits/ungated-impl.stderr | 23 ------------------- .../feature-gates/feature-gate-auto-traits.rs | 11 ++------- .../feature-gate-auto-traits.stderr | 16 ++++++------- .../soft-feature-gate-negative_impls.rs | 12 ++++++++++ .../soft-feature-gate-negative_impls.stderr | 14 +++++++++++ .../feature-gate-negative_impls.rs | 4 +++- .../feature-gate-negative_impls.stderr | 5 ++-- 10 files changed, 46 insertions(+), 52 deletions(-) delete mode 100644 tests/ui/auto-traits/ungated-impl.rs delete mode 100644 tests/ui/auto-traits/ungated-impl.stderr create mode 100644 tests/ui/feature-gates/soft-feature-gate-negative_impls.rs create mode 100644 tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d8ace8e38634c..ae046c61c2767 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -218,8 +218,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self, negative_impls, span.to(of_trait.trait_ref.path.span), - "negative trait bounds are not fully implemented; \ - use marker types for now" + "negative impls are experimental", + "use marker types for now" ); } @@ -614,6 +614,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { soft_gate_all_legacy_dont_use!(auto_traits, "`auto` traits are unstable"); soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); + soft_gate_all_legacy_dont_use!(negative_impls, "negative impls are experimental"); soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); // tidy-alphabetical-end diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0f4927432f6fa..823d5957949cb 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -603,6 +603,7 @@ impl<'a> Parser<'a> { fn parse_polarity(&mut self) -> ast::ImplPolarity { // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. if self.check(exp!(Bang)) && self.look_ahead(1, |t| t.can_begin_type()) { + self.psess.gated_spans.gate(sym::negative_impls, self.token.span); self.bump(); // `!` ast::ImplPolarity::Negative(self.prev_token.span) } else { diff --git a/tests/ui/auto-traits/ungated-impl.rs b/tests/ui/auto-traits/ungated-impl.rs deleted file mode 100644 index d46b4b01af9c7..0000000000000 --- a/tests/ui/auto-traits/ungated-impl.rs +++ /dev/null @@ -1,7 +0,0 @@ -auto trait MyTrait {} -//~^ ERROR auto traits are experimental and possibly buggy - -impl !MyTrait for *mut T {} -//~^ ERROR negative trait bounds are not fully implemented - -fn main() {} diff --git a/tests/ui/auto-traits/ungated-impl.stderr b/tests/ui/auto-traits/ungated-impl.stderr deleted file mode 100644 index 9d10d46a90283..0000000000000 --- a/tests/ui/auto-traits/ungated-impl.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: auto traits are experimental and possibly buggy - --> $DIR/ungated-impl.rs:1:1 - | -LL | auto trait MyTrait {} - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #13231 for more information - = help: add `#![feature(auto_traits)]` 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]: negative trait bounds are not fully implemented; use marker types for now - --> $DIR/ungated-impl.rs:4:9 - | -LL | impl !MyTrait for *mut T {} - | ^^^^^^^^ - | - = note: see issue #68318 for more information - = help: add `#![feature(negative_impls)]` 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 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.rs b/tests/ui/feature-gates/feature-gate-auto-traits.rs index aab9e784fe9d7..e900fb84a02d9 100644 --- a/tests/ui/feature-gates/feature-gate-auto-traits.rs +++ b/tests/ui/feature-gates/feature-gate-auto-traits.rs @@ -1,12 +1,5 @@ -// Test that default and negative trait implementations are gated by -// `auto_traits` feature gate +auto trait DummyAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy -struct DummyStruct; - -auto trait AutoDummyTrait {} -//~^ ERROR auto traits are experimental and possibly buggy - -impl !AutoDummyTrait for DummyStruct {} -//~^ ERROR negative trait bounds are not fully implemented; use marker types for now +pub unsafe auto trait AnotherAutoTrait {} //~ ERROR auto traits are experimental and possibly buggy fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-auto-traits.stderr b/tests/ui/feature-gates/feature-gate-auto-traits.stderr index 8fa5168b2d041..d476b4fecbe58 100644 --- a/tests/ui/feature-gates/feature-gate-auto-traits.stderr +++ b/tests/ui/feature-gates/feature-gate-auto-traits.stderr @@ -1,21 +1,21 @@ error[E0658]: auto traits are experimental and possibly buggy - --> $DIR/feature-gate-auto-traits.rs:6:1 + --> $DIR/feature-gate-auto-traits.rs:1:1 | -LL | auto trait AutoDummyTrait {} +LL | auto trait DummyAutoTrait {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #13231 for more information = help: add `#![feature(auto_traits)]` 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]: negative trait bounds are not fully implemented; use marker types for now - --> $DIR/feature-gate-auto-traits.rs:9:6 +error[E0658]: auto traits are experimental and possibly buggy + --> $DIR/feature-gate-auto-traits.rs:3:1 | -LL | impl !AutoDummyTrait for DummyStruct {} - | ^^^^^^^^^^^^^^^ +LL | pub unsafe auto trait AnotherAutoTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #68318 for more information - = help: add `#![feature(negative_impls)]` to the crate attributes to enable + = note: see issue #13231 for more information + = help: add `#![feature(auto_traits)]` 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 2 previous errors diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs new file mode 100644 index 0000000000000..7c578f20d2dc0 --- /dev/null +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs @@ -0,0 +1,12 @@ +// For historical reasons, negative impls don't have a proper pre-expansion feature gate. +// We're now at least issuing a *warning* for those that only exist before macro expansion. +// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// As part of this, move these test cases into `feature-gate-negative_impls.rs`. +//@ check-pass + +#[cfg(false)] +impl !Trait for () {} +//~^ WARN negative impls are experimental +//~| WARN unstable syntax can change at any point in the future + +fn main() {} diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr new file mode 100644 index 0000000000000..35e125cb2d24c --- /dev/null +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.stderr @@ -0,0 +1,14 @@ +warning: negative impls are experimental + --> $DIR/soft-feature-gate-negative_impls.rs:8:6 + | +LL | impl !Trait for () {} + | ^ + | + = note: see issue #68318 for more information + = help: add `#![feature(negative_impls)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 1 warning emitted + diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs index 8d3f6ff6d78c7..1b3c5abe10918 100644 --- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.rs @@ -1,3 +1,5 @@ trait MyTrait {} -impl !MyTrait for u32 {} //~ ERROR negative trait bounds are not fully implemented + +impl !MyTrait for u32 {} //~ ERROR negative impls are experimental + fn main() {} diff --git a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr index 1777dfcc993f1..36bc5bb4be2bc 100644 --- a/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr +++ b/tests/ui/traits/negative-impls/feature-gate-negative_impls.stderr @@ -1,5 +1,5 @@ -error[E0658]: negative trait bounds are not fully implemented; use marker types for now - --> $DIR/feature-gate-negative_impls.rs:2:6 +error[E0658]: negative impls are experimental + --> $DIR/feature-gate-negative_impls.rs:3:6 | LL | impl !MyTrait for u32 {} | ^^^^^^^^ @@ -7,6 +7,7 @@ LL | impl !MyTrait for u32 {} = note: see issue #68318 for more information = help: add `#![feature(negative_impls)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use marker types for now error: aborting due to 1 previous error From 92fbfae16b868be626465d005222366ad4b31960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 28 Mar 2026 19:20:21 +0100 Subject: [PATCH 46/61] Emit pre-expansion feature gate warning for item modifier `default` --- compiler/rustc_ast_passes/src/feature_gate.rs | 15 ++++- compiler/rustc_parse/src/parser/item.rs | 11 +++- tests/ui/macros/stringify.rs | 3 +- .../trait-item-with-defaultness-pass.rs | 1 + .../feature-gate-specialization.rs | 21 +++++++ .../feature-gate-specialization.stderr | 45 ++++++++++++++ ...feature-gate-specialization.default.stderr | 62 +++++++++++++++++++ ...oft-feature-gate-specialization.min.stderr | 38 ++++++++++++ .../soft-feature-gate-specialization.rs | 44 +++++++++++++ .../specialization-feature-gate-default.rs | 13 ---- ...specialization-feature-gate-default.stderr | 13 ---- tests/ui/track-diagnostics/track6.rs | 2 +- tests/ui/track-diagnostics/track6.stderr | 2 +- 13 files changed, 238 insertions(+), 32 deletions(-) create mode 100644 tests/ui/specialization/feature-gate-specialization.rs create mode 100644 tests/ui/specialization/feature-gate-specialization.stderr create mode 100644 tests/ui/specialization/soft-feature-gate-specialization.default.stderr create mode 100644 tests/ui/specialization/soft-feature-gate-specialization.min.stderr create mode 100644 tests/ui/specialization/soft-feature-gate-specialization.rs delete mode 100644 tests/ui/specialization/specialization-feature-gate-default.rs delete mode 100644 tests/ui/specialization/specialization-feature-gate-default.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index ae046c61c2767..1b615b611258f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -224,7 +224,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } if let ast::Defaultness::Default(_) = of_trait.defaultness { - gate!(self, specialization, i.span, "specialization is unstable"); + gate!(self, specialization, i.span, "specialization is experimental"); } } @@ -450,7 +450,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.features.specialization() || (is_fn && self.features.min_specialization()), sym::specialization, i.span, - "specialization is unstable" + "specialization is experimental" ); } visit::walk_assoc_item(self, i, ctxt) @@ -615,10 +615,21 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { soft_gate_all_legacy_dont_use!(box_patterns, "box pattern syntax is experimental"); soft_gate_all_legacy_dont_use!(decl_macro, "`macro` is experimental"); soft_gate_all_legacy_dont_use!(negative_impls, "negative impls are experimental"); + soft_gate_all_legacy_dont_use!(specialization, "specialization is experimental"); soft_gate_all_legacy_dont_use!(trait_alias, "trait aliases are experimental"); soft_gate_all_legacy_dont_use!(try_blocks, "`try` blocks are unstable"); // tidy-alphabetical-end + for &span in spans.get(&sym::min_specialization).into_iter().flatten() { + if !visitor.features.specialization() + && !visitor.features.min_specialization() + && !span.allows_unstable(sym::specialization) + && !span.allows_unstable(sym::min_specialization) + { + feature_warn(visitor.sess, sym::specialization, span, "specialization is experimental"); + } + } + // ----------------------------------------------------------------------------- visit::walk_crate(&mut visitor, krate); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 823d5957949cb..79b79db6ccc07 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -248,10 +248,18 @@ impl<'a> Parser<'a> { self.parse_use_item()? } else if self.check_fn_front_matter(check_pub, case) { // FUNCTION ITEM + let defaultness = def_(); + if let Defaultness::Default(span) = defaultness { + // Default functions should only require feature `min_specialization`. We remove the + // `specialization` tag again as such spans *require* feature `specialization` to be + // enabled. In a later stage, we make `specialization` imply `min_specialization`. + self.psess.gated_spans.gate(sym::min_specialization, span); + self.psess.gated_spans.ungate_last(sym::specialization, span); + } let (ident, sig, generics, contract, body) = self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?; ItemKind::Fn(Box::new(Fn { - defaultness: def_(), + defaultness, ident, sig, generics, @@ -1016,6 +1024,7 @@ impl<'a> Parser<'a> { if self.check_keyword(exp!(Default)) && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As)) { + self.psess.gated_spans.gate(sym::specialization, self.token.span); self.bump(); // `default` Defaultness::Default(self.prev_token_uninterpolated_span()) } else if self.eat_keyword(exp!(Final)) { diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs index af2ba7a809ad0..46f50593c4e95 100644 --- a/tests/ui/macros/stringify.rs +++ b/tests/ui/macros/stringify.rs @@ -9,12 +9,13 @@ #![feature(const_trait_impl)] #![feature(coroutines)] #![feature(decl_macro)] +#![feature(macro_guard_matcher)] #![feature(more_qualified_paths)] #![feature(never_patterns)] +#![feature(specialization)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] -#![feature(macro_guard_matcher)] #![deny(unused_macros)] // These macros force the use of AST pretty-printing by converting the input to diff --git a/tests/ui/parser/trait-item-with-defaultness-pass.rs b/tests/ui/parser/trait-item-with-defaultness-pass.rs index 164d0b13b539c..e8452fcbd5f99 100644 --- a/tests/ui/parser/trait-item-with-defaultness-pass.rs +++ b/tests/ui/parser/trait-item-with-defaultness-pass.rs @@ -1,4 +1,5 @@ //@ check-pass +#![feature(specialization)] fn main() {} diff --git a/tests/ui/specialization/feature-gate-specialization.rs b/tests/ui/specialization/feature-gate-specialization.rs new file mode 100644 index 0000000000000..82e467ad98d32 --- /dev/null +++ b/tests/ui/specialization/feature-gate-specialization.rs @@ -0,0 +1,21 @@ +trait Trait { + type Ty; + const CT: (); + fn fn_(&self); +} + +impl Trait for T { + default type Ty = (); //~ ERROR specialization is experimental + default const CT: () = (); //~ ERROR specialization is experimental + default fn fn_(&self) {} //~ ERROR specialization is experimental +} + +trait OtherTrait { + fn fn_(); +} + +default impl OtherTrait for T { //~ ERROR specialization is experimental + fn fn_() {} +} + +fn main() {} diff --git a/tests/ui/specialization/feature-gate-specialization.stderr b/tests/ui/specialization/feature-gate-specialization.stderr new file mode 100644 index 0000000000000..2efc0faa7c23e --- /dev/null +++ b/tests/ui/specialization/feature-gate-specialization.stderr @@ -0,0 +1,45 @@ +error[E0658]: specialization is experimental + --> $DIR/feature-gate-specialization.rs:8:5 + | +LL | default type Ty = (); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` 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]: specialization is experimental + --> $DIR/feature-gate-specialization.rs:9:5 + | +LL | default const CT: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` 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]: specialization is experimental + --> $DIR/feature-gate-specialization.rs:10:5 + | +LL | default fn fn_(&self) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` 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]: specialization is experimental + --> $DIR/feature-gate-specialization.rs:17:1 + | +LL | / default impl OtherTrait for T { +LL | | fn fn_() {} +LL | | } + | |_^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` 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 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/specialization/soft-feature-gate-specialization.default.stderr b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr new file mode 100644 index 0000000000000..f5961090947ed --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.default.stderr @@ -0,0 +1,62 @@ +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:21:5 + | +LL | default type Ty = (); + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:24:5 + | +LL | default const CT: () = (); + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:40:1 + | +LL | default impl Trait for () {} + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:27:5 + | +LL | default fn fn_(); + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:35:1 + | +LL | default fn fn_() {} + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 5 warnings emitted + diff --git a/tests/ui/specialization/soft-feature-gate-specialization.min.stderr b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr new file mode 100644 index 0000000000000..aa4ce0cc58be2 --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.min.stderr @@ -0,0 +1,38 @@ +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:21:5 + | +LL | default type Ty = (); + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:24:5 + | +LL | default const CT: () = (); + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: specialization is experimental + --> $DIR/soft-feature-gate-specialization.rs:40:1 + | +LL | default impl Trait for () {} + | ^^^^^^^ + | + = note: see issue #31844 for more information + = help: add `#![feature(specialization)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = warning: unstable syntax can change at any point in the future, causing a hard error! + = note: for more information, see issue #65860 + +warning: 3 warnings emitted + diff --git a/tests/ui/specialization/soft-feature-gate-specialization.rs b/tests/ui/specialization/soft-feature-gate-specialization.rs new file mode 100644 index 0000000000000..e671bc20a1f34 --- /dev/null +++ b/tests/ui/specialization/soft-feature-gate-specialization.rs @@ -0,0 +1,44 @@ +// For historical reasons, item modifier `default` doesn't have a proper pre-expansion feature gate. +// We're now at least issuing a *warning* for those that only exist before macro expansion. +// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// As part of this, move these test cases into `feature-gate-specialization.rs`. +// +// Moreover, `specialization` implies `min_specialization` similar to the post-expansion gate. +// +// However, while we only gate `default` *associated* functions only behind `min_specialization` OR +// `specialization` in the post-expansion case, in the pre-expansion case we gate all kinds of +// functions (free, assoc, foreign) behind `min_specialization` OR `specialization` if marked with +// `default` for simplicity of implementation. Ultimately it doesn't matter since we later reject +// `default` on anything other than impls & impl assoc items during semantic analysis. +// +//@ revisions: default min full +//@ check-pass +#![cfg_attr(min, feature(min_specialization))] +#![cfg_attr(full, feature(specialization))] + +#[cfg(false)] +impl Trait for () { + default type Ty = (); + //[default,min]~^ WARN specialization is experimental + //[default,min]~| WARN unstable syntax can change at any point in the future + default const CT: () = (); + //[default,min]~^ WARN specialization is experimental + //[default,min]~| WARN unstable syntax can change at any point in the future + default fn fn_(); + //[default]~^ WARN specialization is experimental + //[default]~| WARN unstable syntax can change at any point in the future +} + +// While free ty/ct/fn items marked `default` are +// semantically malformed we still need to gate the keyword! +#[cfg(false)] +default fn fn_() {} +//[default]~^ WARN specialization is experimental +//[default]~| WARN unstable syntax can change at any point in the future + +#[cfg(false)] +default impl Trait for () {} +//[default,min]~^ WARN specialization is experimental +//[default,min]~| WARN unstable syntax can change at any point in the future + +fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.rs b/tests/ui/specialization/specialization-feature-gate-default.rs deleted file mode 100644 index 8bad3ac0a1fb3..0000000000000 --- a/tests/ui/specialization/specialization-feature-gate-default.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Check that specialization must be ungated to use the `default` keyword - -// gate-test-specialization - -trait Foo { - fn foo(&self); -} - -impl Foo for T { - default fn foo(&self) {} //~ ERROR specialization is unstable -} - -fn main() {} diff --git a/tests/ui/specialization/specialization-feature-gate-default.stderr b/tests/ui/specialization/specialization-feature-gate-default.stderr deleted file mode 100644 index 3e651b6ee4f37..0000000000000 --- a/tests/ui/specialization/specialization-feature-gate-default.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: specialization is unstable - --> $DIR/specialization-feature-gate-default.rs:10:5 - | -LL | default fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #31844 for more information - = help: add `#![feature(specialization)]` 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 - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs index aa75c5691e5f9..38d34f46270a4 100644 --- a/tests/ui/track-diagnostics/track6.rs +++ b/tests/ui/track-diagnostics/track6.rs @@ -12,7 +12,7 @@ pub trait Foo { impl Foo for T { default fn bar() {} - //~^ ERROR specialization is unstable + //~^ ERROR specialization is experimental //~| NOTE created at } diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr index a61f7855e3231..30d518a69cadd 100644 --- a/tests/ui/track-diagnostics/track6.stderr +++ b/tests/ui/track-diagnostics/track6.stderr @@ -1,4 +1,4 @@ -error[E0658]: specialization is unstable +error[E0658]: specialization is experimental --> $DIR/track6.rs:LL:CC | LL | default fn bar() {} From 3e658d3744373f0b362acacd6c9daf50ee7441c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 1 Apr 2026 14:15:26 +0200 Subject: [PATCH 47/61] Reword descriptions of soft feature gate tests --- tests/ui/feature-gates/soft-feature-gate-auto_traits.rs | 6 +++--- tests/ui/feature-gates/soft-feature-gate-box_patterns.rs | 6 +++--- tests/ui/feature-gates/soft-feature-gate-decl_macro.rs | 6 +++--- tests/ui/feature-gates/soft-feature-gate-negative_impls.rs | 6 +++--- tests/ui/feature-gates/soft-feature-gate-trait_alias.rs | 6 +++--- tests/ui/feature-gates/soft-feature-gate-try_blocks.rs | 6 +++--- tests/ui/specialization/soft-feature-gate-specialization.rs | 4 ++-- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs index 0ccbaf1e476a9..01f44df0d7621 100644 --- a/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs +++ b/tests/ui/feature-gates/soft-feature-gate-auto_traits.rs @@ -1,6 +1,6 @@ -// For historical reasons, auto traits don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, auto traits don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-auto-traits.rs`. //@ check-pass diff --git a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs index 8ab0e80e6be31..9fdaa7a0ec08c 100644 --- a/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs +++ b/tests/ui/feature-gates/soft-feature-gate-box_patterns.rs @@ -1,6 +1,6 @@ -// For historical reasons, box patterns don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, box patterns don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-box_patterns.rs`. //@ check-pass diff --git a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs index 7d2d48503797a..dbc0b940265fc 100644 --- a/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs +++ b/tests/ui/feature-gates/soft-feature-gate-decl_macro.rs @@ -1,6 +1,6 @@ -// For historical reasons, decl macros 2.0 don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, decl macros 2.0 don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-decl_macro.rs`. //@ check-pass diff --git a/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs index 7c578f20d2dc0..0071ce6350b16 100644 --- a/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs +++ b/tests/ui/feature-gates/soft-feature-gate-negative_impls.rs @@ -1,6 +1,6 @@ -// For historical reasons, negative impls don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, negative impls don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-negative_impls.rs`. //@ check-pass diff --git a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs index 553e88375a2a7..7f929f5198a70 100644 --- a/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs +++ b/tests/ui/feature-gates/soft-feature-gate-trait_alias.rs @@ -1,6 +1,6 @@ -// For historical reasons, trait aliases don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, trait aliases don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-trait-alias.rs`. //@ check-pass diff --git a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs index aa51e60d56b4a..3f439d0c26893 100644 --- a/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs +++ b/tests/ui/feature-gates/soft-feature-gate-try_blocks.rs @@ -1,6 +1,6 @@ -// For historical reasons, try blocks don't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// For historical reasons, try blocks don't have an erroring pre-expansion feature gate. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-try_blocks.rs`. //@ edition: 2018 //@ check-pass diff --git a/tests/ui/specialization/soft-feature-gate-specialization.rs b/tests/ui/specialization/soft-feature-gate-specialization.rs index e671bc20a1f34..46e4b28e61d23 100644 --- a/tests/ui/specialization/soft-feature-gate-specialization.rs +++ b/tests/ui/specialization/soft-feature-gate-specialization.rs @@ -1,6 +1,6 @@ // For historical reasons, item modifier `default` doesn't have a proper pre-expansion feature gate. -// We're now at least issuing a *warning* for those that only exist before macro expansion. -// FIXME(#154045): Turn their post-expansion feature gate into a proper pre-expansion one. +// We're now at least issuing a warning for those that only exist before macro expansion. +// FIXME(#154045): Turn this pre-expansion warning into an error and remove the post-expansion gate. // As part of this, move these test cases into `feature-gate-specialization.rs`. // // Moreover, `specialization` implies `min_specialization` similar to the post-expansion gate. From eb5453f7d4c6f9d1578ca2dd850aab9e2b683e3f Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 19 Feb 2026 11:03:14 +0000 Subject: [PATCH 48/61] ty_utils: lower tuples to `ScalableVector` repr Instead of just using regular struct lowering for these types, which results in an incorrect ABI (e.g. returning indirectly), use `BackendRepr::ScalableVector` which will lower to the correct type and be passed in registers. This also enables some simplifications for generating alloca of scalable vectors and greater re-use of `scalable_vector_parts`. A LLVM codegen test demonstrating the changed IR this generates is included in the next commit alongside some intrinsics that make these tuples usable. --- compiler/rustc_abi/src/layout.rs | 21 ++++++--- compiler/rustc_abi/src/lib.rs | 33 ++++++++++++-- compiler/rustc_codegen_gcc/src/builder.rs | 7 +-- compiler/rustc_codegen_llvm/src/builder.rs | 18 +++----- compiler/rustc_codegen_llvm/src/type_of.rs | 44 ++++++++++++++++++- .../rustc_codegen_ssa/src/mir/debuginfo.rs | 4 +- compiler/rustc_codegen_ssa/src/mir/place.rs | 15 +++---- .../rustc_codegen_ssa/src/traits/builder.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 24 +++++++--- compiler/rustc_public/src/abi.rs | 5 +++ .../src/unstable/convert/stable/abi.rs | 25 +++++++++-- compiler/rustc_ty_utils/src/layout.rs | 32 ++++++-------- 12 files changed, 161 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index ca6128b6f1be4..cca1d499088f4 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -10,8 +10,8 @@ use tracing::{debug, trace}; use crate::{ AbiAlign, Align, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, IndexVec, Integer, - LayoutData, Niche, NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, - TargetDataLayout, Variants, WrappingRange, + LayoutData, Niche, NonZeroUsize, NumScalableVectors, Primitive, ReprOptions, Scalar, Size, + StructKind, TagEncoding, TargetDataLayout, Variants, WrappingRange, }; mod coroutine; @@ -204,13 +204,19 @@ impl LayoutCalculator { &self, element: F, count: u64, + number_of_vectors: NumScalableVectors, ) -> LayoutCalculatorResult where FieldIdx: Idx, VariantIdx: Idx, F: AsRef> + fmt::Debug, { - vector_type_layout(SimdVectorKind::Scalable, self.cx.data_layout(), element, count) + vector_type_layout( + SimdVectorKind::Scalable(number_of_vectors), + self.cx.data_layout(), + element, + count, + ) } pub fn simd_type( @@ -1526,7 +1532,7 @@ impl LayoutCalculator { enum SimdVectorKind { /// `#[rustc_scalable_vector]` - Scalable, + Scalable(NumScalableVectors), /// `#[repr(simd, packed)]` PackedFixed, /// `#[repr(simd)]` @@ -1559,9 +1565,10 @@ where let size = elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; let (repr, align) = match kind { - SimdVectorKind::Scalable => { - (BackendRepr::SimdScalableVector { element, count }, dl.llvmlike_vector_align(size)) - } + SimdVectorKind::Scalable(number_of_vectors) => ( + BackendRepr::SimdScalableVector { element, count, number_of_vectors }, + dl.llvmlike_vector_align(size), + ), // Non-power-of-two vectors have padding up to the next power-of-two. // If we're a packed repr, remove the padding while keeping the alignment as close // to a vector as possible. diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 253dff6f8e75c..4f3bd6ef208da 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1702,6 +1702,28 @@ impl AddressSpace { pub const ZERO: Self = AddressSpace(0); } +/// How many scalable vectors are in a `BackendRepr::ScalableVector`? +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +pub struct NumScalableVectors(pub u8); + +impl NumScalableVectors { + /// Returns a `NumScalableVector` for a non-tuple scalable vector (e.g. a single vector). + pub fn for_non_tuple() -> Self { + NumScalableVectors(1) + } + + // Returns `NumScalableVectors` for values of two through eight, which are a valid number of + // fields for a tuple of scalable vectors to have. `1` is a valid value of `NumScalableVectors` + // but not for a tuple which would have a field count. + pub fn from_field_count(count: usize) -> Option { + match count { + 2..8 => Some(NumScalableVectors(count as u8)), + _ => None, + } + } +} + /// The way we represent values to the backend /// /// Previously this was conflated with the "ABI" a type is given, as in the platform-specific ABI. @@ -1720,6 +1742,7 @@ pub enum BackendRepr { SimdScalableVector { element: Scalar, count: u64, + number_of_vectors: NumScalableVectors, }, SimdVector { element: Scalar, @@ -1826,8 +1849,12 @@ impl BackendRepr { BackendRepr::SimdVector { element: element.to_union(), count } } BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true }, - BackendRepr::SimdScalableVector { element, count } => { - BackendRepr::SimdScalableVector { element: element.to_union(), count } + BackendRepr::SimdScalableVector { element, count, number_of_vectors } => { + BackendRepr::SimdScalableVector { + element: element.to_union(), + count, + number_of_vectors, + } } } } @@ -2167,7 +2194,7 @@ impl LayoutData { } /// Returns `true` if the size of the type is only known at runtime. - pub fn is_runtime_sized(&self) -> bool { + pub fn is_scalable_vector(&self) -> bool { matches!(self.backend_repr, BackendRepr::SimdScalableVector { .. }) } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 3eb0fd95284a1..08964113b944a 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -24,7 +24,8 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, + LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; use rustc_span::Span; @@ -943,8 +944,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { .get_address(self.location) } - fn scalable_alloca(&mut self, _elt: u64, _align: Align, _element_ty: Ty<'_>) -> RValue<'gcc> { - todo!() + fn alloca_with_ty(&mut self, ty: TyAndLayout<'tcx>) -> RValue<'gcc> { + self.alloca(ty.layout.size, ty.layout.align.abi) } fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> { diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index f3508c10d1f61..9e59d7aa7c20a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -7,8 +7,7 @@ pub(crate) mod autodiff; pub(crate) mod gpu_offload; use libc::{c_char, c_uint}; -use rustc_abi as abi; -use rustc_abi::{Align, Size, WrappingRange}; +use rustc_abi::{self as abi, Align, Size, WrappingRange}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; @@ -616,21 +615,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value { + fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value { let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); - let llvm_ty = match element_ty.kind() { - ty::Bool => bx.type_i1(), - ty::Int(int_ty) => self.cx.type_int_from_ty(*int_ty), - ty::Uint(uint_ty) => self.cx.type_uint_from_ty(*uint_ty), - ty::Float(float_ty) => self.cx.type_float_from_ty(*float_ty), - _ => unreachable!("scalable vectors can only contain a bool, int, uint or float"), - }; + let scalable_vector_ty = layout.llvm_type(self.cx); unsafe { - let ty = llvm::LLVMScalableVectorType(llvm_ty, elt.try_into().unwrap()); - let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, ty, UNNAMED); - llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); + let alloca = llvm::LLVMBuildAlloca(&bx.llbuilder, scalable_vector_ty, UNNAMED); + llvm::LLVMSetAlignment(alloca, layout.align.abi.bytes() as c_uint); alloca } } diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index e586ed0dd6b07..6d0490e4a1f79 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -24,14 +24,54 @@ fn uncached_llvm_type<'a, 'tcx>( let element = layout.scalar_llvm_type_at(cx, element); return cx.type_vector(element, count); } - BackendRepr::SimdScalableVector { ref element, count } => { + BackendRepr::SimdScalableVector { ref element, count, number_of_vectors } => { let element = if element.is_bool() { cx.type_i1() } else { layout.scalar_llvm_type_at(cx, *element) }; - return cx.type_scalable_vector(element, count); + let vector_type = cx.type_scalable_vector(element, count); + return match number_of_vectors.0 { + 1 => vector_type, + 2 => cx.type_struct(&[vector_type, vector_type], false), + 3 => cx.type_struct(&[vector_type, vector_type, vector_type], false), + 4 => cx.type_struct(&[vector_type, vector_type, vector_type, vector_type], false), + 5 => cx.type_struct( + &[vector_type, vector_type, vector_type, vector_type, vector_type], + false, + ), + 6 => cx.type_struct( + &[vector_type, vector_type, vector_type, vector_type, vector_type, vector_type], + false, + ), + 7 => cx.type_struct( + &[ + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + ], + false, + ), + 8 => cx.type_struct( + &[ + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + vector_type, + ], + false, + ), + _ => bug!("`#[rustc_scalable_vector]` tuple struct with too many fields"), + }; } BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 2f93f688c316d..60ab13dbc6f76 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -438,8 +438,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if operand.layout.ty.is_scalable_vector() && bx.sess().target.arch == rustc_target::spec::Arch::AArch64 { - let (count, element_ty) = - operand.layout.ty.scalable_vector_element_count_and_type(bx.tcx()); + let (count, element_ty, _) = + operand.layout.ty.scalable_vector_parts(bx.tcx()).unwrap(); // i.e. `` when `N != 16` if element_ty.is_bool() && count != 16 { return; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index d62e622b6fed3..53518fd816f31 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -1,3 +1,5 @@ +use std::ops::Deref as _; + use rustc_abi::{ Align, BackendRepr, FieldIdx, FieldsShape, Size, TagEncoding, VariantIdx, Variants, }; @@ -109,8 +111,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, layout: TyAndLayout<'tcx>, ) -> Self { - if layout.is_runtime_sized() { - Self::alloca_runtime_sized(bx, layout) + if layout.deref().is_scalable_vector() { + Self::alloca_scalable(bx, layout) } else { Self::alloca_size(bx, layout.size, layout) } @@ -151,16 +153,11 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { } } - fn alloca_runtime_sized>( + fn alloca_scalable>( bx: &mut Bx, layout: TyAndLayout<'tcx>, ) -> Self { - let (element_count, ty) = layout.ty.scalable_vector_element_count_and_type(bx.tcx()); - PlaceValue::new_sized( - bx.scalable_alloca(element_count as u64, layout.align.abi, ty), - layout.align.abi, - ) - .with_type(layout) + PlaceValue::new_sized(bx.alloca_with_ty(layout), layout.align.abi).with_type(layout) } } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 05e94b8019f49..5092f28a33f7b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -235,7 +235,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value; fn alloca(&mut self, size: Size, align: Align) -> Self::Value; - fn scalable_alloca(&mut self, elt: u64, align: Align, element_ty: Ty<'_>) -> Self::Value; + fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value; fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value; fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 0d047b348d9e1..621ceeffac658 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -7,7 +7,7 @@ use std::debug_assert_matches; use std::ops::{ControlFlow, Range}; use hir::def::{CtorKind, DefKind}; -use rustc_abi::{FIRST_VARIANT, FieldIdx, ScalableElt, VariantIdx}; +use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::LangItem; @@ -1261,17 +1261,27 @@ impl<'tcx> Ty<'tcx> { } } - pub fn scalable_vector_element_count_and_type(self, tcx: TyCtxt<'tcx>) -> (u16, Ty<'tcx>) { + pub fn scalable_vector_parts( + self, + tcx: TyCtxt<'tcx>, + ) -> Option<(u16, Ty<'tcx>, NumScalableVectors)> { let Adt(def, args) = self.kind() else { - bug!("`scalable_vector_size_and_type` called on invalid type") + return None; }; - let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else { - bug!("`scalable_vector_size_and_type` called on non-scalable vector type"); + let (num_vectors, vec_def) = match def.repr().scalable? { + ScalableElt::ElementCount(_) => (NumScalableVectors::for_non_tuple(), *def), + ScalableElt::Container => ( + NumScalableVectors::from_field_count(def.non_enum_variant().fields.len())?, + def.non_enum_variant().fields[FieldIdx::ZERO].ty(tcx, args).ty_adt_def()?, + ), }; - let variant = def.non_enum_variant(); + let Some(ScalableElt::ElementCount(element_count)) = vec_def.repr().scalable else { + return None; + }; + let variant = vec_def.non_enum_variant(); assert_eq!(variant.fields.len(), 1); let field_ty = variant.fields[FieldIdx::ZERO].ty(tcx, args); - (element_count, field_ty) + Some((element_count, field_ty, num_vectors)) } pub fn simd_size_and_type(self, tcx: TyCtxt<'tcx>) -> (u64, Ty<'tcx>) { diff --git a/compiler/rustc_public/src/abi.rs b/compiler/rustc_public/src/abi.rs index 1403e57a7e6a9..4a780d652df81 100644 --- a/compiler/rustc_public/src/abi.rs +++ b/compiler/rustc_public/src/abi.rs @@ -232,6 +232,10 @@ pub enum TagEncoding { }, } +/// How many scalable vectors are in a `ValueAbi::ScalableVector`? +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] +pub struct NumScalableVectors(pub(crate) u8); + /// Describes how values of the type are passed by target ABIs, /// in terms of categories of C types there are ABI rules for. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] @@ -245,6 +249,7 @@ pub enum ValueAbi { ScalableVector { element: Scalar, count: u64, + number_of_vectors: NumScalableVectors, }, Aggregate { /// If true, the size is exact, otherwise it's only a lower bound. diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index b3edc6194c307..d8c4cee7abbe4 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -10,8 +10,9 @@ use rustc_target::callconv; use crate::abi::{ AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, - IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar, - TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape, WrappingRange, + IntegerType, Layout, LayoutShape, NumScalableVectors, PassMode, Primitive, ReprFlags, + ReprOptions, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape, + WrappingRange, }; use crate::compiler_interface::BridgeTys; use crate::target::MachineSize as Size; @@ -249,6 +250,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding { } } +impl<'tcx> Stable<'tcx> for rustc_abi::NumScalableVectors { + type T = NumScalableVectors; + + fn stable<'cx>( + &self, + _tables: &mut Tables<'cx, BridgeTys>, + _cx: &CompilerCtxt<'cx, BridgeTys>, + ) -> Self::T { + NumScalableVectors(self.0) + } +} + impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { type T = ValueAbi; @@ -265,8 +278,12 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { rustc_abi::BackendRepr::SimdVector { element, count } => { ValueAbi::Vector { element: element.stable(tables, cx), count } } - rustc_abi::BackendRepr::SimdScalableVector { element, count } => { - ValueAbi::ScalableVector { element: element.stable(tables, cx), count } + rustc_abi::BackendRepr::SimdScalableVector { element, count, number_of_vectors } => { + ValueAbi::ScalableVector { + element: element.stable(tables, cx), + count, + number_of_vectors: number_of_vectors.stable(tables, cx), + } } rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized }, } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 391f50edf23fa..136df923ee47a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -4,8 +4,8 @@ use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout, - LayoutCalculatorError, LayoutData, Niche, ReprOptions, ScalableElt, Scalar, Size, StructKind, - TagEncoding, VariantIdx, Variants, WrappingRange, + LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, + VariantIdx, Variants, WrappingRange, }; use rustc_hashes::Hash64; use rustc_hir as hir; @@ -572,30 +572,26 @@ fn layout_of_uncached<'tcx>( // ```rust (ignore, example) // #[rustc_scalable_vector(3)] // struct svuint32_t(u32); + // + // #[rustc_scalable_vector] + // struct svuint32x2_t(svuint32_t, svuint32_t); // ``` - ty::Adt(def, args) - if matches!(def.repr().scalable, Some(ScalableElt::ElementCount(..))) => - { - let Some(element_ty) = def - .is_struct() - .then(|| &def.variant(FIRST_VARIANT).fields) - .filter(|fields| fields.len() == 1) - .map(|fields| fields[FieldIdx::ZERO].ty(tcx, args)) + ty::Adt(def, _args) if def.repr().scalable() => { + let Some((element_count, element_ty, number_of_vectors)) = + ty.scalable_vector_parts(tcx) else { let guar = tcx .dcx() - .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type"); - return Err(error(cx, LayoutError::ReferencesError(guar))); - }; - let Some(ScalableElt::ElementCount(element_count)) = def.repr().scalable else { - let guar = tcx - .dcx() - .delayed_bug("#[rustc_scalable_vector] was applied to an invalid type"); + .delayed_bug("`#[rustc_scalable_vector]` was applied to an invalid type"); return Err(error(cx, LayoutError::ReferencesError(guar))); }; let element_layout = cx.layout_of(element_ty)?; - map_layout(cx.calc.scalable_vector_type(element_layout, element_count as u64))? + map_layout(cx.calc.scalable_vector_type( + element_layout, + element_count as u64, + number_of_vectors, + ))? } // SIMD vector types. From e3d70b6f758b1377fbff21becfdb51a597c27d18 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 19 Feb 2026 11:03:14 +0000 Subject: [PATCH 49/61] cg_llvm: `sve_tuple_{create,get,set}` intrinsics Clang changed to representing tuples of scalable vectors as structs rather than as wide vectors (that is, scalable vector types where the `N` part of the `` type was multiplied by the number of vectors). rustc mirrored this in the initial implementation of scalable vectors. Earlier versions of our patches used the wide vector representation and our intrinsic patches used the legacy `llvm.aarch64.sve.tuple.{create,get,set}{2,3,4}` intrinsics for creating these tuples/getting/setting the vectors, which were only supported due to LLVM's `AutoUpgrade` pass converting these intrinsics into `llvm.vector.insert`. `AutoUpgrade` only supports these legacy intrinsics with the wide vector representation. With the current struct representation, Clang has special handling in codegen for generating `insertvalue`/`extractvalue` instructions for these operations, which must be replicated by rustc's codegen for our intrinsics to use. This patch implements new intrinsics in `core::intrinsics::scalable` (mirroring the structure of `core::intrinsics::simd`) which rustc lowers to the appropriate `insertvalue`/`extractvalue` instructions. --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 112 +++++++++++++++++- .../rustc_hir_analysis/src/check/intrinsic.rs | 6 + compiler/rustc_span/src/symbol.rs | 5 + .../src/intrinsics/{simd.rs => simd/mod.rs} | 2 + library/core/src/intrinsics/simd/scalable.rs | 71 +++++++++++ .../scalable-vectors/tuple-intrinsics.rs | 100 ++++++++++++++++ .../simd/masked-load-store-check-fail.stderr | 4 +- triagebot.toml | 2 +- 8 files changed, 298 insertions(+), 4 deletions(-) rename library/core/src/intrinsics/{simd.rs => simd/mod.rs} (99%) create mode 100644 library/core/src/intrinsics/simd/scalable.rs create mode 100644 tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 39bf4c10dab18..ad2c23c99820b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -3,7 +3,8 @@ use std::ffi::c_uint; use std::{assert_matches, ptr}; use rustc_abi::{ - Align, BackendRepr, ExternAbi, Float, HasDataLayout, Primitive, Size, WrappingRange, + Align, BackendRepr, ExternAbi, Float, HasDataLayout, NumScalableVectors, Primitive, Size, + WrappingRange, }; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; @@ -605,6 +606,115 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.pointercast(val, self.type_ptr()) } + sym::sve_tuple_create2 => { + assert_matches!( + self.layout_of(fn_args.type_at(0)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(1), + .. + } + ); + let tuple_ty = self.layout_of(fn_args.type_at(1)); + assert_matches!( + tuple_ty.backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(2), + .. + } + ); + let ret = self.const_poison(self.backend_type(tuple_ty)); + let ret = self.insert_value(ret, args[0].immediate(), 0); + self.insert_value(ret, args[1].immediate(), 1) + } + + sym::sve_tuple_create3 => { + assert_matches!( + self.layout_of(fn_args.type_at(0)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(1), + .. + } + ); + let tuple_ty = self.layout_of(fn_args.type_at(1)); + assert_matches!( + tuple_ty.backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(3), + .. + } + ); + let ret = self.const_poison(self.backend_type(tuple_ty)); + let ret = self.insert_value(ret, args[0].immediate(), 0); + let ret = self.insert_value(ret, args[1].immediate(), 1); + self.insert_value(ret, args[2].immediate(), 2) + } + + sym::sve_tuple_create4 => { + assert_matches!( + self.layout_of(fn_args.type_at(0)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(1), + .. + } + ); + let tuple_ty = self.layout_of(fn_args.type_at(1)); + assert_matches!( + tuple_ty.backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(4), + .. + } + ); + let ret = self.const_poison(self.backend_type(tuple_ty)); + let ret = self.insert_value(ret, args[0].immediate(), 0); + let ret = self.insert_value(ret, args[1].immediate(), 1); + let ret = self.insert_value(ret, args[2].immediate(), 2); + self.insert_value(ret, args[3].immediate(), 3) + } + + sym::sve_tuple_get => { + assert_matches!( + self.layout_of(fn_args.type_at(0)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8), + .. + } + ); + assert_matches!( + self.layout_of(fn_args.type_at(1)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(1), + .. + } + ); + self.extract_value( + args[0].immediate(), + fn_args.const_at(2).to_leaf().to_i32() as u64, + ) + } + + sym::sve_tuple_set => { + assert_matches!( + self.layout_of(fn_args.type_at(0)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(2 | 3 | 4 | 5 | 6 | 7 | 8), + .. + } + ); + assert_matches!( + self.layout_of(fn_args.type_at(1)).backend_repr, + BackendRepr::SimdScalableVector { + number_of_vectors: NumScalableVectors(1), + .. + } + ); + self.insert_value( + args[0].immediate(), + args[1].immediate(), + fn_args.const_at(2).to_leaf().to_i32() as u64, + ) + } + _ if name.as_str().starts_with("simd_") => { // Unpack non-power-of-2 #[repr(packed, simd)] arguments. // This gives them the expected layout of a regular #[repr(simd)] vector. diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index b1dc593331c6c..ca57921089fae 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -783,6 +783,12 @@ pub(crate) fn check_intrinsic_type( sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)), sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)), + sym::sve_tuple_create2 => (2, 0, vec![param(0), param(0)], param(1)), + sym::sve_tuple_create3 => (2, 0, vec![param(0), param(0), param(0)], param(1)), + sym::sve_tuple_create4 => (2, 0, vec![param(0), param(0), param(0), param(0)], param(1)), + sym::sve_tuple_get => (2, 1, vec![param(0)], param(1)), + sym::sve_tuple_set => (2, 1, vec![param(0), param(1)], param(0)), + sym::atomic_cxchg | sym::atomic_cxchgweak => ( 1, 2, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 30bf8dd7c2206..e0bdd60f5971b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1979,6 +1979,11 @@ symbols! { suggestion, super_let, supertrait_item_shadowing, + sve_tuple_create2, + sve_tuple_create3, + sve_tuple_create4, + sve_tuple_get, + sve_tuple_set, sym, sync, synthetic, diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd/mod.rs similarity index 99% rename from library/core/src/intrinsics/simd.rs rename to library/core/src/intrinsics/simd/mod.rs index ae86690dc418d..084d8a3f1f247 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd/mod.rs @@ -2,6 +2,8 @@ //! //! In this module, a "vector" is any `repr(simd)` type. +pub mod scalable; + use crate::marker::ConstParamTy; /// Inserts an element into a vector, returning the updated vector. diff --git a/library/core/src/intrinsics/simd/scalable.rs b/library/core/src/intrinsics/simd/scalable.rs new file mode 100644 index 0000000000000..5e7b64f18e533 --- /dev/null +++ b/library/core/src/intrinsics/simd/scalable.rs @@ -0,0 +1,71 @@ +//! Scalable vector compiler intrinsics. +//! +//! In this module, a "vector" is any `#[rustc_scalable_vector]`-annotated type. + +/// Create a tuple of two vectors. +/// +/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a +/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of +/// type `SVec`. +/// +/// Corresponds to Clang's `__builtin_sve_svcreate2*` builtins. +#[cfg(target_arch = "aarch64")] +#[rustc_nounwind] +#[rustc_intrinsic] +pub unsafe fn sve_tuple_create2(x0: SVec, x1: SVec) -> SVecTup; + +/// Create a tuple of three vectors. +/// +/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a +/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of +/// type `SVec`. +/// +/// Corresponds to Clang's `__builtin_sve_svcreate3*` builtins. +#[cfg(target_arch = "aarch64")] +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn sve_tuple_create3(x0: SVec, x1: SVec, x2: SVec) -> SVecTup; + +/// Create a tuple of four vectors. +/// +/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a +/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of +/// type `SVec`. +/// +/// Corresponds to Clang's `__builtin_sve_svcreate4*` builtins. +#[cfg(target_arch = "aarch64")] +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn sve_tuple_create4(x0: SVec, x1: SVec, x2: SVec, x3: SVec) -> SVecTup; + +/// Get one vector from a tuple of vectors. +/// +/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a +/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of +/// type `SVec`. +/// +/// Corresponds to Clang's `__builtin_sve_svget*` builtins. +/// +/// # Safety +/// +/// `IDX` must be in-bounds of the tuple. +#[cfg(target_arch = "aarch64")] +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn sve_tuple_get(tuple: SVecTup) -> SVec; + +/// Change one vector in a tuple of vectors. +/// +/// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a +/// scalable vector (`#[rustc_scalable_vector(N)]`). `SVecTup` must be a tuple of vectors of +/// type `SVec`. +/// +/// Corresponds to Clang's `__builtin_sve_svset*` builtins. +/// +/// # Safety +/// +/// `IDX` must be in-bounds of the tuple. +#[cfg(target_arch = "aarch64")] +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn sve_tuple_set(tuple: SVecTup, x: SVec) -> SVecTup; diff --git a/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs b/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs new file mode 100644 index 0000000000000..e19fc40cb9d67 --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/tuple-intrinsics.rs @@ -0,0 +1,100 @@ +//@ build-pass +//@ only-aarch64 +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features)] +#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)] + +// Tests that tuples of scalable vectors are passed as immediates and that the intrinsics for +// creating/getting/setting tuples of scalable vectors generate the correct assembly + +#[derive(Copy, Clone)] +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +pub struct svfloat32_t(f32); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +pub struct svfloat32x2_t(svfloat32_t, svfloat32_t); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +pub struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +pub struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t); + +#[inline(never)] +#[target_feature(enable = "sve")] +pub fn svdup_n_f32(op: f32) -> svfloat32_t { + extern "C" { + #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.sve.dup.x.nxv4f32")] + fn _svdup_n_f32(op: f32) -> svfloat32_t; + } + unsafe { _svdup_n_f32(op) } +} + +// CHECK: define { , } @svcreate2_f32( %x0, %x1) +#[no_mangle] +#[target_feature(enable = "sve")] +pub fn svcreate2_f32(x0: svfloat32_t, x1: svfloat32_t) -> svfloat32x2_t { + // CHECK: %1 = insertvalue { , } poison, %x0, 0 + // CHECK-NEXT: %2 = insertvalue { , } %1, %x1, 1 + unsafe { std::intrinsics::simd::scalable::sve_tuple_create2(x0, x1) } +} + +// CHECK: define { , , } @svcreate3_f32( %x0, %x1, %x2) +#[no_mangle] +#[target_feature(enable = "sve")] +pub fn svcreate3_f32(x0: svfloat32_t, x1: svfloat32_t, x2: svfloat32_t) -> svfloat32x3_t { + // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate3_f32 + // CHECK: %1 = insertvalue { , , } poison, %x0, 0 + // CHECK-NEXT: %2 = insertvalue { , , } %1, %x1, 1 + // CHECK-NEXT: %3 = insertvalue { , , } %2, %x2, 2 + unsafe { std::intrinsics::simd::scalable::sve_tuple_create3(x0, x1, x2) } +} + +// CHECK: define { , , , } @svcreate4_f32( %x0, %x1, %x2, %x3) +#[no_mangle] +#[target_feature(enable = "sve")] +pub fn svcreate4_f32( + x0: svfloat32_t, + x1: svfloat32_t, + x2: svfloat32_t, + x3: svfloat32_t, +) -> svfloat32x4_t { + // CHECK-LABEL: @_RNvCsk3YxfLN8zWY_6tuples13svcreate4_f32 + // CHECK: %1 = insertvalue { , , , } poison, %x0, 0 + // CHECK-NEXT: %2 = insertvalue { , , , } %1, %x1, 1 + // CHECK-NEXT: %3 = insertvalue { , , , } %2, %x2, 2 + // CHECK-NEXT: %4 = insertvalue { , , , } %3, %x3, 3 + unsafe { std::intrinsics::simd::scalable::sve_tuple_create4(x0, x1, x2, x3) } +} + +// CHECK: define @svget2_f32({ , } %tup) +#[no_mangle] +#[target_feature(enable = "sve")] +pub fn svget2_f32(tup: svfloat32x2_t) -> svfloat32_t { + // CHECK: %1 = extractvalue { , } %tup, 0 + unsafe { std::intrinsics::simd::scalable::sve_tuple_get::<_, _, { IDX }>(tup) } +} + +// CHECK: define { , } @svset2_f32({ , } %tup, %x) +#[no_mangle] +#[target_feature(enable = "sve")] +pub fn svset2_f32(tup: svfloat32x2_t, x: svfloat32_t) -> svfloat32x2_t { + // CHECK: %1 = insertvalue { , } %tup, %x, 0 + unsafe { std::intrinsics::simd::scalable::sve_tuple_set::<_, _, { IDX }>(tup, x) } +} + +// This function exists only so there are calls to the generic functions +#[target_feature(enable = "sve")] +pub fn test() { + let x = svdup_n_f32(2f32); + let tup = svcreate2_f32(x, x); + let x = svget2_f32::<0>(tup); + let tup = svset2_f32::<0>(tup, x); +} diff --git a/tests/ui/simd/masked-load-store-check-fail.stderr b/tests/ui/simd/masked-load-store-check-fail.stderr index 4e63d04a3b158..037855c8ec9ca 100644 --- a/tests/ui/simd/masked-load-store-check-fail.stderr +++ b/tests/ui/simd/masked-load-store-check-fail.stderr @@ -21,7 +21,7 @@ LL | | Simd::([9; 4]), LL | | ); | |_________^ note: function defined here - --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL error[E0308]: mismatched types --> $DIR/masked-load-store-check-fail.rs:25:13 @@ -46,7 +46,7 @@ LL | | default, LL | | ); | |_________^ note: function defined here - --> $SRC_DIR/core/src/intrinsics/simd.rs:LL:COL + --> $SRC_DIR/core/src/intrinsics/simd/mod.rs:LL:COL error: aborting due to 2 previous errors diff --git a/triagebot.toml b/triagebot.toml index f99d700310dfe..719fe2a75c82b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1077,7 +1077,7 @@ cc = ["@Amanieu", "@folkertdev", "@sayantn"] message = "Some changes occurred in `std_detect`" cc = ["@Amanieu", "@folkertdev", "@sayantn"] -[mentions."library/core/src/intrinsics/simd.rs"] +[mentions."library/core/src/intrinsics/simd/mod.rs"] message = """ Some changes occurred to the platform-builtins intrinsics. Make sure the LLVM backend as well as portable-simd gets adapted for the changes. From 8cccf30094e16ca53f04f417702e987518717999 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 26 Feb 2026 15:35:20 +0000 Subject: [PATCH 50/61] cg_llvm/debuginfo: scalable vectors Generate debuginfo for scalable vectors, following the structure that Clang generates for scalable vectors. --- compiler/rustc_codegen_gcc/src/common.rs | 4 + compiler/rustc_codegen_llvm/src/common.rs | 4 + .../src/debuginfo/dwarf_const.rs | 8 + .../src/debuginfo/metadata.rs | 120 +++++++++++++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 17 ++ .../rustc_codegen_ssa/src/traits/consts.rs | 1 + .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 36 ++++- .../scalable-vectors/debuginfo-tuples-x2.rs | 149 ++++++++++++++++++ .../scalable-vectors/debuginfo-tuples-x3.rs | 149 ++++++++++++++++++ .../scalable-vectors/debuginfo-tuples-x4.rs | 149 ++++++++++++++++++ .../scalable-vectors/debuginfo.rs | 123 +++++++++++++++ 11 files changed, 754 insertions(+), 6 deletions(-) create mode 100644 tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs create mode 100644 tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs create mode 100644 tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs create mode 100644 tests/codegen-llvm/scalable-vectors/debuginfo.rs diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 9e548ac0a8b01..dd0064d34bc4a 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -145,6 +145,10 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { self.const_int(self.type_i32(), i as i64) } + fn const_i64(&self, i: i64) -> RValue<'gcc> { + self.const_int(self.type_i64(), i) + } + fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> { self.gcc_int(typ, int) } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a134e97cc8915..dadf8e9e7d5fa 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -159,6 +159,10 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { self.const_int(self.type_i32(), i as i64) } + fn const_i64(&self, i: i64) -> &'ll Value { + self.const_int(self.type_i64(), i as i64) + } + fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value { debug_assert!( self.type_kind(t) == TypeKind::Integer, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs index 52d04625749b9..1172660af4a29 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs @@ -35,6 +35,14 @@ declare_constant!(DW_OP_plus_uconst: u64); /// Double-checked by a static assertion in `RustWrapper.cpp`. #[allow(non_upper_case_globals)] pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000; +#[allow(non_upper_case_globals)] +pub(crate) const DW_OP_constu: u64 = 0x10; +#[allow(non_upper_case_globals)] +pub(crate) const DW_OP_minus: u64 = 0x1c; +#[allow(non_upper_case_globals)] +pub(crate) const DW_OP_mul: u64 = 0x1e; +#[allow(non_upper_case_globals)] +pub(crate) const DW_OP_bregx: u64 = 0x92; // It describes the actual value of a source variable which might not exist in registers or in memory. #[allow(non_upper_case_globals)] pub(crate) const DW_OP_stack_value: u64 = 0x9f; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 04c0b6953290c..25307823b37c7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use std::{iter, ptr}; use libc::{c_longlong, c_uint}; -use rustc_abi::{Align, Size}; +use rustc_abi::{Align, Layout, NumScalableVectors, Size}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; @@ -16,12 +16,12 @@ use rustc_middle::ty::layout::{ HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA, }; use rustc_middle::ty::{ - self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, + self, AdtDef, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility, }; use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene}; use rustc_symbol_mangling::typeid_for_trait_ref; -use rustc_target::spec::DebuginfoKind; +use rustc_target::spec::{Arch, DebuginfoKind}; use smallvec::smallvec; use tracing::{debug, instrument}; @@ -33,7 +33,7 @@ use super::type_names::{compute_debuginfo_type_name, compute_debuginfo_vtable_na use super::utils::{DIB, debug_context, get_namespace_for_item, is_node_local_to_unit}; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::build_type_with_children; -use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind}; +use crate::debuginfo::utils::{WidePtrKind, create_DIArray, wide_pointer_kind}; use crate::debuginfo::{DIBuilderExt, dwarf_const}; use crate::llvm::debuginfo::{ DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, @@ -1039,6 +1039,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( span: Span, ) -> DINodeCreationResult<'ll> { let struct_type = unique_type_id.expect_ty(); + let ty::Adt(adt_def, _) = struct_type.kind() else { bug!("build_struct_type_di_node() called with non-struct-type: {:?}", struct_type); }; @@ -1051,6 +1052,21 @@ fn build_struct_type_di_node<'ll, 'tcx>( } else { None }; + let name = compute_debuginfo_type_name(cx.tcx, struct_type, false); + + if struct_type.is_scalable_vector() { + let parts = struct_type.scalable_vector_parts(cx.tcx).unwrap(); + return build_scalable_vector_di_node( + cx, + unique_type_id, + name, + *adt_def, + parts, + struct_type_and_layout.layout, + def_location, + containing_scope, + ); + } type_map::build_type_with_children( cx, @@ -1058,7 +1074,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( cx, Stub::Struct, unique_type_id, - &compute_debuginfo_type_name(cx.tcx, struct_type, false), + &name, def_location, size_and_align_of(struct_type_and_layout), Some(containing_scope), @@ -1101,6 +1117,100 @@ fn build_struct_type_di_node<'ll, 'tcx>( ) } +/// Generate debuginfo for a `#[rustc_scalable_vector]` type. +/// +/// Debuginfo for a scalable vector uses a derived type based on a composite type. The composite +/// type has the `DIFlagVector` flag set and is based on the element type of the scalable vector. +/// The composite type has a subrange from 0 to an expression that calculates the number of +/// elements in the vector. +/// +/// ```text,ignore +/// !1 = !DIDerivedType(tag: DW_TAG_typedef, name: "svint16_t", ..., baseType: !2, ...) +/// !2 = !DICompositeType(tag: DW_TAG_array_type, baseType: !3, ..., flags: DIFlagVector, elements: !4) +/// !3 = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed) +/// !4 = !{!5} +/// !5 = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) +/// ``` +/// +/// See the `CodegenType::CreateType(const BuiltinType *BT)` implementation in Clang for how this +/// is generated for C and C++. +fn build_scalable_vector_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + unique_type_id: UniqueTypeId<'tcx>, + name: String, + adt_def: AdtDef<'tcx>, + (element_count, element_ty, number_of_vectors): (u16, Ty<'tcx>, NumScalableVectors), + layout: Layout<'tcx>, + def_location: Option>, + containing_scope: &'ll DIScope, +) -> DINodeCreationResult<'ll> { + use dwarf_const::{DW_OP_bregx, DW_OP_constu, DW_OP_minus, DW_OP_mul}; + assert!(adt_def.repr().scalable()); + // This logic is specific to AArch64 for the moment, but can be extended for other architectures + // later. + assert_matches!(cx.tcx.sess.target.arch, Arch::AArch64); + + let (file_metadata, line_number) = if let Some(def_location) = def_location { + (def_location.0, def_location.1) + } else { + (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) + }; + + let (bitstride, element_di_node) = if element_ty.is_bool() { + (Some(llvm::LLVMValueAsMetadata(cx.const_i64(1))), type_di_node(cx, cx.tcx.types.u8)) + } else { + (None, type_di_node(cx, element_ty)) + }; + + let number_of_elements: u64 = (element_count as u64) * (number_of_vectors.0 as u64); + let number_of_elements_per_vg = number_of_elements / 2; + let mut expr = smallvec::SmallVec::<[u64; 9]>::new(); + // `($number_of_elements_per_vector_granule * (value_of_register(AArch64::VG) + 0)) - 1` + expr.push(DW_OP_constu); // Push a constant onto the stack + expr.push(number_of_elements_per_vg); + expr.push(DW_OP_bregx); // Push the value of a register + offset on to the stack + expr.push(/* AArch64::VG */ 46u64); + expr.push(0u64); + expr.push(DW_OP_mul); // Multiply top two values on stack + expr.push(DW_OP_constu); // Push a constant onto the stack + expr.push(1u64); + expr.push(DW_OP_minus); // Subtract top two values on stack + + let di_builder = DIB(cx); + let metadata = unsafe { + let upper = llvm::LLVMDIBuilderCreateExpression(di_builder, expr.as_ptr(), expr.len()); + let subrange = llvm::LLVMRustDIGetOrCreateSubrange( + di_builder, + /* CountNode */ None, + llvm::LLVMValueAsMetadata(cx.const_i64(0)), + upper, + /* Stride */ None, + ); + let subscripts = create_DIArray(di_builder, &[Some(subrange)]); + let vector_ty = llvm::LLVMRustDICreateVectorType( + di_builder, + /* Size */ 0, + layout.align.bits() as u32, + element_di_node, + subscripts, + bitstride, + ); + llvm::LLVMDIBuilderCreateTypedef( + di_builder, + vector_ty, + name.as_ptr(), + name.len(), + file_metadata, + line_number, + Some(containing_scope), + layout.align.bits() as u32, + ) + }; + + debug_context(cx).type_map.insert(unique_type_id, metadata); + DINodeCreationResult { di_node: metadata, already_stored_in_typemap: true } +} + //=----------------------------------------------------------------------------- // Tuples //=----------------------------------------------------------------------------- diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7355d11367920..0ad74c9ca43a7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2302,6 +2302,23 @@ unsafe extern "C" { Params: Option<&'a DIArray>, ); + pub(crate) fn LLVMRustDIGetOrCreateSubrange<'a>( + Builder: &DIBuilder<'a>, + CountNode: Option<&'a Metadata>, + LB: &'a Metadata, + UB: &'a Metadata, + Stride: Option<&'a Metadata>, + ) -> &'a Metadata; + + pub(crate) fn LLVMRustDICreateVectorType<'a>( + Builder: &DIBuilder<'a>, + Size: u64, + AlignInBits: u32, + Type: &'a DIType, + Subscripts: &'a DIArray, + BitStride: Option<&'a Metadata>, + ) -> &'a Metadata; + pub(crate) fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>( Location: &'a DILocation, BD: c_uint, diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 4178a9742e268..22784a8868ab5 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -20,6 +20,7 @@ pub trait ConstCodegenMethods: BackendTypes { fn const_i8(&self, i: i8) -> Self::Value; fn const_i16(&self, i: i16) -> Self::Value; fn const_i32(&self, i: i32) -> Self::Value; + fn const_i64(&self, i: i64) -> Self::Value; fn const_int(&self, t: Self::Type, i: i64) -> Self::Value; fn const_u8(&self, i: u8) -> Self::Value; fn const_u32(&self, i: u32) -> Self::Value; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 63ff0b2a0a0df..f0cda4493c851 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -70,6 +70,10 @@ using namespace llvm::object; // This opcode is an LLVM detail that could hypothetically change (?), so // verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM. static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000); +static_assert(dwarf::DW_OP_constu == 0x10); +static_assert(dwarf::DW_OP_minus == 0x1c); +static_assert(dwarf::DW_OP_mul == 0x1e); +static_assert(dwarf::DW_OP_bregx == 0x92); static_assert(dwarf::DW_OP_stack_value == 0x9f); static LLVM_THREAD_LOCAL char *LastError; @@ -731,7 +735,7 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints, } template DIT *unwrapDIPtr(LLVMMetadataRef Ref) { - return (DIT *)(Ref ? unwrap(Ref) : nullptr); + return (DIT *)(Ref ? unwrap(Ref) : nullptr); } #define DIDescriptor DIScope @@ -1207,6 +1211,36 @@ extern "C" void LLVMRustDICompositeTypeReplaceArrays( DINodeArray(unwrap(Params))); } +// LLVM's C FFI bindings don't expose the overload of `GetOrCreateSubrange` +// which takes a metadata node as the upper bound. +extern "C" LLVMMetadataRef +LLVMRustDIGetOrCreateSubrange(LLVMDIBuilderRef Builder, + LLVMMetadataRef CountNode, LLVMMetadataRef LB, + LLVMMetadataRef UB, LLVMMetadataRef Stride) { + return wrap(unwrap(Builder)->getOrCreateSubrange( + unwrapDI(CountNode), unwrapDI(LB), + unwrapDI(UB), unwrapDI(Stride))); +} + +// LLVM's CI FFI bindings don't expose the `BitStride` parameter of +// `createVectorType`. +extern "C" LLVMMetadataRef +LLVMRustDICreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size, + uint32_t AlignInBits, LLVMMetadataRef Type, + LLVMMetadataRef Subscripts, + LLVMMetadataRef BitStride) { +#if LLVM_VERSION_GE(22, 0) + return wrap(unwrap(Builder)->createVectorType( + Size, AlignInBits, unwrapDI(Type), + DINodeArray(unwrapDI(Subscripts)), + unwrapDI(BitStride))); +#else + return wrap(unwrap(Builder)->createVectorType( + Size, AlignInBits, unwrapDI(Type), + DINodeArray(unwrapDI(Subscripts)))); +#endif +} + extern "C" LLVMMetadataRef LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location, unsigned BD) { diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs new file mode 100644 index 0000000000000..1aaba621d0e10 --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x2.rs @@ -0,0 +1,149 @@ +//@ only-aarch64 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 + +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features)] +#![feature(rustc_attrs)] + +// Test that we generate the correct debuginfo for scalable vector types. + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svint8_t(i8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint8x2_t(svint8_t, svint8_t); + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svuint8_t(u8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint8x2_t(svuint8_t, svuint8_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svint16_t(i16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint16x2_t(svint16_t, svint16_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svuint16_t(u16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint16x2_t(svuint16_t, svuint16_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svint32_t(i32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint32x2_t(svint32_t, svint32_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svuint32_t(u32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint32x2_t(svuint32_t, svuint32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svint64_t(i64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint64x2_t(svint64_t, svint64_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svuint64_t(u64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint64x2_t(svuint64_t, svuint64_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svfloat32_t(f32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat32x2_t(svfloat32_t, svfloat32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svfloat64_t(f64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat64x2_t(svfloat64_t, svfloat64_t); + +#[target_feature(enable = "sve")] +pub fn locals() { + // CHECK-DAG: name: "svint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2:[0-9]+]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS8x2]] = !{![[REALELTS8x2:[0-9]+]]} + // CHECK-DAG: ![[REALELTS8x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 16, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s8: svint8x2_t; + + // CHECK-DAG: name: "svuint8x2_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x2]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) + let u8: svuint8x2_t; + + // CHECK-DAG: name: "svint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2:[0-9]+]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS16x2]] = !{![[REALELTS16x2:[0-9]+]]} + // CHECK-DAG: ![[REALELTS16x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s16: svint16x2_t; + + // CHECK-DAG: name: "svuint16x2_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x2]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) + let u16: svuint16x2_t; + + // CHECK-DAG: name: "svint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2:[0-9]+]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS32x2]] = !{![[REALELTS32x2:[0-9]+]]} + // CHECK-DAG: ![[REALELTS32x2]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s32: svint32x2_t; + + // CHECK-DAG: name: "svuint32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) + let u32: svuint32x2_t; + + // CHECK-DAG: name: "svint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64:[0-9]+]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS1x2_64]] = !{![[REALELTS1x2_64:[0-9]+]]} + // CHECK-DAG: ![[REALELTS1x2_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s64: svint64x2_t; + + // CHECK-DAG: name: "svuint64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned) + let u64: svuint64x2_t; + + // CHECK: name: "svfloat32x2_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x2]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float) + let f32: svfloat32x2_t; + + // CHECK: name: "svfloat64x2_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x2_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float) + let f64: svfloat64x2_t; +} diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs new file mode 100644 index 0000000000000..b19051e2c743d --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x3.rs @@ -0,0 +1,149 @@ +//@ only-aarch64 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 + +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features)] +#![feature(rustc_attrs)] + +// Test that we generate the correct debuginfo for scalable vector types. + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svint8_t(i8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint8x3_t(svint8_t, svint8_t, svint8_t); + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svuint8_t(u8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint8x3_t(svuint8_t, svuint8_t, svuint8_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svint16_t(i16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint16x3_t(svint16_t, svint16_t, svint16_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svuint16_t(u16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint16x3_t(svuint16_t, svuint16_t, svuint16_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svint32_t(i32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint32x3_t(svint32_t, svint32_t, svint32_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svuint32_t(u32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint32x3_t(svuint32_t, svuint32_t, svuint32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svint64_t(i64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint64x3_t(svint64_t, svint64_t, svint64_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svuint64_t(u64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint64x3_t(svuint64_t, svuint64_t, svuint64_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svfloat32_t(f32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat32x3_t(svfloat32_t, svfloat32_t, svfloat32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svfloat64_t(f64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat64x3_t(svfloat64_t, svfloat64_t, svfloat64_t); + +#[target_feature(enable = "sve")] +pub fn locals() { + // CHECK-DAG: name: "svint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3:[0-9]+]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS8x3]] = !{![[REALELTS8x3:[0-9]+]]} + // CHECK-DAG: ![[REALELTS8x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 24, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s8: svint8x3_t; + + // CHECK-DAG: name: "svuint8x3_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x3]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) + let u8: svuint8x3_t; + + // CHECK-DAG: name: "svint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3:[0-9]+]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS16x3]] = !{![[REALELTS16x3:[0-9]+]]} + // CHECK-DAG: ![[REALELTS16x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 12, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s16: svint16x3_t; + + // CHECK-DAG: name: "svuint16x3_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x3]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) + let u16: svuint16x3_t; + + // CHECK-DAG: name: "svint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3:[0-9]+]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS32x3]] = !{![[REALELTS32x3:[0-9]+]]} + // CHECK-DAG: ![[REALELTS32x3]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 6, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s32: svint32x3_t; + + // CHECK-DAG: name: "svuint32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) + let u32: svuint32x3_t; + + // CHECK-DAG: name: "svint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64:[0-9]+]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS1x3_64]] = !{![[REALELTS1x3_64:[0-9]+]]} + // CHECK-DAG: ![[REALELTS1x3_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 3, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s64: svint64x3_t; + + // CHECK-DAG: name: "svuint64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned) + let u64: svuint64x3_t; + + // CHECK: name: "svfloat32x3_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x3]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float) + let f32: svfloat32x3_t; + + // CHECK: name: "svfloat64x3_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x3_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float) + let f64: svfloat64x3_t; +} diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs new file mode 100644 index 0000000000000..911af76f42ebb --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/debuginfo-tuples-x4.rs @@ -0,0 +1,149 @@ +//@ only-aarch64 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 + +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features)] +#![feature(rustc_attrs)] + +// Test that we generate the correct debuginfo for scalable vector types. + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svint8_t(i8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint8x4_t(svint8_t, svint8_t, svint8_t, svint8_t); + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svuint8_t(u8); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint8x4_t(svuint8_t, svuint8_t, svuint8_t, svuint8_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svint16_t(i16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint16x4_t(svint16_t, svint16_t, svint16_t, svint16_t); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svuint16_t(u16); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint16x4_t(svuint16_t, svuint16_t, svuint16_t, svuint16_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svint32_t(i32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint32x4_t(svint32_t, svint32_t, svint32_t, svint32_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svuint32_t(u32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint32x4_t(svuint32_t, svuint32_t, svuint32_t, svuint32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svint64_t(i64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svint64x4_t(svint64_t, svint64_t, svint64_t, svint64_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svuint64_t(u64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svuint64x4_t(svuint64_t, svuint64_t, svuint64_t, svuint64_t); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svfloat32_t(f32); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat32x4_t(svfloat32_t, svfloat32_t, svfloat32_t, svfloat32_t); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svfloat64_t(f64); + +#[rustc_scalable_vector] +#[allow(non_camel_case_types)] +struct svfloat64x4_t(svfloat64_t, svfloat64_t, svfloat64_t, svfloat64_t); + +#[target_feature(enable = "sve")] +pub fn locals() { + // CHECK-DAG: name: "svint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4:[0-9]+]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS8x4]] = !{![[REALELTS8x4:[0-9]+]]} + // CHECK-DAG: ![[REALELTS8x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 32, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s8: svint8x4_t; + + // CHECK-DAG: name: "svuint8x4_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8x4]]) + // CHECK-DAG: ![[ELTTY8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) + let u8: svuint8x4_t; + + // CHECK-DAG: name: "svint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4:[0-9]+]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS16x4]] = !{![[REALELTS16x4:[0-9]+]]} + // CHECK-DAG: ![[REALELTS16x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 16, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s16: svint16x4_t; + + // CHECK-DAG: name: "svuint16x4_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16x4]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) + let u16: svuint16x4_t; + + // CHECK-DAG: name: "svint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4:[0-9]+]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS32x4]] = !{![[REALELTS32x4:[0-9]+]]} + // CHECK-DAG: ![[REALELTS32x4]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s32: svint32x4_t; + + // CHECK-DAG: name: "svuint32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) + let u32: svuint32x4_t; + + // CHECK-DAG: name: "svint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64:[0-9]+]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS1x4_64]] = !{![[REALELTS1x4_64:[0-9]+]]} + // CHECK-DAG: ![[REALELTS1x4_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s64: svint64x4_t; + + // CHECK-DAG: name: "svuint64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned) + let u64: svuint64x4_t; + + // CHECK: name: "svfloat32x4_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32x4]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float) + let f32: svfloat32x4_t; + + // CHECK: name: "svfloat64x4_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS1x4_64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float) + let f64: svfloat64x4_t; +} diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo.rs b/tests/codegen-llvm/scalable-vectors/debuginfo.rs new file mode 100644 index 0000000000000..f4b34a5e1e7eb --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/debuginfo.rs @@ -0,0 +1,123 @@ +// ignore-tidy-linelength +//@ only-aarch64 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 +//@ revisions: POST-LLVM-22 PRE-LLVM-22 +//@ [PRE-LLVM-22] max-llvm-major-version: 21 +//@ [POST-LLVM-22] min-llvm-version: 22 + +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features)] +#![feature(rustc_attrs)] + +// Test that we generate the correct debuginfo for scalable vector types. + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svbool_t(bool); + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svint8_t(i8); + +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +struct svuint8_t(u8); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svint16_t(i16); + +#[rustc_scalable_vector(8)] +#[allow(non_camel_case_types)] +struct svuint16_t(u16); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svint32_t(i32); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svuint32_t(u32); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svint64_t(i64); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svuint64_t(u64); + +#[rustc_scalable_vector(4)] +#[allow(non_camel_case_types)] +struct svfloat32_t(f32); + +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +struct svfloat64_t(f64); + +#[target_feature(enable = "sve")] +pub fn locals() { + // CHECK-DAG: name: "svbool_t",{{.*}}, baseType: ![[CT1:[0-9]+]] + // PRE-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]]) + // POST-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]], bitStride: i64 1) + // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) + // CHECK-DAG: ![[ELTS8]] = !{![[REALELTS8:[0-9]+]]} + // CHECK-DAG: ![[REALELTS8]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let b8: svbool_t; + + // CHECK-DAG: name: "svint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYS8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]]) + // CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed) + let s8: svint8_t; + + // PRE-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT1:[0-9]+]] + // POST-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // POST-LLVM-22-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8]]) + let u8: svuint8_t; + + // CHECK-DAG: name: "svint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16:[0-9]+]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "i16", size: 16, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS16]] = !{![[REALELTS16:[0-9]+]]} + // CHECK-DAG: ![[REALELTS16]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 4, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s16: svint16_t; + + // CHECK-DAG: name: "svuint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]] + // CHECK-DAG: ![[CT16]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY16:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS16]]) + // CHECK-DAG: ![[ELTTY16]] = !DIBasicType(name: "u16", size: 16, encoding: DW_ATE_unsigned) + let u16: svuint16_t; + + // CHECK-DAG: name: "svint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32:[0-9]+]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS32]] = !{![[REALELTS32:[0-9]+]]} + // CHECK-DAG: ![[REALELTS32]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 2, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s32: svint32_t; + + // CHECK-DAG: name: "svuint32_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) + let u32: svuint32_t; + + // CHECK-DAG: name: "svint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64:[0-9]+]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "i64", size: 64, encoding: DW_ATE_signed) + // CHECK-DAG: ![[ELTS64]] = !{![[REALELTS64:[0-9]+]]} + // CHECK-DAG: ![[REALELTS64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 1, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) + let s64: svint64_t; + + // CHECK-DAG: name: "svuint64_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned) + let u64: svuint64_t; + + // CHECK: name: "svfloat32_t",{{.*}}, baseType: ![[CT32:[0-9]+]] + // CHECK-DAG: ![[CT32]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY32:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS32]]) + // CHECK-DAG: ![[ELTTY32]] = !DIBasicType(name: "f32", size: 32, encoding: DW_ATE_float) + let f32: svfloat32_t; + + // CHECK: name: "svfloat64_t",{{.*}}, baseType: ![[CT64:[0-9]+]] + // CHECK-DAG: ![[CT64]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTY64:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS64]]) + // CHECK-DAG: ![[ELTTY64]] = !DIBasicType(name: "f64", size: 64, encoding: DW_ATE_float) + let f64: svfloat64_t; +} From 73fdeed0a1dfabb64f37632c1e61b0a323fe85fa Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 28 Feb 2026 16:48:59 +0000 Subject: [PATCH 51/61] cg_llvm: `sve_cast` intrinsic Abstract over the existing `simd_cast` intrinsic to implement a new `sve_cast` intrinsic - this is better than allowing scalable vectors to be used with all of the generic `simd_*` intrinsics. --- .../src/debuginfo/metadata.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 203 ++++++++++-------- .../rustc_hir_analysis/src/check/intrinsic.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/simd/scalable.rs | 22 ++ tests/ui/scalable-vectors/cast-intrinsic.rs | 65 ++++++ 6 files changed, 204 insertions(+), 90 deletions(-) create mode 100644 tests/ui/scalable-vectors/cast-intrinsic.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 25307823b37c7..c91d3ec63a028 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -3,7 +3,7 @@ use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; use std::path::PathBuf; use std::sync::Arc; -use std::{iter, ptr}; +use std::{assert_matches, iter, ptr}; use libc::{c_longlong, c_uint}; use rustc_abi::{Align, Layout, NumScalableVectors, Size}; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index ad2c23c99820b..3e600914d6f42 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -606,6 +606,27 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { self.pointercast(val, self.type_ptr()) } + sym::sve_cast => { + let Some((in_cnt, in_elem, in_num_vecs)) = + args[0].layout.ty.scalable_vector_parts(self.cx.tcx) + else { + bug!("input parameter to `sve_cast` was not scalable vector"); + }; + let out_layout = self.layout_of(fn_args.type_at(1)); + let Some((out_cnt, out_elem, out_num_vecs)) = + out_layout.ty.scalable_vector_parts(self.cx.tcx) + else { + bug!("output parameter to `sve_cast` was not scalable vector"); + }; + assert_eq!(in_cnt, out_cnt); + assert_eq!(in_num_vecs, out_num_vecs); + let out_llty = self.backend_type(out_layout); + match simd_cast(self, sym::simd_cast, args, out_llty, in_elem, out_elem) { + Some(val) => val, + _ => bug!("could not cast scalable vectors"), + } + } + sym::sve_tuple_create2 => { assert_matches!( self.layout_of(fn_args.type_at(0)).backend_repr, @@ -2772,96 +2793,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>( out_len } ); - // casting cares about nominal type, not just structural type - if in_elem == out_elem { - return Ok(args[0].immediate()); - } - - #[derive(Copy, Clone)] - enum Sign { - Unsigned, - Signed, - } - use Sign::*; - - enum Style { - Float, - Int(Sign), - Unsupported, - } - - let (in_style, in_width) = match in_elem.kind() { - // vectors of pointer-sized integers should've been - // disallowed before here, so this unwrap is safe. - ty::Int(i) => ( - Style::Int(Signed), - i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), - ), - ty::Uint(u) => ( - Style::Int(Unsigned), - u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), - ), - ty::Float(f) => (Style::Float, f.bit_width()), - _ => (Style::Unsupported, 0), - }; - let (out_style, out_width) = match out_elem.kind() { - ty::Int(i) => ( - Style::Int(Signed), - i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), - ), - ty::Uint(u) => ( - Style::Int(Unsigned), - u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), - ), - ty::Float(f) => (Style::Float, f.bit_width()), - _ => (Style::Unsupported, 0), - }; - - match (in_style, out_style) { - (Style::Int(sign), Style::Int(_)) => { - return Ok(match in_width.cmp(&out_width) { - Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty), - Ordering::Equal => args[0].immediate(), - Ordering::Less => match sign { - Sign::Signed => bx.sext(args[0].immediate(), llret_ty), - Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty), - }, - }); - } - (Style::Int(Sign::Signed), Style::Float) => { - return Ok(bx.sitofp(args[0].immediate(), llret_ty)); - } - (Style::Int(Sign::Unsigned), Style::Float) => { - return Ok(bx.uitofp(args[0].immediate(), llret_ty)); - } - (Style::Float, Style::Int(sign)) => { - return Ok(match (sign, name == sym::simd_as) { - (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty), - (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty), - (_, true) => bx.cast_float_to_int( - matches!(sign, Sign::Signed), - args[0].immediate(), - llret_ty, - ), - }); - } - (Style::Float, Style::Float) => { - return Ok(match in_width.cmp(&out_width) { - Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty), - Ordering::Equal => args[0].immediate(), - Ordering::Less => bx.fpext(args[0].immediate(), llret_ty), - }); - } - _ => { /* Unsupported. Fallthrough. */ } + match simd_cast(bx, name, args, llret_ty, in_elem, out_elem) { + Some(val) => return Ok(val), + None => return_error!(InvalidMonomorphization::UnsupportedCast { + span, + name, + in_ty, + in_elem, + ret_ty, + out_elem + }), } - return_error!(InvalidMonomorphization::UnsupportedCast { - span, - name, - in_ty, - in_elem, - ret_ty, - out_elem - }); } macro_rules! arith_binary { ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { @@ -3035,3 +2977,86 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span_bug!(span, "unknown SIMD intrinsic"); } + +/// Implementation of `core::intrinsics::simd_cast`, re-used by `core::scalable::sve_cast`. +fn simd_cast<'ll, 'tcx>( + bx: &mut Builder<'_, 'll, 'tcx>, + name: Symbol, + args: &[OperandRef<'tcx, &'ll Value>], + llret_ty: &'ll Type, + in_elem: Ty<'tcx>, + out_elem: Ty<'tcx>, +) -> Option<&'ll Value> { + // Casting cares about nominal type, not just structural type + if in_elem == out_elem { + return Some(args[0].immediate()); + } + + #[derive(Copy, Clone)] + enum Sign { + Unsigned, + Signed, + } + use Sign::*; + + enum Style { + Float, + Int(Sign), + Unsupported, + } + + let (in_style, in_width) = match in_elem.kind() { + // vectors of pointer-sized integers should've been + // disallowed before here, so this unwrap is safe. + ty::Int(i) => ( + Style::Int(Signed), + i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), + ), + ty::Uint(u) => ( + Style::Int(Unsigned), + u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), + ), + ty::Float(f) => (Style::Float, f.bit_width()), + _ => (Style::Unsupported, 0), + }; + let (out_style, out_width) = match out_elem.kind() { + ty::Int(i) => ( + Style::Int(Signed), + i.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), + ), + ty::Uint(u) => ( + Style::Int(Unsigned), + u.normalize(bx.tcx().sess.target.pointer_width).bit_width().unwrap(), + ), + ty::Float(f) => (Style::Float, f.bit_width()), + _ => (Style::Unsupported, 0), + }; + + match (in_style, out_style) { + (Style::Int(sign), Style::Int(_)) => Some(match in_width.cmp(&out_width) { + Ordering::Greater => bx.trunc(args[0].immediate(), llret_ty), + Ordering::Equal => args[0].immediate(), + Ordering::Less => match sign { + Sign::Signed => bx.sext(args[0].immediate(), llret_ty), + Sign::Unsigned => bx.zext(args[0].immediate(), llret_ty), + }, + }), + (Style::Int(Sign::Signed), Style::Float) => Some(bx.sitofp(args[0].immediate(), llret_ty)), + (Style::Int(Sign::Unsigned), Style::Float) => { + Some(bx.uitofp(args[0].immediate(), llret_ty)) + } + (Style::Float, Style::Int(sign)) => Some(match (sign, name == sym::simd_as) { + (Sign::Unsigned, false) => bx.fptoui(args[0].immediate(), llret_ty), + (Sign::Signed, false) => bx.fptosi(args[0].immediate(), llret_ty), + (_, true) => { + bx.cast_float_to_int(matches!(sign, Sign::Signed), args[0].immediate(), llret_ty) + } + }), + (Style::Float, Style::Float) => Some(match in_width.cmp(&out_width) { + Ordering::Greater => bx.fptrunc(args[0].immediate(), llret_ty), + Ordering::Equal => args[0].immediate(), + Ordering::Less => bx.fpext(args[0].immediate(), llret_ty), + }), + _ => None, + } +} diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index ca57921089fae..58454cfc489c6 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -783,6 +783,7 @@ pub(crate) fn check_intrinsic_type( sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)), sym::simd_shuffle_const_generic => (2, 1, vec![param(0), param(0)], param(1)), + sym::sve_cast => (2, 0, vec![param(0)], param(1)), sym::sve_tuple_create2 => (2, 0, vec![param(0), param(0)], param(1)), sym::sve_tuple_create3 => (2, 0, vec![param(0), param(0), param(0)], param(1)), sym::sve_tuple_create4 => (2, 0, vec![param(0), param(0), param(0), param(0)], param(1)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e0bdd60f5971b..a4394af263870 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1979,6 +1979,7 @@ symbols! { suggestion, super_let, supertrait_item_shadowing, + sve_cast, sve_tuple_create2, sve_tuple_create3, sve_tuple_create4, diff --git a/library/core/src/intrinsics/simd/scalable.rs b/library/core/src/intrinsics/simd/scalable.rs index 5e7b64f18e533..f33831a30c070 100644 --- a/library/core/src/intrinsics/simd/scalable.rs +++ b/library/core/src/intrinsics/simd/scalable.rs @@ -2,6 +2,28 @@ //! //! In this module, a "vector" is any `#[rustc_scalable_vector]`-annotated type. +/// Numerically casts a vector, elementwise. +/// +/// `T` and `U` must be vectors of integers or floats, and must have the same length. +/// +/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB. +/// When casting integers to floats, the result is rounded. +/// Otherwise, truncates or extends the value, maintaining the sign for signed integers. +/// +/// # Safety +/// Casting from integer types is always safe. +/// Casting between two float types is also always safe. +/// +/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`. +/// Specifically, each element must: +/// * Not be `NaN` +/// * Not be infinite +/// * Be representable in the return type, after truncating off its fractional part +#[cfg(target_arch = "aarch64")] +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn sve_cast(x: T) -> U; + /// Create a tuple of two vectors. /// /// `SVecTup` must be a scalable vector tuple (`#[rustc_scalable_vector]`) and `SVec` must be a diff --git a/tests/ui/scalable-vectors/cast-intrinsic.rs b/tests/ui/scalable-vectors/cast-intrinsic.rs new file mode 100644 index 0000000000000..f2157d8bcc14b --- /dev/null +++ b/tests/ui/scalable-vectors/cast-intrinsic.rs @@ -0,0 +1,65 @@ +//@ check-pass +//@ only-aarch64 +#![crate_type = "lib"] +#![allow(incomplete_features, internal_features, improper_ctypes)] +#![feature(abi_unadjusted, core_intrinsics, link_llvm_intrinsics, rustc_attrs)] + +use std::intrinsics::simd::scalable::sve_cast; + +#[derive(Copy, Clone)] +#[rustc_scalable_vector(16)] +#[allow(non_camel_case_types)] +pub struct svbool_t(bool); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +pub struct svbool2_t(bool); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +pub struct svint64_t(i64); + +#[derive(Copy, Clone)] +#[rustc_scalable_vector(2)] +#[allow(non_camel_case_types)] +pub struct nxv2i16(i16); + +pub trait SveInto: Sized { + unsafe fn sve_into(self) -> T; +} + +impl SveInto for svbool_t { + #[target_feature(enable = "sve")] + unsafe fn sve_into(self) -> svbool2_t { + unsafe extern "C" { + #[cfg_attr( + target_arch = "aarch64", + link_name = concat!("llvm.aarch64.sve.convert.from.svbool.nxv2i1") + )] + fn convert_from_svbool(b: svbool_t) -> svbool2_t; + } + unsafe { convert_from_svbool(self) } + } +} + +#[target_feature(enable = "sve")] +pub unsafe fn svld1sh_gather_s64offset_s64( + pg: svbool_t, + base: *const i16, + offsets: svint64_t, +) -> svint64_t { + unsafe extern "unadjusted" { + #[cfg_attr( + target_arch = "aarch64", + link_name = "llvm.aarch64.sve.ld1.gather.nxv2i16" + )] + fn _svld1sh_gather_s64offset_s64( + pg: svbool2_t, + base: *const i16, + offsets: svint64_t, + ) -> nxv2i16; + } + sve_cast(_svld1sh_gather_s64offset_s64(pg.sve_into(), base, offsets)) +} From 3e0572e7b62a118f845b349f9426d0ca61b7ed68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sat, 7 Mar 2026 10:26:23 +0100 Subject: [PATCH 52/61] improve diagnostics for attrs that *contain* the word rustc --- compiler/rustc_resolve/src/errors.rs | 9 +++++++++ compiler/rustc_resolve/src/macros.rs | 14 ++++++++++---- tests/ui/attributes/rustc-in-attr-path.rs | 9 --------- tests/ui/attributes/rustc-in-attr-path.stderr | 8 -------- tests/ui/feature-gates/feature-gate-rustc-attrs.rs | 2 +- .../feature-gates/feature-gate-rustc-attrs.stderr | 2 +- 6 files changed, 21 insertions(+), 23 deletions(-) delete mode 100644 tests/ui/attributes/rustc-in-attr-path.rs delete mode 100644 tests/ui/attributes/rustc-in-attr-path.stderr diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 24c923de67946..4bbb7d8e5571a 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1198,6 +1198,15 @@ pub(crate) struct AttributesStartingWithRustcAreReserved { pub(crate) span: Span, } +#[derive(Diagnostic)] +#[diag( + "attributes containing a segment starting with `rustc` are reserved for use by the `rustc` compiler" +)] +pub(crate) struct AttributesContainingRustcAreReserved { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag("cannot use {$article} {$descr} through an import")] pub(crate) struct CannotUseThroughAnImport { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6ae9d3aaeb236..619e61211984d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -618,14 +618,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // Report errors for the resolved macro. - for segment in &path.segments { + for (idx, segment) in path.segments.iter().enumerate() { if let Some(args) = &segment.args { self.dcx().emit_err(errors::GenericArgumentsInMacroPath { span: args.span() }); } if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { - self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved { - span: segment.ident.span, - }); + if idx == 0 { + self.dcx().emit_err(errors::AttributesStartingWithRustcAreReserved { + span: segment.ident.span, + }); + } else { + self.dcx().emit_err(errors::AttributesContainingRustcAreReserved { + span: segment.ident.span, + }); + } } } diff --git a/tests/ui/attributes/rustc-in-attr-path.rs b/tests/ui/attributes/rustc-in-attr-path.rs deleted file mode 100644 index 302f0239de03d..0000000000000 --- a/tests/ui/attributes/rustc-in-attr-path.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod rustc { - pub use std::prelude::v1::test; -} - -#[crate::rustc::test] -//~^ ERROR: attributes starting with `rustc` are reserved for use by the `rustc` compiler -fn foo() {} - -fn main() {} diff --git a/tests/ui/attributes/rustc-in-attr-path.stderr b/tests/ui/attributes/rustc-in-attr-path.stderr deleted file mode 100644 index 62f96a36480b6..0000000000000 --- a/tests/ui/attributes/rustc-in-attr-path.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: attributes starting with `rustc` are reserved for use by the `rustc` compiler - --> $DIR/rustc-in-attr-path.rs:5:10 - | -LL | #[crate::rustc::test] - | ^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs.rs index e7b2eca6f858a..6382af32efb2a 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs.rs +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -12,7 +12,7 @@ mod unknown { pub macro rustc() {} } fn f() {} #[unknown::rustc] -//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler +//~^ ERROR attributes containing a segment starting with `rustc` are reserved for use by the `rustc` compiler //~| ERROR expected attribute, found macro `unknown::rustc` //~| NOTE not an attribute fn g() {} diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr index d58603883f158..bc0db8b81aefc 100644 --- a/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/tests/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -10,7 +10,7 @@ error: expected attribute, found macro `rustc::unknown` LL | #[rustc::unknown] | ^^^^^^^^^^^^^^ not an attribute -error: attributes starting with `rustc` are reserved for use by the `rustc` compiler +error: attributes containing a segment starting with `rustc` are reserved for use by the `rustc` compiler --> $DIR/feature-gate-rustc-attrs.rs:14:12 | LL | #[unknown::rustc] From 7dc9a0856fe454caf95195a12257377270de05d8 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 27 Mar 2026 15:32:27 +0000 Subject: [PATCH 53/61] Lower spans for literal const args --- compiler/rustc_ast_lowering/src/lib.rs | 4 +-- .../type_const-mismatched-type-incremental.rs | 15 +++++++++++ ...e_const-mismatched-type-incremental.stderr | 26 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs create mode 100644 tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5fcc8f0161194..6d9fe9870c42e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2683,7 +2683,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { overly_complex_const(self) } ExprKind::Lit(literal) => { - let span = expr.span; + let span = self.lower_span(expr.span); let literal = self.lower_lit(literal, span); ConstArg { @@ -2695,7 +2695,7 @@ impl<'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'_, 'hir, R> { ExprKind::Unary(UnOp::Neg, inner_expr) if let ExprKind::Lit(literal) = &inner_expr.kind => { - let span = expr.span; + let span = self.lower_span(expr.span); let literal = self.lower_lit(literal, span); if !matches!(literal.node, LitKind::Int(..)) { diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs new file mode 100644 index 0000000000000..74c945b0881a4 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs @@ -0,0 +1,15 @@ +//! Regression test for +//! +//@ incremental +#![feature(min_generic_const_args)] +type const R: usize = 1_i32; //~ ERROR: the constant `1` is not of type `usize` +type const U: usize = -1_i32; //~ ERROR: the constant `-1` is not of type `usize` +type const S: bool = 1i32; //~ ERROR: the constant `1` is not of type `bool` +type const T: bool = -1i32; //~ ERROR: the constant `-1` is not of type `bool` + +fn main() { + R; + U; + S; + T; +} diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr new file mode 100644 index 0000000000000..b09ac22240325 --- /dev/null +++ b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr @@ -0,0 +1,26 @@ +error: the constant `1` is not of type `usize` + --> $DIR/type_const-mismatched-type-incremental.rs:5:1 + | +LL | type const R: usize = 1_i32; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i32` + +error: the constant `-1` is not of type `usize` + --> $DIR/type_const-mismatched-type-incremental.rs:6:1 + | +LL | type const U: usize = -1_i32; + | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i32` + +error: the constant `1` is not of type `bool` + --> $DIR/type_const-mismatched-type-incremental.rs:7:1 + | +LL | type const S: bool = 1i32; + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `i32` + +error: the constant `-1` is not of type `bool` + --> $DIR/type_const-mismatched-type-incremental.rs:8:1 + | +LL | type const T: bool = -1i32; + | ^^^^^^^^^^^^^^^^^^ expected `bool`, found `i32` + +error: aborting due to 4 previous errors + From 28b06a67b36694f5840773f8b128104b09d4a700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Mon, 30 Mar 2026 13:08:08 +0200 Subject: [PATCH 54/61] Rename probe_ty_var to try_resolve_ty_var Co-authored-by: khyperia <953151+khyperia@users.noreply.github.com> --- .../rustc_infer/src/infer/canonical/canonicalizer.rs | 4 ++-- compiler/rustc_infer/src/infer/context.rs | 12 ++++++------ compiler/rustc_infer/src/infer/mod.rs | 7 +++++-- compiler/rustc_infer/src/infer/relate/generalize.rs | 4 ++-- .../src/error_reporting/infer/need_type_info.rs | 2 +- 5 files changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 89ea6324d8543..87d389a5dea5a 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -341,7 +341,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } debug!("canonical: type var found with vid {:?}", vid); - match self.infcx.unwrap().probe_ty_var(vid) { + match self.infcx.unwrap().try_resolve_ty_var(vid) { // `t` could be a float / int variable; canonicalize that instead. Ok(t) => { debug!("(resolved to {:?})", t); @@ -443,7 +443,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } debug!("canonical: const var found with vid {:?}", vid); - match self.infcx.unwrap().probe_const_var(vid) { + match self.infcx.unwrap().try_resolve_const_var(vid) { Ok(c) => { debug!("(resolved to {:?})", c); return self.fold_const(c); diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 09403513aa08c..fada30ff30633 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -35,7 +35,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn universe_of_ty(&self, vid: ty::TyVid) -> Option { - match self.probe_ty_var(vid) { + match self.try_resolve_ty_var(vid) { Err(universe) => Some(universe), Ok(_) => None, } @@ -49,7 +49,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn universe_of_ct(&self, ct: ty::ConstVid) -> Option { - match self.probe_const_var(ct) { + match self.try_resolve_const_var(ct) { Err(universe) => Some(universe), Ok(_) => None, } @@ -68,7 +68,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty<'tcx> { - match self.probe_ty_var(vid) { + match self.try_resolve_ty_var(vid) { Ok(ty) => ty, Err(_) => Ty::new_var(self.tcx, self.root_var(vid)), } @@ -83,7 +83,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { } fn opportunistic_resolve_ct_var(&self, vid: ty::ConstVid) -> ty::Const<'tcx> { - match self.probe_const_var(vid) { + match self.try_resolve_const_var(vid) { Ok(ct) => ct, Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)), } @@ -103,7 +103,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { if let ty::Infer(infer_ty) = *ty.kind() { match infer_ty { ty::InferTy::TyVar(vid) => { - !self.probe_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid) + !self.try_resolve_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid) } ty::InferTy::IntVar(vid) => { let mut inner = self.inner.borrow_mut(); @@ -133,7 +133,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { if let ty::ConstKind::Infer(infer_ct) = ct.kind() { match infer_ct { ty::InferConst::Var(vid) => !self - .probe_const_var(vid) + .try_resolve_const_var(vid) .is_err_and(|_| self.root_const_var(vid) == vid), ty::InferConst::Fresh(_) => true, } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e15b25500bb57..2057eeb875970 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1074,7 +1074,7 @@ impl<'tcx> InferCtxt<'tcx> { /// If `TyVar(vid)` resolves to a type, return that type. Else, return the /// universe index of `TyVar(vid)`. - pub fn probe_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { + pub fn try_resolve_ty_var(&self, vid: TyVid) -> Result, ty::UniverseIndex> { use self::type_variable::TypeVariableValue; match self.inner.borrow_mut().type_variables().probe(vid) { @@ -1228,7 +1228,10 @@ impl<'tcx> InferCtxt<'tcx> { value.fold_with(&mut r) } - pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { + pub fn try_resolve_const_var( + &self, + vid: ty::ConstVid, + ) -> Result, ty::UniverseIndex> { match self.inner.borrow_mut().const_unification_table().probe_value(vid) { ConstVariableValue::Known { value } => Ok(value), ConstVariableValue::Unknown { origin: _, universe } => Err(universe), diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 3ab39e83f3123..0b29421a8da8b 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -300,10 +300,10 @@ impl<'tcx> InferCtxt<'tcx> { assert!(!source_term.has_escaping_bound_vars()); let (for_universe, root_vid) = match target_vid { TermVid::Ty(ty_vid) => { - (self.probe_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid))) + (self.try_resolve_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid))) } TermVid::Const(ct_vid) => ( - self.probe_const_var(ct_vid).unwrap_err(), + self.try_resolve_const_var(ct_vid).unwrap_err(), TermVid::Const(self.inner.borrow_mut().const_unification_table().find(ct_vid).vid), ), }; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 46bc9bdee04b8..d891cb3fb800d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -255,7 +255,7 @@ impl<'a, 'tcx> TypeFolder> for ClosureEraser<'a, 'tcx> { fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> { let mut p = FmtPrinter::new(infcx.tcx, ns); let ty_getter = move |ty_vid| { - if infcx.probe_ty_var(ty_vid).is_ok() { + if infcx.try_resolve_ty_var(ty_vid).is_ok() { warn!("resolved ty var in error message"); } From e29f4f4a79600113ace50a0394d55258b5702e55 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 2 Apr 2026 10:33:14 +0100 Subject: [PATCH 55/61] Revert `Ty` type alias in `rustc_type_ir` --- .../src/canonical/canonicalizer.rs | 6 +- .../src/canonical/mod.rs | 6 +- .../rustc_next_trait_solver/src/coherence.rs | 29 +++---- .../rustc_next_trait_solver/src/delegate.rs | 8 +- .../src/placeholder.rs | 2 +- .../rustc_next_trait_solver/src/resolve.rs | 6 +- .../src/solve/assembly/mod.rs | 12 +-- .../src/solve/assembly/structural_traits.rs | 38 ++++---- .../src/solve/effect_goals.rs | 6 +- .../src/solve/eval_ctxt/mod.rs | 28 +++--- .../rustc_next_trait_solver/src/solve/mod.rs | 10 +-- .../src/solve/normalizes_to/mod.rs | 4 +- .../src/solve/trait_goals.rs | 27 +++--- compiler/rustc_type_ir/src/binder.rs | 16 ++-- compiler/rustc_type_ir/src/error.rs | 8 +- compiler/rustc_type_ir/src/fast_reject.rs | 15 ++-- compiler/rustc_type_ir/src/flags.rs | 4 +- compiler/rustc_type_ir/src/fold.rs | 8 +- compiler/rustc_type_ir/src/generic_arg.rs | 6 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 34 +++++--- compiler/rustc_type_ir/src/inherent.rs | 32 +++---- compiler/rustc_type_ir/src/lib.rs | 6 +- compiler/rustc_type_ir/src/outlives.rs | 8 +- compiler/rustc_type_ir/src/predicate.rs | 48 +++++------ compiler/rustc_type_ir/src/predicate_kind.rs | 6 +- compiler/rustc_type_ir/src/relate.rs | 18 ++-- compiler/rustc_type_ir/src/relate/combine.rs | 16 ++-- .../src/relate/solver_relating.rs | 16 ++-- compiler/rustc_type_ir/src/solve/mod.rs | 4 +- compiler/rustc_type_ir/src/sty/mod.rs | 3 - compiler/rustc_type_ir/src/ty_kind.rs | 46 +++++----- compiler/rustc_type_ir/src/ty_kind/closure.rs | 86 +++++++++---------- compiler/rustc_type_ir/src/visit.rs | 8 +- 33 files changed, 280 insertions(+), 290 deletions(-) delete mode 100644 compiler/rustc_type_ir/src/sty/mod.rs diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 5a0f149fd0550..ce2be24adc586 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -78,7 +78,7 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate, I: Interner /// We can simply cache based on the ty itself, because we use /// `ty::BoundVarIndexKind::Canonical`. - cache: HashMap, ty::Ty>, + cache: HashMap, } impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { @@ -316,7 +316,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { (max_universe, self.variables, var_kinds) } - fn inner_fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn inner_fold_ty(&mut self, t: I::Ty) -> I::Ty { let kind = match t.kind() { ty::Infer(i) => match i { ty::TyVar(vid) => { @@ -475,7 +475,7 @@ impl, I: Interner> TypeFolder for Canonicaliz Region::new_canonical_bound(self.cx(), var) } - fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { if !t.flags().intersects(NEEDS_CANONICAL) { t } else if let Some(&ty) = self.cache.get(&t) { diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index cd42bf8b57b60..1f64f09fe787f 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -16,7 +16,7 @@ use rustc_index::IndexVec; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::{ - self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, Ty, + self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, }; use tracing::instrument; @@ -53,7 +53,7 @@ impl ResponseT for inspect::State { pub(super) fn canonicalize_goal( delegate: &D, goal: Goal, - opaque_types: &[(ty::OpaqueTypeKey, Ty)], + opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], ) -> (Vec, CanonicalInput) where D: SolverDelegate, @@ -264,7 +264,7 @@ fn register_region_constraints( fn register_new_opaque_types( delegate: &D, - opaque_types: &[(ty::OpaqueTypeKey, Ty)], + opaque_types: &[(ty::OpaqueTypeKey, I::Ty)], span: I::Span, ) where D: SolverDelegate, diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 69cebb0a3dc64..c370fd24a1bb3 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -47,7 +47,7 @@ pub enum Conflict { pub fn trait_ref_is_knowable( infcx: &Infcx, trait_ref: ty::TraitRef, - mut lazily_normalize_ty: impl FnMut(ty::Ty) -> Result, E>, + mut lazily_normalize_ty: impl FnMut(I::Ty) -> Result, ) -> Result, E> where Infcx: InferCtxtLike, @@ -115,14 +115,14 @@ impl From for IsFirstInputType { #[derive_where(Debug; I: Interner, T: Debug)] pub enum OrphanCheckErr { - NonLocalInputType(Vec<(ty::Ty, IsFirstInputType)>), + NonLocalInputType(Vec<(I::Ty, IsFirstInputType)>), UncoveredTyParams(UncoveredTyParams), } #[derive_where(Debug; I: Interner, T: Debug)] pub struct UncoveredTyParams { pub uncovered: T, - pub local_ty: Option>, + pub local_ty: Option, } /// Checks whether a trait-ref is potentially implementable by a crate. @@ -222,8 +222,8 @@ pub fn orphan_check_trait_ref( infcx: &Infcx, trait_ref: ty::TraitRef, in_crate: InCrate, - lazily_normalize_ty: impl FnMut(ty::Ty) -> Result, E>, -) -> Result>>, E> + lazily_normalize_ty: impl FnMut(I::Ty) -> Result, +) -> Result>, E> where Infcx: InferCtxtLike, I: Interner, @@ -262,14 +262,14 @@ struct OrphanChecker<'a, Infcx, I: Interner, F> { lazily_normalize_ty: F, /// Ignore orphan check failures and exclusively search for the first local type. search_first_local_ty: bool, - non_local_tys: Vec<(ty::Ty, IsFirstInputType)>, + non_local_tys: Vec<(I::Ty, IsFirstInputType)>, } impl<'a, Infcx, I, F, E> OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnOnce(ty::Ty) -> Result, E>, + F: FnOnce(I::Ty) -> Result, { fn new(infcx: &'a Infcx, in_crate: InCrate, lazily_normalize_ty: F) -> Self { OrphanChecker { @@ -282,15 +282,12 @@ where } } - fn found_non_local_ty(&mut self, t: ty::Ty) -> ControlFlow> { + fn found_non_local_ty(&mut self, t: I::Ty) -> ControlFlow> { self.non_local_tys.push((t, self.in_self_ty.into())); ControlFlow::Continue(()) } - fn found_uncovered_ty_param( - &mut self, - ty: ty::Ty, - ) -> ControlFlow> { + fn found_uncovered_ty_param(&mut self, ty: I::Ty) -> ControlFlow> { if self.search_first_local_ty { return ControlFlow::Continue(()); } @@ -308,15 +305,15 @@ where enum OrphanCheckEarlyExit { NormalizationFailure(E), - UncoveredTyParam(ty::Ty), - LocalTy(ty::Ty), + UncoveredTyParam(I::Ty), + LocalTy(I::Ty), } impl<'a, Infcx, I, F, E> TypeVisitor for OrphanChecker<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(ty::Ty) -> Result, E>, + F: FnMut(I::Ty) -> Result, { type Result = ControlFlow>; @@ -324,7 +321,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: ty::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { let ty = self.infcx.shallow_resolve(ty); let ty = match (self.lazily_normalize_ty)(ty) { Ok(norm_ty) if norm_ty.is_ty_var() => ty, diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 1714ae3dd6b2e..9d5aa8bc124b6 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Ty, TypeFoldable}; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; pub trait SolverDelegate: Deref + Sized { type Infcx: InferCtxtLike; @@ -70,7 +70,7 @@ pub trait SolverDelegate: Deref + Sized { def_id: ::DefId, args: ::GenericArgs, param_env: ::ParamEnv, - hidden_ty: Ty, + hidden_ty: ::Ty, goals: &mut Vec::Predicate>>, ); @@ -86,8 +86,8 @@ pub trait SolverDelegate: Deref + Sized { fn is_transmutable( &self, - src: Ty, - dst: Ty, + src: ::Ty, + dst: ::Ty, assume: ::Const, ) -> Result; } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index fe7521c86e9be..83f3bdf01dc83 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -113,7 +113,7 @@ where } } - fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { match t.kind() { ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) if debruijn.as_usize() + 1 diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 86bf05bdb57cc..c3c57eccd6eff 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -1,7 +1,7 @@ use rustc_type_ir::data_structures::DelayedMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, + self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -19,7 +19,7 @@ where delegate: &'a D, /// We're able to use a cache here as the folder does not have any /// mutable state. - cache: DelayedMap, Ty>, + cache: DelayedMap, } pub fn eager_resolve_vars>( @@ -45,7 +45,7 @@ impl, I: Interner> TypeFolder for EagerResolv self.delegate.cx() } - fn fold_ty(&mut self, t: Ty) -> Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { match t.kind() { ty::Infer(ty::TyVar(vid)) => { let resolved = self.delegate.opportunistic_resolve_ty_var(vid); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index f58318b83625d..32b1e93bf98be 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -46,11 +46,11 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> ty::Ty; + fn self_ty(self) -> I::Ty; fn trait_ref(self, cx: I) -> ty::TraitRef; - fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self; + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self; fn trait_def_id(self, cx: I) -> I::TraitId; @@ -683,7 +683,7 @@ where // hitting another overflow error something. Add a depth parameter needed later. fn assemble_alias_bound_candidates_recur>( &mut self, - self_ty: ty::Ty, + self_ty: I::Ty, goal: Goal, candidates: &mut Vec>, consider_self_bounds: AliasBoundKind, @@ -1017,13 +1017,13 @@ where struct ReplaceOpaque { cx: I, alias_ty: ty::AliasTy, - self_ty: ty::Ty, + self_ty: I::Ty, } impl TypeFolder for ReplaceOpaque { fn cx(&self) -> I { self.cx } - fn fold_ty(&mut self, ty: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { if let ty::Alias(ty::Opaque, alias_ty) = ty.kind() { if alias_ty == self.alias_ty { return self.self_ty; @@ -1280,7 +1280,7 @@ where ControlFlow::Continue(()) } - fn visit_ty(&mut self, ty: ty::Ty) -> Self::Result { + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { let ty = self.ecx.replace_bound_vars(ty, &mut self.universes); let Ok(ty) = self.ecx.structurally_normalize_ty(self.param_env, ty) else { return ControlFlow::Break(Err(NoSolution)); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index cbdf0b0a4cc72..433cad188bb6c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -21,8 +21,8 @@ use crate::solve::{AdtDestructorKind, EvalCtxt, Goal, NoSolution}; #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait( ecx: &EvalCtxt<'_, D>, - ty: ty::Ty, -) -> Result>>, NoSolution> + ty: I::Ty, +) -> Result>, NoSolution> where D: SolverDelegate, I: Interner, @@ -108,8 +108,8 @@ where pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait( ecx: &EvalCtxt<'_, D>, sizedness: SizedTraitKind, - ty: ty::Ty, -) -> Result>>, NoSolution> + ty: I::Ty, +) -> Result>, NoSolution> where D: SolverDelegate, I: Interner, @@ -186,8 +186,8 @@ where #[instrument(level = "trace", skip(ecx), ret)] pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait( ecx: &EvalCtxt<'_, D>, - ty: ty::Ty, -) -> Result>>, NoSolution> + ty: I::Ty, +) -> Result>, NoSolution> where D: SolverDelegate, I: Interner, @@ -268,9 +268,9 @@ where // Returns a binder of the tupled inputs types and output type from a builtin callable type. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( cx: I, - self_ty: ty::Ty, + self_ty: I::Ty, goal_kind: ty::ClosureKind, -) -> Result, ty::Ty)>>, NoSolution> { +) -> Result>, NoSolution> { match self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, args) => { @@ -408,13 +408,13 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable { - pub tupled_inputs_ty: ty::Ty, + pub tupled_inputs_ty: I::Ty, /// Type returned by calling the closure /// i.e. `f()`. - pub output_coroutine_ty: ty::Ty, + pub output_coroutine_ty: I::Ty, /// Type returned by `await`ing the output /// i.e. `f().await`. - pub coroutine_return_ty: ty::Ty, + pub coroutine_return_ty: I::Ty, } // Returns a binder of the tupled inputs types, output type, and coroutine type @@ -424,7 +424,7 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes { // know the kind already, we can short-circuit this check. pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( cx: I, - self_ty: ty::Ty, + self_ty: I::Ty, goal_kind: ty::ClosureKind, env_region: I::Region, ) -> Result<(ty::Binder>, Vec), NoSolution> { @@ -608,7 +608,7 @@ fn coroutine_closure_to_certain_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> ty::Ty { +) -> I::Ty { sig.to_coroutine_given_kind_and_upvars( cx, args.parent_args(), @@ -632,7 +632,7 @@ fn coroutine_closure_to_ambiguous_coroutine( def_id: I::CoroutineClosureId, args: ty::CoroutineClosureArgs, sig: ty::CoroutineClosureSignature, -) -> ty::Ty { +) -> I::Ty { let upvars_projection_def_id = cx.require_lang_item(SolverLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( cx, @@ -664,8 +664,8 @@ fn coroutine_closure_to_ambiguous_coroutine( #[instrument(level = "trace", skip(cx), ret)] pub(in crate::solve) fn extract_fn_def_from_const_callable( cx: I, - self_ty: ty::Ty, -) -> Result<(ty::Binder, ty::Ty)>, I::DefId, I::GenericArgs), NoSolution> { + self_ty: I::Ty, +) -> Result<(ty::Binder, I::DefId, I::GenericArgs), NoSolution> { match self_ty.kind() { ty::FnDef(def_id, args) => { let sig = cx.fn_sig(def_id); @@ -742,7 +742,7 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( // the old solver, for as long as that exists. pub(in crate::solve) fn const_conditions_for_destruct( cx: I, - self_ty: ty::Ty, + self_ty: I::Ty, ) -> Result>, NoSolution> { let destruct_def_id = cx.require_trait_lang_item(SolverTraitLangItem::Destruct); @@ -927,7 +927,7 @@ where struct ReplaceProjectionWith<'a, 'b, I: Interner, D: SolverDelegate> { ecx: &'a mut EvalCtxt<'b, D>, param_env: I::ParamEnv, - self_ty: ty::Ty, + self_ty: I::Ty, mapping: &'a HashMap>>>, nested: Vec>, } @@ -1013,7 +1013,7 @@ where self.ecx.cx() } - fn try_fold_ty(&mut self, ty: ty::Ty) -> Result, Ambiguous> { + fn try_fold_ty(&mut self, ty: I::Ty) -> Result { if let ty::Alias(ty::Projection, alias_ty) = ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 9a0a82acbc931..4b1e4b2de571d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -13,7 +13,7 @@ use super::assembly::{Candidate, structural_traits}; use crate::delegate::SolverDelegate; use crate::solve::{ BuiltinImplSource, CandidateSource, Certainty, EvalCtxt, Goal, GoalSource, NoSolution, - QueryResult, Ty, assembly, + QueryResult, assembly, }; impl assembly::GoalKind for ty::HostEffectPredicate @@ -21,7 +21,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> Ty { + fn self_ty(self) -> I::Ty { self.self_ty() } @@ -29,7 +29,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } 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 d6ed220909732..6841fe1c5124e 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 @@ -10,7 +10,7 @@ use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::search_graph::{CandidateHeadUsages, PathKind}; use rustc_type_ir::solve::OpaqueTypesJank; use rustc_type_ir::{ - self as ty, CanonicalVarValues, InferCtxtLike, Interner, Ty, TypeFoldable, TypeFolder, + self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; @@ -781,7 +781,7 @@ where region } - pub(super) fn next_ty_infer(&mut self) -> Ty { + pub(super) fn next_ty_infer(&mut self) -> I::Ty { let ty = self.delegate.next_ty_infer(); self.inspect.add_var_value(ty); ty @@ -829,7 +829,7 @@ where term: I::Term, universe_of_term: ty::UniverseIndex, delegate: &'a D, - cache: HashSet>, + cache: HashSet, } impl, I: Interner> ContainsTermOrNotNameable<'_, D, I> { @@ -846,7 +846,7 @@ where for ContainsTermOrNotNameable<'_, D, I> { type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty) -> Self::Result { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { if self.cache.contains(&t) { return ControlFlow::Continue(()); } @@ -1072,7 +1072,7 @@ where self.delegate.resolve_vars_if_possible(value) } - pub(super) fn shallow_resolve(&self, ty: Ty) -> Ty { + pub(super) fn shallow_resolve(&self, ty: I::Ty) -> I::Ty { self.delegate.shallow_resolve(ty) } @@ -1092,7 +1092,7 @@ where args } - pub(super) fn register_ty_outlives(&self, ty: Ty, lt: I::Region) { + pub(super) fn register_ty_outlives(&self, ty: I::Ty, lt: I::Region) { self.delegate.register_ty_outlives(ty, lt, self.origin_span); } @@ -1134,8 +1134,8 @@ where pub(super) fn register_hidden_type_in_storage( &mut self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: Ty, - ) -> Option> { + hidden_ty: I::Ty, + ) -> Option { self.delegate.register_hidden_type_in_storage(opaque_type_key, hidden_ty, self.origin_span) } @@ -1144,7 +1144,7 @@ where opaque_def_id: I::DefId, opaque_args: I::GenericArgs, param_env: I::ParamEnv, - hidden_ty: Ty, + hidden_ty: I::Ty, ) { let mut goals = Vec::new(); self.delegate.add_item_bounds_for_hidden_type( @@ -1170,8 +1170,8 @@ where pub(super) fn is_transmutable( &mut self, - src: Ty, - dst: Ty, + src: I::Ty, + dst: I::Ty, assume: I::Const, ) -> Result { self.delegate.is_transmutable(dst, src, assume) @@ -1195,7 +1195,7 @@ where pub(crate) fn opaques_with_sub_unified_hidden_type( &self, - self_ty: Ty, + self_ty: I::Ty, ) -> Vec> { if let ty::Infer(ty::TyVar(vid)) = self_ty.kind() { self.delegate.opaques_with_sub_unified_hidden_type(vid) @@ -1389,7 +1389,7 @@ where ecx: &'me mut EvalCtxt<'a, D>, param_env: I::ParamEnv, normalization_goal_source: GoalSource, - cache: HashMap, Ty>, + cache: HashMap, } impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I> @@ -1421,7 +1421,7 @@ where self.ecx.cx() } - fn fold_ty(&mut self, ty: Ty) -> Ty { + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { match ty.kind() { ty::Alias(..) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 71b28cf1ad277..58bd7cf663d98 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -24,7 +24,7 @@ mod trait_goals; use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner, Ty, TyVid, TypingMode}; +use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode}; use tracing::instrument; pub use self::eval_ctxt::{ @@ -88,7 +88,7 @@ where #[instrument(level = "trace", skip(self))] fn compute_type_outlives_goal( &mut self, - goal: Goal>>, + goal: Goal>, ) -> QueryResult { let ty::OutlivesPredicate(ty, lt) = goal.predicate; self.register_ty_outlives(ty, lt); @@ -205,7 +205,7 @@ where #[instrument(level = "trace", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, - goal: Goal)>, + goal: Goal, ) -> QueryResult { let (ct, ty) = goal.predicate; let ct = self.structurally_normalize_const(goal.param_env, ct)?; @@ -315,8 +315,8 @@ where fn structurally_normalize_ty( &mut self, param_env: I::ParamEnv, - ty: Ty, - ) -> Result, NoSolution> { + ty: I::Ty, + ) -> Result { self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty()) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 13ed945857db2..13f2ad8f82eba 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -125,7 +125,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> ty::Ty { + fn self_ty(self) -> I::Ty { self.self_ty() } @@ -133,7 +133,7 @@ where self.alias.trait_ref(cx) } - fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 82051b2fea4ef..6589a12c4cc2d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -29,7 +29,7 @@ where D: SolverDelegate, I: Interner, { - fn self_ty(self) -> ty::Ty { + fn self_ty(self) -> I::Ty { self.self_ty() } @@ -37,7 +37,7 @@ where self.trait_ref } - fn with_replaced_self_ty(self, cx: I, self_ty: ty::Ty) -> Self { + fn with_replaced_self_ty(self, cx: I, self_ty: I::Ty) -> Self { self.with_replaced_self_ty(cx, self_ty) } @@ -929,7 +929,7 @@ where /// ``` fn consider_builtin_dyn_upcast_candidates( &mut self, - goal: Goal, ty::Ty)>, + goal: Goal, a_data: I::BoundExistentialPredicates, a_region: I::Region, b_data: I::BoundExistentialPredicates, @@ -977,7 +977,7 @@ where fn consider_builtin_unsize_to_dyn_candidate( &mut self, - goal: Goal, ty::Ty)>, + goal: Goal, b_data: I::BoundExistentialPredicates, b_region: I::Region, ) -> Result, NoSolution> { @@ -1018,7 +1018,7 @@ where fn consider_builtin_upcast_to_principal( &mut self, - goal: Goal, ty::Ty)>, + goal: Goal, source: CandidateSource, a_data: I::BoundExistentialPredicates, a_region: I::Region, @@ -1132,9 +1132,9 @@ where /// `#[rustc_deny_explicit_impl]` in this case. fn consider_builtin_array_unsize( &mut self, - goal: Goal, ty::Ty)>, - a_elem_ty: ty::Ty, - b_elem_ty: ty::Ty, + goal: Goal, + a_elem_ty: I::Ty, + b_elem_ty: I::Ty, ) -> Result, NoSolution> { self.eq(goal.param_env, a_elem_ty, b_elem_ty)?; self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) @@ -1156,7 +1156,7 @@ where /// ``` fn consider_builtin_struct_unsize( &mut self, - goal: Goal, ty::Ty)>, + goal: Goal, def: I::AdtDef, a_args: I::GenericArgs, b_args: I::GenericArgs, @@ -1319,8 +1319,8 @@ where goal: Goal>, constituent_tys: impl Fn( &EvalCtxt<'_, D>, - ty::Ty, - ) -> Result>>, NoSolution>, + I::Ty, + ) -> Result>, NoSolution>, ) -> Result, NoSolution> { self.probe_trait_candidate(source).enter(|ecx| { let goals = @@ -1542,10 +1542,7 @@ where self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) } - fn try_stall_coroutine( - &mut self, - self_ty: ty::Ty, - ) -> Option, NoSolution>> { + fn try_stall_coroutine(&mut self, self_ty: I::Ty) -> Option, NoSolution>> { if let ty::Coroutine(def_id, _) = self_ty.kind() { match self.typing_mode() { TypingMode::Analysis { diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 6528aa7526b21..0b0f0fd2f4249 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -16,7 +16,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldabl use crate::inherent::*; use crate::lift::Lift; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use crate::{self as ty, DebruijnIndex, Interner, Ty, UniverseIndex}; +use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex}; /// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the /// compiler's representation for things like `for<'a> Fn(&'a isize)` @@ -274,7 +274,7 @@ pub struct ValidateBoundVars { // We only cache types because any complex const will have to step through // a type at some point anyways. We may encounter the same variable at // different levels of binding, so this can't just be `Ty`. - visited: SsoHashSet<(ty::DebruijnIndex, Ty)>, + visited: SsoHashSet<(ty::DebruijnIndex, I::Ty)>, } impl ValidateBoundVars { @@ -297,7 +297,7 @@ impl TypeVisitor for ValidateBoundVars { result } - fn visit_ty(&mut self, t: Ty) -> Self::Result { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { @@ -724,7 +724,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } } - fn fold_ty(&mut self, t: Ty) -> Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { if !t.has_param() { return t; } @@ -753,7 +753,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } impl<'a, I: Interner> ArgFolder<'a, I> { - fn ty_for_param(&self, p: I::ParamTy, source_ty: Ty) -> Ty { + fn ty_for_param(&self, p: I::ParamTy, source_ty: I::Ty) -> I::Ty { // Look up the type in the args. It really should be in there. let opt_ty = self.args.get(p.index() as usize).map(|arg| arg.kind()); let ty = match opt_ty { @@ -767,7 +767,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_expected(&self, p: I::ParamTy, ty: Ty, kind: ty::GenericArgKind) -> ! { + fn type_param_expected(&self, p: I::ParamTy, ty: I::Ty, kind: ty::GenericArgKind) -> ! { panic!( "expected type for `{:?}` ({:?}/{}) but found {:?} when instantiating, args={:?}", p, @@ -780,7 +780,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn type_param_out_of_range(&self, p: I::ParamTy, ty: Ty) -> ! { + fn type_param_out_of_range(&self, p: I::ParamTy, ty: I::Ty) -> ! { panic!( "type parameter `{:?}` ({:?}/{}) out of range when instantiating, args={:?}", p, @@ -1277,7 +1277,7 @@ impl PlaceholderConst { Self { universe: ui, bound, _tcx: PhantomData } } - pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> Ty { + pub fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty { let mut candidates = env.caller_bounds().iter().filter_map(|clause| { // `ConstArgHasType` are never desugared to be higher ranked. match clause.kind().skip_binder() { diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index ef542af7f1f9a..eba4c7c6644ac 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -2,7 +2,7 @@ use derive_where::derive_where; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::NoSolution; -use crate::{self as ty, Interner, Ty}; +use crate::{self as ty, Interner}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(TypeFoldable_Generic, TypeVisitable_Generic, GenericTypeVisitable)] @@ -36,15 +36,15 @@ pub enum TypeError { RegionsInsufficientlyPolymorphic(ty::BoundRegion, I::Region), RegionsPlaceholderMismatch, - Sorts(ExpectedFound>), - ArgumentSorts(ExpectedFound>, usize), + Sorts(ExpectedFound), + ArgumentSorts(ExpectedFound, usize), Traits(ExpectedFound), VariadicMismatch(ExpectedFound), /// Instantiating a type variable with the given type would have /// created a cycle (because it appears somewhere within that /// type). - CyclicTy(Ty), + CyclicTy(I::Ty), CyclicConst(I::Const), ProjectionMismatched(ExpectedFound), ExistentialMismatch(ExpectedFound), diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 6bd985a20ae01..5e24e53c62d9a 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -113,7 +113,7 @@ pub enum TreatParams { /// ¹ meaning that if the outermost layers are different, then the whole types are also different. pub fn simplify_type( cx: I, - ty: ty::Ty, + ty: I::Ty, treat_params: TreatParams, ) -> Option> { match ty.kind() { @@ -236,16 +236,11 @@ impl, rhs: ty::Ty) -> bool { + pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool { self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH) } - pub fn types_may_unify_with_depth( - self, - lhs: ty::Ty, - rhs: ty::Ty, - depth_limit: usize, - ) -> bool { + pub fn types_may_unify_with_depth(self, lhs: I::Ty, rhs: I::Ty, depth_limit: usize) -> bool { self.types_may_unify_inner(lhs, rhs, depth_limit) } @@ -273,7 +268,7 @@ impl, rhs: ty::Ty, depth: usize) -> bool { + fn types_may_unify_inner(self, lhs: I::Ty, rhs: I::Ty, depth: usize) -> bool { if lhs == rhs { return true; } @@ -532,7 +527,7 @@ impl) -> bool { + fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool { if !ty.is_known_rigid() { return true; } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 6962a7ab1d727..7e905da0785f8 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,6 +1,6 @@ use crate::inherent::*; use crate::visit::Flags; -use crate::{self as ty, Interner, Ty}; +use crate::{self as ty, Interner}; bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards @@ -430,7 +430,7 @@ impl FlagComputation { } } - fn add_ty(&mut self, ty: Ty) { + fn add_ty(&mut self, ty: I::Ty) { self.add_flags(ty.flags()); self.add_exclusive_binder(ty.outer_exclusive_binder()); } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index ef162b21b660e..d1a50599e8b9c 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -135,7 +135,7 @@ pub trait TypeFolder: Sized { t.super_fold_with(self) } - fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { t.super_fold_with(self) } @@ -177,7 +177,7 @@ pub trait FallibleTypeFolder: Sized { t.try_super_fold_with(self) } - fn try_fold_ty(&mut self, t: ty::Ty) -> Result, Self::Error> { + fn try_fold_ty(&mut self, t: I::Ty) -> Result { t.try_super_fold_with(self) } @@ -408,7 +408,7 @@ impl TypeFolder for Shifter { } } - fn fold_ty(&mut self, ty: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { match ty.kind() { ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty) if debruijn >= self.current_index => @@ -538,7 +538,7 @@ where } } - fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { if t.has_type_flags( TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_RE_BOUND | TypeFlags::HAS_RE_ERASED, ) { diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index 22a4ebd03b69c..5d612740fdd84 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -3,7 +3,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::GenericTypeVisitable; -use crate::{Interner, Ty}; +use crate::Interner; #[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)] #[derive(GenericTypeVisitable)] @@ -13,7 +13,7 @@ use crate::{Interner, Ty}; )] pub enum GenericArgKind { Lifetime(I::Region), - Type(Ty), + Type(I::Ty), Const(I::Const), } @@ -26,7 +26,7 @@ impl Eq for GenericArgKind {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub enum TermKind { - Ty(Ty), + Ty(I::Ty), Const(I::Const), } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 843d1eb37b7d9..feafcee7bad9e 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -6,7 +6,7 @@ use crate::fold::TypeFoldable; use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::{self as ty, Interner, Ty, TyVid}; +use crate::{self as ty, Interner, TyVid}; /// The current typing mode of an inference context. We unfortunately have some /// slightly different typing rules depending on the current context. See the @@ -161,9 +161,12 @@ pub trait InferCtxtLike: Sized { fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid; fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; - fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> Ty; - fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty; - fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty; + fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; + fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; + fn opportunistic_resolve_float_var( + &self, + vid: ty::FloatVid, + ) -> ::Ty; fn opportunistic_resolve_ct_var( &self, vid: ty::ConstVid, @@ -176,7 +179,7 @@ pub trait InferCtxtLike: Sized { fn is_changed_arg(&self, arg: ::GenericArg) -> bool; fn next_region_infer(&self) -> ::Region; - fn next_ty_infer(&self) -> Ty; + fn next_ty_infer(&self) -> ::Ty; fn next_const_infer(&self) -> ::Const; fn fresh_args_for_item( &self, @@ -206,7 +209,7 @@ pub trait InferCtxtLike: Sized { target_is_expected: bool, target_vid: ty::TyVid, instantiation_variance: ty::Variance, - source_ty: Ty, + source_ty: ::Ty, ) -> RelateResult; fn instantiate_int_var_raw(&self, vid: ty::IntVid, value: ty::IntVarValue); fn instantiate_float_var_raw(&self, vid: ty::FloatVid, value: ty::FloatVarValue); @@ -220,7 +223,10 @@ pub trait InferCtxtLike: Sized { fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); - fn shallow_resolve(&self, ty: Ty) -> Ty; + fn shallow_resolve( + &self, + ty: ::Ty, + ) -> ::Ty; fn shallow_resolve_const( &self, ty: ::Const, @@ -248,7 +254,7 @@ pub trait InferCtxtLike: Sized { fn register_ty_outlives( &self, - ty: Ty, + ty: ::Ty, r: ::Region, span: ::Span, ); @@ -257,26 +263,26 @@ pub trait InferCtxtLike: Sized { fn opaque_types_storage_num_entries(&self) -> Self::OpaqueTypeStorageEntries; fn clone_opaque_types_lookup_table( &self, - ) -> Vec<(ty::OpaqueTypeKey, Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; fn clone_duplicate_opaque_types( &self, - ) -> Vec<(ty::OpaqueTypeKey, Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; fn clone_opaque_types_added_since( &self, prev_entries: Self::OpaqueTypeStorageEntries, - ) -> Vec<(ty::OpaqueTypeKey, Ty)>; + ) -> Vec<(ty::OpaqueTypeKey, ::Ty)>; fn opaques_with_sub_unified_hidden_type(&self, ty: TyVid) -> Vec>; fn register_hidden_type_in_storage( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: Ty, + hidden_ty: ::Ty, span: ::Span, - ) -> Option>; + ) -> Option<::Ty>; fn add_duplicate_opaque_type( &self, opaque_type_key: ty::OpaqueTypeKey, - hidden_ty: Ty, + hidden_ty: ::Ty, span: ::Span, ); diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 45590561d9d08..fcadeb6174812 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -108,7 +108,7 @@ pub trait Ty>: fn new_slice(interner: I, ty: Self) -> Self; - fn new_tup(interner: I, tys: &[ty::Ty]) -> Self; + fn new_tup(interner: I, tys: &[I::Ty]) -> Self; fn new_tup_from_iter(interner: I, iter: It) -> T::Output where @@ -121,7 +121,7 @@ pub trait Ty>: fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; - fn new_unsafe_binder(interner: I, ty: ty::Binder>) -> Self; + fn new_unsafe_binder(interner: I, ty: ty::Binder) -> Self; fn tuple_fields(self) -> I::Tys; @@ -158,7 +158,7 @@ pub trait Ty>: self.kind().fn_sig(interner) } - fn discriminant_ty(self, interner: I) -> ty::Ty; + fn discriminant_ty(self, interner: I) -> I::Ty; fn is_known_rigid(self) -> bool { self.kind().is_known_rigid() @@ -198,11 +198,11 @@ pub trait Ty>: } pub trait Tys>: - Copy + Debug + Hash + Eq + SliceLike> + TypeFoldable + Default + Copy + Debug + Hash + Eq + SliceLike + TypeFoldable + Default { fn inputs(self) -> I::FnInputTys; - fn output(self) -> ty::Ty; + fn output(self) -> I::Ty; } pub trait Abi>: Copy + Debug + Hash + Eq { @@ -290,7 +290,7 @@ pub trait Const>: } pub trait ValueConst>: Copy + Debug + Hash + Eq { - fn ty(self) -> ty::Ty; + fn ty(self) -> I::Ty; fn valtree(self) -> I::ValTree; } @@ -310,7 +310,7 @@ pub trait GenericArg>: + IntoKind> + TypeVisitable + Relate - + From> + + From + From + From + From @@ -323,11 +323,11 @@ pub trait GenericArg>: } } - fn as_type(&self) -> Option> { + fn as_type(&self) -> Option { if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> ty::Ty { + fn expect_ty(&self) -> I::Ty { self.as_type().expect("expected a type") } @@ -359,11 +359,11 @@ pub trait GenericArg>: pub trait Term>: Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate { - fn as_type(&self) -> Option> { + fn as_type(&self) -> Option { if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } } - fn expect_ty(&self) -> ty::Ty { + fn expect_ty(&self) -> I::Ty { self.as_type().expect("expected a type, but found a const") } @@ -413,7 +413,7 @@ pub trait GenericArgs>: target: I::GenericArgs, ) -> I::GenericArgs; - fn type_at(self, i: usize) -> ty::Ty; + fn type_at(self, i: usize) -> I::Ty; fn region_at(self, i: usize) -> I::Region; @@ -459,7 +459,7 @@ pub trait Predicate>: + UpcastFrom> + UpcastFrom>> + UpcastFrom> - + UpcastFrom>> + + UpcastFrom> + UpcastFrom> + IntoKind>> + Elaboratable @@ -578,7 +578,7 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { /// Returns the type of the struct tail. /// /// Expects the `AdtDef` to be a struct. If it is not, then this will panic. - fn struct_tail_ty(self, interner: I) -> Option>>; + fn struct_tail_ty(self, interner: I) -> Option>; fn is_phantom_data(self) -> bool; @@ -591,13 +591,13 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { ) -> Option>; // FIXME: perhaps use `all_fields` and expose `FieldDef`. - fn all_field_tys(self, interner: I) -> ty::EarlyBinder>>; + fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; fn sizedness_constraint( self, interner: I, sizedness: SizedTraitKind, - ) -> Option>>; + ) -> Option>; fn is_fundamental(self) -> bool; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 6c838cf8a48ac..a0b444024ca79 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -31,7 +31,6 @@ pub mod outlives; pub mod relate; pub mod search_graph; pub mod solve; -pub mod sty; pub mod walk; // These modules are not `pub` since they are glob-imported. @@ -79,7 +78,6 @@ pub use predicate_kind::*; pub use region_kind::*; pub use rustc_ast_ir::{FloatTy, IntTy, Movability, Mutability, Pinnedness, UintTy}; use rustc_type_ir_macros::GenericTypeVisitable; -pub use sty::*; pub use ty_info::*; pub use ty_kind::*; pub use upcast::*; @@ -445,8 +443,8 @@ impl fmt::Display for ClosureKind { } pub struct FieldInfo { - pub base: Ty, - pub ty: Ty, + pub base: I::Ty, + pub ty: I::Ty, pub variant: Option, pub variant_idx: VariantIdx, pub name: I::Symbol, diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index cc79d6589e6fb..300e5c0b46956 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -8,7 +8,7 @@ use smallvec::{SmallVec, smallvec}; use crate::data_structures::SsoHashSet; use crate::inherent::*; use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _, TypeVisitor}; -use crate::{self as ty, Interner, Ty}; +use crate::{self as ty, Interner}; #[derive_where(Debug; I: Interner)] pub enum Component { @@ -55,7 +55,7 @@ pub enum Component { /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**. pub fn push_outlives_components( cx: I, - ty: Ty, + ty: I::Ty, out: &mut SmallVec<[Component; 4]>, ) { ty.visit_with(&mut OutlivesCollector { cx, out, visited: Default::default() }); @@ -64,14 +64,14 @@ pub fn push_outlives_components( struct OutlivesCollector<'a, I: Interner> { cx: I, out: &'a mut SmallVec<[Component; 4]>, - visited: SsoHashSet>, + visited: SsoHashSet, } impl TypeVisitor for OutlivesCollector<'_, I> { #[cfg(not(feature = "nightly"))] type Result = (); - fn visit_ty(&mut self, ty: Ty) -> Self::Result { + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { if !self.visited.insert(ty) { return; } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index f4975f3ad4486..113192cc02eb8 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -101,7 +101,7 @@ impl TraitRef { ) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { TraitRef::new( interner, self.def_id, @@ -110,13 +110,13 @@ impl TraitRef { } #[inline] - pub fn self_ty(&self) -> ty::Ty { + pub fn self_ty(&self) -> I::Ty { self.args.type_at(0) } } impl ty::Binder> { - pub fn self_ty(&self) -> ty::Binder> { + pub fn self_ty(&self) -> ty::Binder { self.map_bound_ref(|tr| tr.self_ty()) } @@ -152,7 +152,7 @@ pub struct TraitPredicate { impl Eq for TraitPredicate {} impl TraitPredicate { - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), polarity: self.polarity, @@ -163,7 +163,7 @@ impl TraitPredicate { self.trait_ref.def_id } - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.trait_ref.self_ty() } } @@ -174,7 +174,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder> { + pub fn self_ty(self) -> ty::Binder { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -307,7 +307,7 @@ impl ty::Binder> { /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). - pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> I::Clause { + pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause { match self.skip_binder() { ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx), ExistentialPredicate::Projection(p) => { @@ -384,7 +384,7 @@ impl ExistentialTraitRef { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(self, interner: I, self_ty: ty::Ty) -> TraitRef { + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -401,7 +401,7 @@ impl ty::Binder> { /// we convert the principal trait-ref into a normal trait-ref, /// you must give *some* self type. A common choice is `mk_err()` /// or some placeholder type. - pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty)) } } @@ -459,7 +459,7 @@ impl ExistentialProjection { ExistentialTraitRef::new_from_args(interner, def_id.try_into().unwrap(), args) } - pub fn with_self_ty(&self, interner: I, self_ty: ty::Ty) -> ProjectionPredicate { + pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { // otherwise the escaping regions would be captured by the binders debug_assert!(!self_ty.has_escaping_bound_vars()); @@ -487,7 +487,7 @@ impl ExistentialProjection { } impl ty::Binder> { - pub fn with_self_ty(&self, cx: I, self_ty: ty::Ty) -> ty::Binder> { + pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder> { self.map_bound(|p| p.with_self_ty(cx, self_ty)) } @@ -683,11 +683,11 @@ impl AliasTerm { /// The following methods work only with (trait) associated term projections. impl AliasTerm { - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { AliasTerm::new( interner, self.def_id, @@ -796,11 +796,11 @@ pub struct ProjectionPredicate { impl Eq for ProjectionPredicate {} impl ProjectionPredicate { - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.projection_term.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> ProjectionPredicate { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { Self { projection_term: self.projection_term.with_replaced_self_ty(interner, self_ty), ..self @@ -859,11 +859,11 @@ pub struct NormalizesTo { impl Eq for NormalizesTo {} impl NormalizesTo { - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.alias.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> NormalizesTo { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo { Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self } } @@ -896,11 +896,11 @@ pub struct HostEffectPredicate { impl Eq for HostEffectPredicate {} impl HostEffectPredicate { - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.trait_ref.self_ty() } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self } } @@ -915,7 +915,7 @@ impl ty::Binder> { self.skip_binder().def_id() } - pub fn self_ty(self) -> ty::Binder> { + pub fn self_ty(self) -> ty::Binder { self.map_bound(|trait_ref| trait_ref.self_ty()) } @@ -936,8 +936,8 @@ impl ty::Binder> { )] pub struct SubtypePredicate { pub a_is_expected: bool, - pub a: ty::Ty, - pub b: ty::Ty, + pub a: I::Ty, + pub b: I::Ty, } impl Eq for SubtypePredicate {} @@ -950,8 +950,8 @@ impl Eq for SubtypePredicate {} derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) )] pub struct CoercePredicate { - pub a: ty::Ty, - pub b: ty::Ty, + pub a: I::Ty, + pub b: I::Ty, } impl Eq for CoercePredicate {} diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index b6ff27fb238e6..445e85a888fca 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::{self as ty, Interner, Ty}; +use crate::{self as ty, Interner}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. @@ -25,7 +25,7 @@ pub enum ClauseKind { RegionOutlives(ty::OutlivesPredicate), /// `where T: 'r` - TypeOutlives(ty::OutlivesPredicate>), + TypeOutlives(ty::OutlivesPredicate), /// `where ::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. @@ -33,7 +33,7 @@ pub enum ClauseKind { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. - ConstArgHasType(I::Const, Ty), + ConstArgHasType(I::Const, I::Ty), /// No syntax: `T` well-formed. WellFormed(I::Term), diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 31248bea4cf85..d33c6036dadd8 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -44,7 +44,7 @@ pub enum VarianceDiagInfo { Invariant { /// The generic type containing the generic parameter /// that changes the variance (e.g. `*mut T`, `MyStruct`) - ty: ty::Ty, + ty: I::Ty, /// The index of the generic parameter being used /// (e.g. `0` for `*mut T`, `1` for `MyStruct<'CovariantParam, 'InvariantParam>`) param_index: u32, @@ -75,13 +75,13 @@ pub trait TypeRelation: Sized { fn relate_ty_args( &mut self, - a_ty: ty::Ty, - b_ty: ty::Ty, + a_ty: I::Ty, + b_ty: I::Ty, ty_def_id: I::DefId, a_arg: I::GenericArgs, b_arg: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> ty::Ty, - ) -> RelateResult>; + mk: impl FnOnce(I::GenericArgs) -> I::Ty, + ) -> RelateResult; /// Switch variance for the purpose of relating `a` and `b`. fn relate_with_variance>( @@ -98,7 +98,7 @@ pub trait TypeRelation: Sized { // additional hooks for other types in the future if needed // without making older code, which called `relate`, obsolete. - fn tys(&mut self, a: ty::Ty, b: ty::Ty) -> RelateResult>; + fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult; fn regions(&mut self, a: I::Region, b: I::Region) -> RelateResult; @@ -332,9 +332,9 @@ impl Relate for ty::ExistentialTraitRef { #[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys>( relation: &mut R, - a: ty::Ty, - b: ty::Ty, -) -> RelateResult> { + a: I::Ty, + b: I::Ty, +) -> RelateResult { let cx = relation.cx(); match (a.kind(), b.kind()) { (ty::Infer(_), _) | (_, ty::Infer(_)) => { diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 11fbbf89b9c7b..64b87fac77f94 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -39,15 +39,15 @@ where ); /// Register `AliasRelate` obligation(s) that both types must be related to each other. - fn register_alias_relate_predicate(&mut self, a: ty::Ty, b: ty::Ty); + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty); } pub fn super_combine_tys( infcx: &Infcx, relation: &mut R, - a: ty::Ty, - b: ty::Ty, -) -> RelateResult> + a: I::Ty, + b: I::Ty, +) -> RelateResult where Infcx: InferCtxtLike, I: Interner, @@ -226,13 +226,13 @@ where pub fn combine_ty_args( infcx: &Infcx, relation: &mut R, - a_ty: ty::Ty, - b_ty: ty::Ty, + a_ty: I::Ty, + b_ty: I::Ty, variances: I::VariancesOf, a_args: I::GenericArgs, b_args: I::GenericArgs, - mk: impl FnOnce(I::GenericArgs) -> ty::Ty, -) -> RelateResult> + mk: impl FnOnce(I::GenericArgs) -> I::Ty, +) -> RelateResult where Infcx: InferCtxtLike, I: Interner, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 1494d67d3c603..82ee4f75fcb0a 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -5,7 +5,7 @@ use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::Goal; -use crate::{self as ty, InferCtxtLike, Interner, Ty}; +use crate::{self as ty, InferCtxtLike, Interner}; pub trait RelateExt: InferCtxtLike { fn relate>( @@ -104,7 +104,7 @@ pub struct SolverRelating<'infcx, Infcx, I: Interner> { /// constrain `?1` to `u32`. When using the cache entry from the /// first time we've related these types, this only happens when /// later proving the `Subtype(?0, ?1)` goal from the first relation. - cache: DelayedSet<(ty::Variance, Ty, Ty)>, + cache: DelayedSet<(ty::Variance, I::Ty, I::Ty)>, } impl<'infcx, Infcx, I> SolverRelating<'infcx, Infcx, I> @@ -142,13 +142,13 @@ where fn relate_ty_args( &mut self, - a_ty: Ty, - b_ty: Ty, + a_ty: I::Ty, + b_ty: I::Ty, def_id: I::DefId, a_args: I::GenericArgs, b_args: I::GenericArgs, - _: impl FnOnce(I::GenericArgs) -> Ty, - ) -> RelateResult> { + _: impl FnOnce(I::GenericArgs) -> I::Ty, + ) -> RelateResult { if self.ambient_variance == ty::Invariant { // Avoid fetching the variance if we are in an invariant // context; no need, and it can induce dependency cycles @@ -178,7 +178,7 @@ where } #[instrument(skip(self), level = "trace")] - fn tys(&mut self, a: Ty, b: Ty) -> RelateResult> { + fn tys(&mut self, a: I::Ty, b: I::Ty) -> RelateResult { if a == b { return Ok(a); } @@ -383,7 +383,7 @@ where self.goals.extend(obligations); } - fn register_alias_relate_predicate(&mut self, a: Ty, b: Ty) { + fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) { self.register_predicates([ty::Binder::dummy(match self.ambient_variance { ty::Covariant => ty::PredicateKind::AliasRelate( a.into(), diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 23e6075452b18..72b7df22b30d5 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -11,7 +11,7 @@ use rustc_type_ir_macros::{ use crate::lang_items::SolverTraitLangItem; use crate::search_graph::PathKind; -use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Ty, Upcast}; +use crate::{self as ty, Canonical, CanonicalVarValues, Interner, Upcast}; pub type CanonicalInput::Predicate> = ty::CanonicalQueryInput>; @@ -254,7 +254,7 @@ impl Eq for Response {} #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub struct ExternalConstraintsData { pub region_constraints: Vec>, - pub opaque_types: Vec<(ty::OpaqueTypeKey, Ty)>, + pub opaque_types: Vec<(ty::OpaqueTypeKey, I::Ty)>, pub normalization_nested_goals: NestedNormalizationGoals, } diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs deleted file mode 100644 index 5b73d372384b8..0000000000000 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -/// This type is temporary and exists to cut down the bloat of further PR's -/// moving `struct Ty` from `rustc_middle` to `rustc_type_ir`. -pub type Ty = ::Ty; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index ad7a934bb28a5..9afd39e2c7627 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -100,7 +100,7 @@ pub enum TyKind { Str, /// An array with the given length. Written as `[T; N]`. - Array(ty::Ty, I::Const), + Array(I::Ty, I::Const), /// A pattern newtype. /// @@ -109,17 +109,17 @@ pub enum TyKind { /// Only `Copy` and `Clone` will automatically get implemented for pattern types. /// Auto-traits treat this as if it were an aggregate with a single nested type. /// Only supports integer range patterns for now. - Pat(ty::Ty, I::Pat), + Pat(I::Ty, I::Pat), /// The pointee of an array slice. Written as `[T]`. - Slice(ty::Ty), + Slice(I::Ty), /// A raw pointer. Written as `*mut T` or `*const T` - RawPtr(ty::Ty, Mutability), + RawPtr(I::Ty, Mutability), /// A reference; a pointer with an associated lifetime. Written as /// `&'a mut T` or `&'a T`. - Ref(I::Region, ty::Ty, Mutability), + Ref(I::Region, I::Ty, Mutability), /// The anonymous type of a function declaration/definition. /// @@ -469,18 +469,18 @@ impl AliasTy { matches!(self.kind(interner), AliasTyKind::Opaque) } - pub fn to_ty(self, interner: I) -> ty::Ty { + pub fn to_ty(self, interner: I) -> I::Ty { Ty::new_alias(interner, self.kind(interner), self) } } /// The following methods work only with (trait) associated type projections. impl AliasTy { - pub fn self_ty(self) -> ty::Ty { + pub fn self_ty(self) -> I::Ty { self.args.type_at(0) } - pub fn with_replaced_self_ty(self, interner: I, self_ty: ty::Ty) -> Self { + pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { AliasTy::new( interner, self.def_id, @@ -735,7 +735,7 @@ impl fmt::Debug for InferTy { )] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct TypeAndMut { - pub ty: ty::Ty, + pub ty: I::Ty, pub mutbl: Mutability, } @@ -765,7 +765,7 @@ impl FnSig { self.inputs_and_output.inputs() } - pub fn output(self) -> ty::Ty { + pub fn output(self) -> I::Ty { self.inputs_and_output.output() } @@ -783,7 +783,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder> { + pub fn input(self, index: usize) -> ty::Binder { self.map_bound(|fn_sig| fn_sig.inputs().get(index).unwrap()) } @@ -792,7 +792,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder> { + pub fn output(self) -> ty::Binder { self.map_bound(|fn_sig| fn_sig.output()) } @@ -856,21 +856,21 @@ impl fmt::Debug for FnSig { } // FIXME: this is a distinct type because we need to define `Encode`/`Decode` -// impls in this crate for `Binder>`. +// impls in this crate for `Binder`. #[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -pub struct UnsafeBinderInner(ty::Binder>); +pub struct UnsafeBinderInner(ty::Binder); impl Eq for UnsafeBinderInner {} -impl From>> for UnsafeBinderInner { - fn from(value: ty::Binder>) -> Self { +impl From> for UnsafeBinderInner { + fn from(value: ty::Binder) -> Self { UnsafeBinderInner(value) } } -impl From> for ty::Binder> { +impl From> for ty::Binder { fn from(value: UnsafeBinderInner) -> Self { value.0 } @@ -883,7 +883,7 @@ impl fmt::Debug for UnsafeBinderInner { } impl Deref for UnsafeBinderInner { - type Target = ty::Binder>; + type Target = ty::Binder; fn deref(&self) -> &Self::Target { &self.0 @@ -894,7 +894,7 @@ impl Deref for UnsafeBinderInner { impl rustc_serialize::Encodable for UnsafeBinderInner where - ty::Ty: rustc_serialize::Encodable, + I::Ty: rustc_serialize::Encodable, I::BoundVarKinds: rustc_serialize::Encodable, { fn encode(&self, e: &mut E) { @@ -907,7 +907,7 @@ where impl rustc_serialize::Decodable for UnsafeBinderInner where - ty::Ty: TypeVisitable + rustc_serialize::Decodable, + I::Ty: TypeVisitable + rustc_serialize::Decodable, I::BoundVarKinds: rustc_serialize::Decodable, { fn decode(decoder: &mut D) -> Self { @@ -937,7 +937,7 @@ impl FnSigTys { self.inputs_and_output.inputs() } - pub fn output(self) -> ty::Ty { + pub fn output(self) -> I::Ty { self.inputs_and_output.output() } } @@ -960,7 +960,7 @@ impl ty::Binder> { #[inline] #[track_caller] - pub fn input(self, index: usize) -> ty::Binder> { + pub fn input(self, index: usize) -> ty::Binder { self.map_bound(|sig_tys| sig_tys.inputs().get(index).unwrap()) } @@ -969,7 +969,7 @@ impl ty::Binder> { } #[inline] - pub fn output(self) -> ty::Binder> { + pub fn output(self) -> ty::Binder { self.map_bound(|sig_tys| sig_tys.output()) } } diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 08c303b8de9c8..e8f94c8e7cc92 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -121,13 +121,13 @@ pub struct ClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: ty::Ty, + pub closure_kind_ty: I::Ty, /// Captures the closure's signature. This closure signature is "tupled", and /// thus has a peculiar signature of `extern "rust-call" fn((Args, ...)) -> Ty`. - pub closure_sig_as_fn_ptr_ty: ty::Ty, + pub closure_sig_as_fn_ptr_ty: I::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: ty::Ty, + pub tupled_upvars_ty: I::Ty, } impl ClosureArgs { @@ -169,14 +169,14 @@ impl ClosureArgs { /// Returns the tuple type representing the upvars for this closure. #[inline] - pub fn tupled_upvars_ty(self) -> ty::Ty { + pub fn tupled_upvars_ty(self) -> I::Ty { self.split().tupled_upvars_ty } /// Returns the closure kind for this closure; may return a type /// variable during inference. To get the closure kind during /// inference, use `infcx.closure_kind(args)`. - pub fn kind_ty(self) -> ty::Ty { + pub fn kind_ty(self) -> I::Ty { self.split().closure_kind_ty } @@ -185,7 +185,7 @@ impl ClosureArgs { // FIXME(eddyb) this should be unnecessary, as the shallowly resolved // type is known at the time of the creation of `ClosureArgs`, // see `rustc_hir_analysis::check::closure`. - pub fn sig_as_fn_ptr_ty(self) -> ty::Ty { + pub fn sig_as_fn_ptr_ty(self) -> I::Ty { self.split().closure_sig_as_fn_ptr_ty } @@ -223,7 +223,7 @@ pub struct CoroutineClosureArgsParts { /// This is the args of the typeck root. pub parent_args: I::GenericArgsSlice, /// Represents the maximum calling capability of the closure. - pub closure_kind_ty: ty::Ty, + pub closure_kind_ty: I::Ty, /// Represents all of the relevant parts of the coroutine returned by this /// coroutine-closure. This signature parts type will have the general /// shape of `fn(tupled_inputs, resume_ty) -> (return_ty, yield_ty)`, where @@ -232,10 +232,10 @@ pub struct CoroutineClosureArgsParts { /// /// Use `coroutine_closure_sig` to break up this type rather than using it /// yourself. - pub signature_parts_ty: ty::Ty, + pub signature_parts_ty: I::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: ty::Ty, + pub tupled_upvars_ty: I::Ty, /// a function pointer that has the shape `for<'env> fn() -> (&'env T, ...)`. /// This allows us to represent the binder of the self-captures of the closure. /// @@ -243,7 +243,7 @@ pub struct CoroutineClosureArgsParts { /// from the closure's upvars, this will be `for<'env> fn() -> (&'env String,)`, /// while the `tupled_upvars_ty`, representing the by-move version of the same /// captures, will be `(String,)`. - pub coroutine_captures_by_ref_ty: ty::Ty, + pub coroutine_captures_by_ref_ty: I::Ty, } impl CoroutineClosureArgs { @@ -277,11 +277,11 @@ impl CoroutineClosureArgs { } #[inline] - pub fn tupled_upvars_ty(self) -> ty::Ty { + pub fn tupled_upvars_ty(self) -> I::Ty { self.split().tupled_upvars_ty } - pub fn kind_ty(self) -> ty::Ty { + pub fn kind_ty(self) -> I::Ty { self.split().closure_kind_ty } @@ -289,7 +289,7 @@ impl CoroutineClosureArgs { self.kind_ty().to_opt_closure_kind().unwrap() } - pub fn signature_parts_ty(self) -> ty::Ty { + pub fn signature_parts_ty(self) -> I::Ty { self.split().signature_parts_ty } @@ -314,7 +314,7 @@ impl CoroutineClosureArgs { }) } - pub fn coroutine_captures_by_ref_ty(self) -> ty::Ty { + pub fn coroutine_captures_by_ref_ty(self) -> I::Ty { self.split().coroutine_captures_by_ref_ty } @@ -358,10 +358,10 @@ impl TypeVisitor for HasRegionsBoundAt { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct CoroutineClosureSignature { - pub tupled_inputs_ty: ty::Ty, - pub resume_ty: ty::Ty, - pub yield_ty: ty::Ty, - pub return_ty: ty::Ty, + pub tupled_inputs_ty: I::Ty, + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, // Like the `fn_sig_as_fn_ptr_ty` of a regular closure, these types // never actually differ. But we save them rather than recreating them @@ -393,10 +393,10 @@ impl CoroutineClosureSignature { self, cx: I, parent_args: I::GenericArgsSlice, - coroutine_kind_ty: ty::Ty, + coroutine_kind_ty: I::Ty, coroutine_def_id: I::CoroutineId, - tupled_upvars_ty: ty::Ty, - ) -> ty::Ty { + tupled_upvars_ty: I::Ty, + ) -> I::Ty { let coroutine_args = ty::CoroutineArgs::new( cx, ty::CoroutineArgsParts { @@ -424,9 +424,9 @@ impl CoroutineClosureSignature { coroutine_def_id: I::CoroutineId, goal_kind: ty::ClosureKind, env_region: I::Region, - closure_tupled_upvars_ty: ty::Ty, - coroutine_captures_by_ref_ty: ty::Ty, - ) -> ty::Ty { + closure_tupled_upvars_ty: I::Ty, + coroutine_captures_by_ref_ty: I::Ty, + ) -> I::Ty { let tupled_upvars_ty = Self::tupled_upvars_by_closure_kind( cx, goal_kind, @@ -457,11 +457,11 @@ impl CoroutineClosureSignature { pub fn tupled_upvars_by_closure_kind( cx: I, kind: ty::ClosureKind, - tupled_inputs_ty: ty::Ty, - closure_tupled_upvars_ty: ty::Ty, - coroutine_captures_by_ref_ty: ty::Ty, + tupled_inputs_ty: I::Ty, + closure_tupled_upvars_ty: I::Ty, + coroutine_captures_by_ref_ty: I::Ty, env_region: I::Region, - ) -> ty::Ty { + ) -> I::Ty { match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { @@ -503,7 +503,7 @@ struct FoldEscapingRegions { // Depends on `debruijn` because we may have types with regions of different // debruijn depths depending on the binders we've entered. - cache: DelayedMap<(ty::DebruijnIndex, ty::Ty), ty::Ty>, + cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>, } impl TypeFolder for FoldEscapingRegions { @@ -511,7 +511,7 @@ impl TypeFolder for FoldEscapingRegions { self.interner } - fn fold_ty(&mut self, t: ty::Ty) -> ty::Ty { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { if !t.has_vars_bound_at_or_above(self.debruijn) { t } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) { @@ -553,9 +553,9 @@ impl TypeFolder for FoldEscapingRegions { #[derive_where(Clone, Copy, PartialEq, Hash, Debug; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] pub struct GenSig { - pub resume_ty: ty::Ty, - pub yield_ty: ty::Ty, - pub return_ty: ty::Ty, + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, } impl Eq for GenSig {} @@ -581,15 +581,15 @@ pub struct CoroutineArgsParts { /// kind: `i8`/`i16`/`i32`. /// /// For regular coroutines, this field will always just be `()`. - pub kind_ty: ty::Ty, + pub kind_ty: I::Ty, - pub resume_ty: ty::Ty, - pub yield_ty: ty::Ty, - pub return_ty: ty::Ty, + pub resume_ty: I::Ty, + pub yield_ty: I::Ty, + pub return_ty: I::Ty, /// The upvars captured by the closure. Remains an inference variable /// until the upvar analysis, which happens late in HIR typeck. - pub tupled_upvars_ty: ty::Ty, + pub tupled_upvars_ty: I::Ty, } impl CoroutineArgs { @@ -619,7 +619,7 @@ impl CoroutineArgs { } // Returns the kind of the coroutine. See docs on the `kind_ty` field. - pub fn kind_ty(self) -> ty::Ty { + pub fn kind_ty(self) -> I::Ty { self.split().kind_ty } @@ -638,22 +638,22 @@ impl CoroutineArgs { /// Returns the tuple type representing the upvars for this coroutine. #[inline] - pub fn tupled_upvars_ty(self) -> ty::Ty { + pub fn tupled_upvars_ty(self) -> I::Ty { self.split().tupled_upvars_ty } /// Returns the type representing the resume type of the coroutine. - pub fn resume_ty(self) -> ty::Ty { + pub fn resume_ty(self) -> I::Ty { self.split().resume_ty } /// Returns the type representing the yield type of the coroutine. - pub fn yield_ty(self) -> ty::Ty { + pub fn yield_ty(self) -> I::Ty { self.split().yield_ty } /// Returns the type representing the return type of the coroutine. - pub fn return_ty(self) -> ty::Ty { + pub fn return_ty(self) -> I::Ty { self.split().return_ty } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 1ee4bff6b7a11..6e62e1031a969 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, Ty, TypeFlags}; +use crate::{self as ty, Interner, TypeFlags}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -98,7 +98,7 @@ pub trait TypeVisitor: Sized { t.super_visit_with(self) } - fn visit_ty(&mut self, t: Ty) -> Self::Result { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { t.super_visit_with(self) } @@ -417,7 +417,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_ty(&mut self, t: Ty) -> Self::Result { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // Note: no `super_visit_with` call. let flags = t.flags(); if flags.intersects(self.flags) { @@ -522,7 +522,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } #[inline] - fn visit_ty(&mut self, t: Ty) -> Self::Result { + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `t` contains some content // bound at `outer_index` or above (because From 0e2c554e74754ddb51363d2f216d1367ff64e4f4 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:12:32 +0200 Subject: [PATCH 56/61] rename opaque_generic_const_args to generic_const_args --- compiler/rustc_feature/src/unstable.rs | 6 +++--- compiler/rustc_hir_analysis/src/collect.rs | 12 ++++++------ .../rustc_hir_analysis/src/collect/generics_of.rs | 4 ++-- .../rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 6 +++--- .../src/solve/normalizes_to/anon_const.rs | 6 +++--- compiler/rustc_resolve/src/diagnostics.rs | 6 +++--- compiler/rustc_resolve/src/errors.rs | 6 +++--- compiler/rustc_resolve/src/ident.rs | 10 ++-------- compiler/rustc_resolve/src/late/diagnostics.rs | 4 ++-- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- compiler/rustc_trait_selection/src/traits/mod.rs | 4 ++-- compiler/rustc_type_ir/src/const_kind.rs | 4 ++-- .../ui/const-generics/{ogca => gca}/basic-fail.rs | 2 +- .../const-generics/{ogca => gca}/basic-fail.stderr | 0 tests/ui/const-generics/{ogca => gca}/basic.rs | 2 +- .../{ogca => gca}/coherence-ambiguous.rs | 2 +- .../{ogca => gca}/coherence-ambiguous.stderr | 0 .../{ogca => gca}/generic-param-rhs.rs | 2 +- .../{ogca => gca}/generic-param-rhs.stderr | 0 .../{ogca => gca}/rhs-but-not-root.rs | 4 ++-- .../{ogca => gca}/rhs-but-not-root.stderr | 0 .../const-generics/mgca/adt_expr_arg_simple.stderr | 2 +- .../mgca/early-bound-param-lt-bad.stderr | 2 +- .../mgca/explicit_anon_consts.stderr | 14 +++++++------- .../mgca/selftyalias-containing-param.stderr | 2 +- tests/ui/const-generics/mgca/selftyparam.stderr | 2 +- .../mgca/size-of-generic-ptr-in-array-len.stderr | 2 +- .../mgca/tuple_ctor_complex_args.stderr | 2 +- .../mgca/tuple_expr_arg_complex.stderr | 2 +- .../mgca/type_const-on-generic-expr.stderr | 4 ++-- .../mgca/type_const-on-generic_expr-2.stderr | 6 +++--- ...-args.rs => feature-gate-generic-const-args.rs} | 2 +- ...derr => feature-gate-generic-const-args.stderr} | 4 ++-- 34 files changed, 61 insertions(+), 67 deletions(-) rename tests/ui/const-generics/{ogca => gca}/basic-fail.rs (91%) rename tests/ui/const-generics/{ogca => gca}/basic-fail.stderr (100%) rename tests/ui/const-generics/{ogca => gca}/basic.rs (90%) rename tests/ui/const-generics/{ogca => gca}/coherence-ambiguous.rs (84%) rename tests/ui/const-generics/{ogca => gca}/coherence-ambiguous.stderr (100%) rename tests/ui/const-generics/{ogca => gca}/generic-param-rhs.rs (79%) rename tests/ui/const-generics/{ogca => gca}/generic-param-rhs.stderr (100%) rename tests/ui/const-generics/{ogca => gca}/rhs-but-not-root.rs (77%) rename tests/ui/const-generics/{ogca => gca}/rhs-but-not-root.stderr (100%) rename tests/ui/feature-gates/{feature-gate-opaque-generic-const-args.rs => feature-gate-generic-const-args.rs} (80%) rename tests/ui/feature-gates/{feature-gate-opaque-generic-const-args.stderr => feature-gate-generic-const-args.stderr} (57%) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 224b7273314b5..a9ad07be319c3 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -520,6 +520,8 @@ declare_features! ( (unstable, frontmatter, "1.88.0", Some(136889)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), + /// Allows using generics in more complex const expressions, based on definitional equality. + (unstable, generic_const_args, "1.95.0", Some(151972)), /// Allows non-trivial generic constants which have to have wfness manually propagated to callers (incomplete, generic_const_exprs, "1.56.0", Some(76560)), /// Allows generic parameters and where-clauses on free & associated const items. @@ -623,8 +625,6 @@ declare_features! ( (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using fields with slice type in offset_of! (unstable, offset_of_slice, "1.81.0", Some(126151)), - /// Allows using generics in more complex const expressions, based on definitional equality. - (unstable, opaque_generic_const_args, "1.95.0", Some(151972)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows specifying nop padding on functions for dynamic patching. @@ -806,6 +806,6 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ /// Some features require one or more other features to be enabled. pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ - (sym::opaque_generic_const_args, &[sym::min_generic_const_args]), + (sym::generic_const_args, &[sym::min_generic_const_args]), (sym::unsized_const_params, &[sym::adt_const_params]), ]; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 80ef2001cc72e..cfda0300f3f02 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1598,8 +1598,8 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().opaque_generic_const_args() { - // Only anon consts that are the RHS of a const item can be OGCA. + } else if tcx.features().generic_const_args() { + // Only anon consts that are the RHS of a const item can be GCA. // Note: We can't just check tcx.parent because it needs to be EXACTLY // the RHS, not just part of the RHS. if !is_anon_const_rhs_of_const_item(tcx, def) { @@ -1607,9 +1607,9 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } let body = tcx.hir_body_owned_by(def); - let mut visitor = OGCAParamVisitor(tcx); + let mut visitor = GCAParamVisitor(tcx); match visitor.visit_body(body) { - ControlFlow::Break(UsesParam) => ty::AnonConstKind::OGCA, + ControlFlow::Break(UsesParam) => ty::AnonConstKind::GCA, ControlFlow::Continue(()) => ty::AnonConstKind::MCG, } } else if tcx.features().min_generic_const_args() { @@ -1650,11 +1650,11 @@ fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) def_id == rhs_anon.def_id } -struct OGCAParamVisitor<'tcx>(TyCtxt<'tcx>); +struct GCAParamVisitor<'tcx>(TyCtxt<'tcx>); struct UsesParam; -impl<'tcx> Visitor<'tcx> for OGCAParamVisitor<'tcx> { +impl<'tcx> Visitor<'tcx> for GCAParamVisitor<'tcx> { type NestedFilter = nested_filter::OnlyBodies; type Result = ControlFlow; diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ea98beb955805..3647c91fb7f15 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -97,8 +97,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... ty::AnonConstKind::MCG => None, - // OGCA anon consts inherit their parent's generics. - ty::AnonConstKind::OGCA => Some(parent_did), + // GCA anon consts inherit their parent's generics. + ty::AnonConstKind::GCA => Some(parent_did), // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), 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 91660fc655377..9ec5632a74982 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -387,7 +387,7 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { fn error(&self) -> ErrorGuaranteed { let msg = if self.is_self_alias { "generic `Self` types are currently not permitted in anonymous constants" - } else if self.tcx.features().opaque_generic_const_args() { + } else if self.tcx.features().generic_const_args() { "generic parameters in const blocks are only allowed as the direct value of a `type const`" } else { "generic parameters may not be used in const operations" @@ -408,8 +408,8 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { } } if self.tcx.features().min_generic_const_args() { - if !self.tcx.features().opaque_generic_const_args() { - diag.help("add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items"); + if !self.tcx.features().generic_const_args() { + diag.help("add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items"); } else { diag.help("consider factoring the expression into a `type const` item and use it as the const argument instead"); } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index eb6a1b51421ca..894910dfb6c16 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -15,11 +15,11 @@ where goal: Goal>, ) -> QueryResult { if self.typing_mode() == TypingMode::Coherence - && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA + && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::GCA { - // During coherence, OGCA consts should be normalized ambiguously + // During coherence, GCA consts should be normalized ambiguously // because they are opaque but eventually resolved to a real value. - // We don't want two OGCAs that have the same value to be treated + // We don't want two GCAs that have the same value to be treated // as distinct for coherence purposes. (Just like opaque types.) // // We can't rely on evaluate_const below because that particular wrapper diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 97c88064e9799..cab37f5c0faa6 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1011,14 +1011,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ResolutionError::ParamInTyOfConstParam { name } => { self.dcx().create_err(errs::ParamInTyOfConstParam { span, name }) } - ResolutionError::ParamInNonTrivialAnonConst { is_ogca, name, param_kind: is_type } => { + ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => { self.dcx().create_err(errs::ParamInNonTrivialAnonConst { span, name, param_kind: is_type, help: self.tcx.sess.is_nightly_build(), - is_ogca, - help_ogca: is_ogca, + is_gca, + help_gca: is_gca, }) } ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index c9dad4dcd4a75..ea2eeb64acc42 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -407,7 +407,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( - "{$is_ogca -> + "{$is_gca -> [true] generic parameters in const blocks are only allowed as the direct value of a `type const` *[false] generic parameters may not be used in const operations }" @@ -421,11 +421,11 @@ pub(crate) struct ParamInNonTrivialAnonConst { pub(crate) param_kind: ParamKindInNonTrivialAnonConst, #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) help: bool, - pub(crate) is_ogca: bool, + pub(crate) is_gca: bool, #[help( "consider factoring the expression into a `type const` item and use it as the const argument instead" )] - pub(crate) help_ogca: bool, + pub(crate) help_gca: bool, } #[derive(Debug)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 069018139145d..b7561d58401ab 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1568,10 +1568,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_ogca: self - .tcx - .features() - .opaque_generic_const_args(), + is_gca: self.tcx.features().generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1663,10 +1660,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_ogca: self - .tcx - .features() - .opaque_generic_const_args(), + is_gca: self.tcx.features().generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cf048231bd607..7539e3c4f499f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3921,8 +3921,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { name: lifetime_ref.ident.name, param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime, help: self.r.tcx.sess.is_nightly_build(), - is_ogca: self.r.tcx.features().opaque_generic_const_args(), - help_ogca: self.r.tcx.features().opaque_generic_const_args(), + is_gca: self.r.tcx.features().generic_const_args(), + help_gca: self.r.tcx.features().generic_const_args(), }) .emit() } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 72d5cdcf1f3b6..d75f2981a7724 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -308,7 +308,7 @@ enum ResolutionError<'ra> { /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { - is_ogca: bool, + is_gca: bool, name: Symbol, param_kind: ParamKindInNonTrivialAnonConst, }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 30bf8dd7c2206..53e2527057bc2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1014,6 +1014,7 @@ symbols! { generic_assert, generic_associated_types, generic_associated_types_extended, + generic_const_args, generic_const_exprs, generic_const_items, generic_const_parameter_types, @@ -1414,7 +1415,6 @@ symbols! { on_move, on_unimplemented, opaque, - opaque_generic_const_args, opaque_module_name_placeholder: "", ops, opt_out_copy, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index bdad1b259b733..41b7b5b925cf0 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -676,9 +676,9 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } - Some(ty::AnonConstKind::OGCA) => { + Some(ty::AnonConstKind::GCA) => { if infcx.typing_mode() != TypingMode::PostAnalysis { - // OGCA anon consts should be treated as always having generics + // GCA anon consts should be treated as always having generics // during anything before codegen (or maybe MIR opts too). return Err(EvaluateConstErr::HasGenericsOrInfers); } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 9786608ab4bc0..2877364762f46 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -210,9 +210,9 @@ pub enum AnonConstKind { GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters MCG, - /// `feature(opaque_generic_const_args)` anon consts are allowed to use arbitrary + /// `feature(generic_const_args)` anon consts are allowed to use arbitrary /// generic parameters in scope, but only if they syntactically reference them. - OGCA, + GCA, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information RepeatExprCount, diff --git a/tests/ui/const-generics/ogca/basic-fail.rs b/tests/ui/const-generics/gca/basic-fail.rs similarity index 91% rename from tests/ui/const-generics/ogca/basic-fail.rs rename to tests/ui/const-generics/gca/basic-fail.rs index e3db3dea3735e..4b638279988d3 100644 --- a/tests/ui/const-generics/ogca/basic-fail.rs +++ b/tests/ui/const-generics/gca/basic-fail.rs @@ -1,6 +1,6 @@ #![feature(generic_const_items)] #![feature(min_generic_const_args)] -#![feature(opaque_generic_const_args)] +#![feature(generic_const_args)] #![expect(incomplete_features)] type const ADD1: usize = const { N + 1 }; diff --git a/tests/ui/const-generics/ogca/basic-fail.stderr b/tests/ui/const-generics/gca/basic-fail.stderr similarity index 100% rename from tests/ui/const-generics/ogca/basic-fail.stderr rename to tests/ui/const-generics/gca/basic-fail.stderr diff --git a/tests/ui/const-generics/ogca/basic.rs b/tests/ui/const-generics/gca/basic.rs similarity index 90% rename from tests/ui/const-generics/ogca/basic.rs rename to tests/ui/const-generics/gca/basic.rs index e736484b5c3c9..e80540d621de5 100644 --- a/tests/ui/const-generics/ogca/basic.rs +++ b/tests/ui/const-generics/gca/basic.rs @@ -2,7 +2,7 @@ #![feature(generic_const_items)] #![feature(min_generic_const_args)] -#![feature(opaque_generic_const_args)] +#![feature(generic_const_args)] #![expect(incomplete_features)] type const ADD1: usize = const { N + 1 }; diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.rs b/tests/ui/const-generics/gca/coherence-ambiguous.rs similarity index 84% rename from tests/ui/const-generics/ogca/coherence-ambiguous.rs rename to tests/ui/const-generics/gca/coherence-ambiguous.rs index bb20c0457c03d..7c8b2b33548c2 100644 --- a/tests/ui/const-generics/ogca/coherence-ambiguous.rs +++ b/tests/ui/const-generics/gca/coherence-ambiguous.rs @@ -1,6 +1,6 @@ //@ check-fail -#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)] +#![feature(generic_const_items, min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] type const FOO: usize = const { N + 1 }; diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.stderr b/tests/ui/const-generics/gca/coherence-ambiguous.stderr similarity index 100% rename from tests/ui/const-generics/ogca/coherence-ambiguous.stderr rename to tests/ui/const-generics/gca/coherence-ambiguous.stderr diff --git a/tests/ui/const-generics/ogca/generic-param-rhs.rs b/tests/ui/const-generics/gca/generic-param-rhs.rs similarity index 79% rename from tests/ui/const-generics/ogca/generic-param-rhs.rs rename to tests/ui/const-generics/gca/generic-param-rhs.rs index a62b509190bd6..ed4467d6f0039 100644 --- a/tests/ui/const-generics/ogca/generic-param-rhs.rs +++ b/tests/ui/const-generics/gca/generic-param-rhs.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, opaque_generic_const_args)] +#![feature(min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] fn foo() {} diff --git a/tests/ui/const-generics/ogca/generic-param-rhs.stderr b/tests/ui/const-generics/gca/generic-param-rhs.stderr similarity index 100% rename from tests/ui/const-generics/ogca/generic-param-rhs.stderr rename to tests/ui/const-generics/gca/generic-param-rhs.stderr diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.rs b/tests/ui/const-generics/gca/rhs-but-not-root.rs similarity index 77% rename from tests/ui/const-generics/ogca/rhs-but-not-root.rs rename to tests/ui/const-generics/gca/rhs-but-not-root.rs index bb6c6b667e1d0..6c0337dbbd470 100644 --- a/tests/ui/const-generics/ogca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/gca/rhs-but-not-root.rs @@ -1,9 +1,9 @@ #![feature(generic_const_items)] #![feature(min_generic_const_args)] -#![feature(opaque_generic_const_args)] +#![feature(generic_const_args)] #![expect(incomplete_features)] -// Anon consts must be the root of the RHS to be OGCA. +// Anon consts must be the root of the RHS to be GCA. type const FOO: usize = ID::; //~^ ERROR generic parameters in const blocks are only allowed as the direct value of a `type const` type const ID: usize = N; diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr b/tests/ui/const-generics/gca/rhs-but-not-root.stderr similarity index 100% rename from tests/ui/const-generics/ogca/rhs-but-not-root.stderr rename to tests/ui/const-generics/gca/rhs-but-not-root.stderr diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index f1d5e5c674756..0060c94875b5c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr index e0804158952d1..b25199bca2e28 100644 --- a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr +++ b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | T: Trait | ^^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index 1c72afce52c7d..f634ec1cf12e4 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -40,7 +40,7 @@ error: generic parameters may not be used in const operations LL | type const ITEM3: usize = const { N }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:60:31 @@ -48,7 +48,7 @@ error: generic parameters may not be used in const operations LL | T3: Trait, | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:69:58 @@ -56,7 +56,7 @@ error: generic parameters may not be used in const operations LL | struct Default3; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:28:27 @@ -64,7 +64,7 @@ error: generic parameters may not be used in const operations LL | let _3 = [(); const { N }]; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:33:26 @@ -72,7 +72,7 @@ error: generic parameters may not be used in const operations LL | let _6: [(); const { N }] = todo!(); | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:11:41 @@ -80,7 +80,7 @@ error: generic parameters may not be used in const operations LL | type Adt3 = Foo; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:19:42 @@ -88,7 +88,7 @@ error: generic parameters may not be used in const operations LL | type Arr3 = [(); const { N }]; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 13 previous errors diff --git a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr index 1c841e39e6739..cf5974fd83df9 100644 --- a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr +++ b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr @@ -9,7 +9,7 @@ note: not a concrete type | LL | impl S { | ^^^^ - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/selftyparam.stderr b/tests/ui/const-generics/mgca/selftyparam.stderr index c3e0770fb978e..74d8f083ee09e 100644 --- a/tests/ui/const-generics/mgca/selftyparam.stderr +++ b/tests/ui/const-generics/mgca/selftyparam.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | fn foo() -> [(); const { let _: Self; 1 }]; | ^^^^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 61e934380c360..694d4c8ebabd4 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | [0; const { size_of::<*mut T>() }]; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 2961c714d1415..3a873ec33fb19 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index 95a98d857b1d4..a9d412964da29 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -22,7 +22,7 @@ error: generic parameters may not be used in const operations LL | takes_nested_tuple::<{ (N, (N, const { N + 1 })) }>(); | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index 475d2cf312d64..0c88fbfb8578c 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | type const FREE1: usize = const { std::mem::size_of::() }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic-expr.rs:8:51 @@ -12,7 +12,7 @@ error: generic parameters may not be used in const operations LL | type const FREE2: usize = const { I + 1 }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr index e13d6fbcdd82f..78e38d800524e 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | type const N1: usize = const { std::mem::size_of::() }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:15:52 @@ -12,7 +12,7 @@ error: generic parameters may not be used in const operations LL | type const N2: usize = const { I + 1 }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:17:40 @@ -20,7 +20,7 @@ error: generic parameters may not be used in const operations LL | type const N3: usize = const { 2 & X }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-generic-const-args.rs similarity index 80% rename from tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs rename to tests/ui/feature-gates/feature-gate-generic-const-args.rs index f18f59cf60bd1..b62e7fb08099a 100644 --- a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-generic-const-args.rs @@ -3,6 +3,6 @@ type const INC: usize = const { N + 1 }; //~^ ERROR generic parameters may not be used in const operations -//~| HELP add `#![feature(opaque_generic_const_args)]` +//~| HELP add `#![feature(generic_const_args)]` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-generic-const-args.stderr similarity index 57% rename from tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr rename to tests/ui/feature-gates/feature-gate-generic-const-args.stderr index ef771e77f6923..27794b43966cd 100644 --- a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-generic-const-args.stderr @@ -1,10 +1,10 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-opaque-generic-const-args.rs:4:49 + --> $DIR/feature-gate-generic-const-args.rs:4:49 | LL | type const INC: usize = const { N + 1 }; | ^ | - = help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items + = help: add `#![feature(generic_const_args)]` to allow generic expressions as the RHS of const items error: aborting due to 1 previous error From 9465366ec44cc3cbfab1a39433b8d0c8e70c9a85 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Thu, 2 Apr 2026 12:06:25 +0200 Subject: [PATCH 57/61] remove the o from oGCA --- .../src/solve/normalizes_to/anon_const.rs | 15 ++-------- .../rustc_trait_selection/src/traits/mod.rs | 19 +++---------- ...fail.rs => basic-different-definitions.rs} | 4 +-- tests/ui/const-generics/gca/basic-fail.stderr | 11 -------- .../const-generics/gca/coherence-ambiguous.rs | 18 ------------ .../gca/coherence-ambiguous.stderr | 20 ------------- tests/ui/const-generics/gca/coherence-fail.rs | 28 +++++++++++++++++++ .../const-generics/gca/coherence-fail.stderr | 27 ++++++++++++++++++ tests/ui/const-generics/gca/coherence-ok.rs | 14 ++++++++++ 9 files changed, 77 insertions(+), 79 deletions(-) rename tests/ui/const-generics/gca/{basic-fail.rs => basic-different-definitions.rs} (87%) delete mode 100644 tests/ui/const-generics/gca/basic-fail.stderr delete mode 100644 tests/ui/const-generics/gca/coherence-ambiguous.rs delete mode 100644 tests/ui/const-generics/gca/coherence-ambiguous.stderr create mode 100644 tests/ui/const-generics/gca/coherence-fail.rs create mode 100644 tests/ui/const-generics/gca/coherence-fail.stderr create mode 100644 tests/ui/const-generics/gca/coherence-ok.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index 894910dfb6c16..46312be5ea9a9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -1,4 +1,4 @@ -use rustc_type_ir::{self as ty, Interner, TypingMode}; +use rustc_type_ir::{self as ty, Interner}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -14,18 +14,7 @@ where &mut self, goal: Goal>, ) -> QueryResult { - if self.typing_mode() == TypingMode::Coherence - && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::GCA - { - // During coherence, GCA consts should be normalized ambiguously - // because they are opaque but eventually resolved to a real value. - // We don't want two GCAs that have the same value to be treated - // as distinct for coherence purposes. (Just like opaque types.) - // - // We can't rely on evaluate_const below because that particular wrapper - // treats too-generic consts as a successful evaluation. - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } else if let Some(normalized_const) = self.evaluate_const( + if let Some(normalized_const) = self.evaluate_const( goal.param_env, ty::UnevaluatedConst::new( goal.predicate.alias.def_id.try_into().unwrap(), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 41b7b5b925cf0..94ce7631b3c88 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -676,21 +676,10 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } - Some(ty::AnonConstKind::GCA) => { - if infcx.typing_mode() != TypingMode::PostAnalysis { - // GCA anon consts should be treated as always having generics - // during anything before codegen (or maybe MIR opts too). - return Err(EvaluateConstErr::HasGenericsOrInfers); - } - - if uv.args.has_non_region_param() || uv.args.has_non_region_infer() { - return Err(EvaluateConstErr::HasGenericsOrInfers); - } - - let typing_env = ty::TypingEnv::fully_monomorphized(); - (uv.args, typing_env) - } - Some(ty::AnonConstKind::MCG) | Some(ty::AnonConstKind::NonTypeSystem) | None => { + Some(ty::AnonConstKind::GCA) + | Some(ty::AnonConstKind::MCG) + | Some(ty::AnonConstKind::NonTypeSystem) + | None => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately // - Repeat expr count back compat consts have also been handled separately diff --git a/tests/ui/const-generics/gca/basic-fail.rs b/tests/ui/const-generics/gca/basic-different-definitions.rs similarity index 87% rename from tests/ui/const-generics/gca/basic-fail.rs rename to tests/ui/const-generics/gca/basic-different-definitions.rs index 4b638279988d3..d96c718617d24 100644 --- a/tests/ui/const-generics/gca/basic-fail.rs +++ b/tests/ui/const-generics/gca/basic-different-definitions.rs @@ -1,3 +1,5 @@ +//@ check-pass + #![feature(generic_const_items)] #![feature(min_generic_const_args)] #![feature(generic_const_args)] @@ -11,8 +13,6 @@ type const ONE: usize = ADD1::<0>; type const OTHER_ONE: usize = INC::<0>; -// Not definitionally equal. const ARR: [(); ADD1::<0>] = [(); INC::<0>]; -//~^ ERROR mismatched types fn main() {} diff --git a/tests/ui/const-generics/gca/basic-fail.stderr b/tests/ui/const-generics/gca/basic-fail.stderr deleted file mode 100644 index b1808deacd27f..0000000000000 --- a/tests/ui/const-generics/gca/basic-fail.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/basic-fail.rs:15:30 - | -LL | const ARR: [(); ADD1::<0>] = [(); INC::<0>]; - | --------------- ^^^^^^^^^^^^^^ expected an array with a size of const { N + 1 }, found one with a size of const { N + 1 } - | | - | expected because of the type of the constant - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/gca/coherence-ambiguous.rs b/tests/ui/const-generics/gca/coherence-ambiguous.rs deleted file mode 100644 index 7c8b2b33548c2..0000000000000 --- a/tests/ui/const-generics/gca/coherence-ambiguous.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ check-fail - -#![feature(generic_const_items, min_generic_const_args, generic_const_args)] -#![expect(incomplete_features)] - -type const FOO: usize = const { N + 1 }; - -type const BAR: usize = const { N + 1 }; - -trait Trait {} - -impl Trait for [(); FOO::<1>] {} -impl Trait for [(); BAR::<1>] {} -//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]` -impl Trait for [(); BAR::<2>] {} -//~^ ERROR conflicting implementations of trait `Trait` for type `[(); FOO::<1>]` - -fn main() {} diff --git a/tests/ui/const-generics/gca/coherence-ambiguous.stderr b/tests/ui/const-generics/gca/coherence-ambiguous.stderr deleted file mode 100644 index 919a0c8d70e94..0000000000000 --- a/tests/ui/const-generics/gca/coherence-ambiguous.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]` - --> $DIR/coherence-ambiguous.rs:13:1 - | -LL | impl Trait for [(); FOO::<1>] {} - | ----------------------------- first implementation here -LL | impl Trait for [(); BAR::<1>] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]` - -error[E0119]: conflicting implementations of trait `Trait` for type `[(); FOO::<1>]` - --> $DIR/coherence-ambiguous.rs:15:1 - | -LL | impl Trait for [(); FOO::<1>] {} - | ----------------------------- first implementation here -... -LL | impl Trait for [(); BAR::<2>] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); FOO::<1>]` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/gca/coherence-fail.rs b/tests/ui/const-generics/gca/coherence-fail.rs new file mode 100644 index 0000000000000..1b181d792d362 --- /dev/null +++ b/tests/ui/const-generics/gca/coherence-fail.rs @@ -0,0 +1,28 @@ +#![feature(generic_const_items, min_generic_const_args, generic_const_args)] +#![expect(incomplete_features)] + +// computing the same value with different constant items but same generic arguments should fail +trait Trait1 {} +type const FOO: usize = const { N + 1 }; +type const BAR: usize = const { N + 1 }; +impl Trait1 for [(); FOO::<1>] {} +impl Trait1 for [(); BAR::<1>] {} +//~^ ERROR conflicting implementations of trait `Trait1` for type `[(); 2]` + +// computing the same value with the same constant item but different generic arguments should fail +type const DIV2: usize = const { N / 2 }; +trait Trait2 {} +impl Trait2 for [(); DIV2::<2>] {} +impl Trait2 for [(); DIV2::<3>] {} +//~^ ERROR conflicting implementations of trait `Trait2` for type `[(); 1]` + +// computing the same value with different constant items and different generic arguments should +// fail +trait Trait3 {} +type const ADD1: usize = const { N + 1 }; +type const SUB1: usize = const { N - 1 }; +impl Trait3 for [(); ADD1::<1>] {} +impl Trait3 for [(); SUB1::<3>] {} +//~^ ERROR conflicting implementations of trait `Trait3` for type `[(); 2]` + +fn main() {} diff --git a/tests/ui/const-generics/gca/coherence-fail.stderr b/tests/ui/const-generics/gca/coherence-fail.stderr new file mode 100644 index 0000000000000..e8122c1b832f1 --- /dev/null +++ b/tests/ui/const-generics/gca/coherence-fail.stderr @@ -0,0 +1,27 @@ +error[E0119]: conflicting implementations of trait `Trait1` for type `[(); 2]` + --> $DIR/coherence-fail.rs:9:1 + | +LL | impl Trait1 for [(); FOO::<1>] {} + | ------------------------------ first implementation here +LL | impl Trait1 for [(); BAR::<1>] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); 2]` + +error[E0119]: conflicting implementations of trait `Trait2` for type `[(); 1]` + --> $DIR/coherence-fail.rs:16:1 + | +LL | impl Trait2 for [(); DIV2::<2>] {} + | ------------------------------- first implementation here +LL | impl Trait2 for [(); DIV2::<3>] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); 1]` + +error[E0119]: conflicting implementations of trait `Trait3` for type `[(); 2]` + --> $DIR/coherence-fail.rs:25:1 + | +LL | impl Trait3 for [(); ADD1::<1>] {} + | ------------------------------- first implementation here +LL | impl Trait3 for [(); SUB1::<3>] {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `[(); 2]` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/const-generics/gca/coherence-ok.rs b/tests/ui/const-generics/gca/coherence-ok.rs new file mode 100644 index 0000000000000..447f25bfdc36b --- /dev/null +++ b/tests/ui/const-generics/gca/coherence-ok.rs @@ -0,0 +1,14 @@ +//@ check-pass +#![feature(generic_const_items, min_generic_const_args, generic_const_args)] +#![expect(incomplete_features)] + +// computing different values with the same type const item should be fine + +type const ADD1: usize = const { N + 1 }; + +trait Trait {} + +impl Trait for [(); ADD1::<1>] {} +impl Trait for [(); ADD1::<2>] {} + +fn main() {} From 22faa52629f3458e07c442fdd8c1ed1af1996831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 2 Apr 2026 12:13:21 +0200 Subject: [PATCH 58/61] Revert "Rollup merge of #149904 - ShoyuVanilla:ns-remove-sg-hack, r=lcnr" This reverts commit c108ad5617dbcb0e782a67b8de9f508c8a78e651, reversing changes made to 485f76b835abe0aa4c3c1578c16d0abee54079d3. --- .../rustc_type_ir/src/search_graph/mod.rs | 31 +++++++++++-- .../global-where-bound-normalization.rs | 45 ------------------- 2 files changed, 28 insertions(+), 48 deletions(-) delete mode 100644 tests/ui/traits/next-solver/global-where-bound-normalization.rs diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index e0c6c777c09af..535af2718f3ab 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -926,9 +926,10 @@ impl, X: Cx> SearchGraph { /// heads from the stack. This may not necessarily mean that we've actually /// reached a fixpoint for that cycle head, which impacts the way we rebase /// provisional cache entries. -#[derive(Debug)] -enum RebaseReason { +#[derive_where(Debug; X: Cx)] +enum RebaseReason { NoCycleUsages, + Ambiguity(X::AmbiguityInfo), Overflow, /// We've actually reached a fixpoint. /// @@ -965,7 +966,7 @@ impl, X: Cx> SearchGraph { &mut self, cx: X, stack_entry: &StackEntry, - rebase_reason: RebaseReason, + rebase_reason: RebaseReason, ) { let popped_head_index = self.stack.next_index(); // Rebasing decisions depend only on each provisional entry and the current stack state, @@ -1046,6 +1047,9 @@ impl, X: Cx> SearchGraph { // is not actually equal to the final provisional result. We // need to discard the provisional cache entry in this case. RebaseReason::NoCycleUsages => return false, + RebaseReason::Ambiguity(info) => { + *result = D::propagate_ambiguity(cx, input, info); + } RebaseReason::Overflow => *result = D::fixpoint_overflow_result(cx, input), RebaseReason::ReachedFixpoint(None) => {} RebaseReason::ReachedFixpoint(Some(path_kind)) => { @@ -1362,6 +1366,27 @@ impl, X: Cx> SearchGraph { return EvaluationResult::finalize(stack_entry, encountered_overflow, result); } + // If computing this goal results in ambiguity with no constraints, + // we do not rerun it. It's incredibly difficult to get a different + // response in the next iteration in this case. These changes would + // likely either be caused by incompleteness or can change the maybe + // cause from ambiguity to overflow. Returning ambiguity always + // preserves soundness and completeness even if the goal is be known + // to succeed or fail. + // + // This prevents exponential blowup affecting multiple major crates. + // As we only get to this branch if we haven't yet reached a fixpoint, + // we also taint all provisional cache entries which depend on the + // current goal. + if let Some(info) = D::is_ambiguous_result(result) { + self.rebase_provisional_cache_entries( + cx, + &stack_entry, + RebaseReason::Ambiguity(info), + ); + return EvaluationResult::finalize(stack_entry, encountered_overflow, result); + }; + // If we've reached the fixpoint step limit, we bail with overflow and taint all // provisional cache entries which depend on the current goal. i += 1; diff --git a/tests/ui/traits/next-solver/global-where-bound-normalization.rs b/tests/ui/traits/next-solver/global-where-bound-normalization.rs deleted file mode 100644 index e57fbf378a0d2..0000000000000 --- a/tests/ui/traits/next-solver/global-where-bound-normalization.rs +++ /dev/null @@ -1,45 +0,0 @@ -//@ check-pass -//@ compile-flags: -Znext-solver - -// Regression test for https://github.com/rust-lang/trait-system-refactor-initiative/issues/257. - -#![feature(rustc_attrs)] -#![expect(internal_features)] -#![rustc_no_implicit_bounds] - -pub trait Bound {} -impl Bound for u8 {} - -pub trait Proj { - type Assoc; -} -impl Proj for U { - type Assoc = U; -} -impl Proj for MyField { - type Assoc = u8; -} - -// While wf-checking the global bounds of `fn foo`, elaborating this outlives predicate triggered a -// cycle in the search graph along a particular probe path, which was not an actual solution. -// That cycle then resulted in a forced false-positive ambiguity due to a performance hack in the -// search graph and then ended up floundering the root goal evaluation. -pub trait Field: Proj {} - -struct MyField; -impl Field for MyField {} - -trait IdReqField { - type This; -} -impl IdReqField for F { - type This = F; -} - -fn foo() -where - ::This: Field, -{ -} - -fn main() {} From 77a93164226f78c306e6d9614bcf3a72c9126c76 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 9 Mar 2026 07:19:18 +0100 Subject: [PATCH 59/61] `FindParamInClause` non-global on overflow --- .../src/solve/assembly/mod.rs | 45 ++++++++++--------- .../normalize-param-env-4.next.stderr | 20 ++++++++- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index f58318b83625d..1fa9edb152235 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -9,7 +9,6 @@ use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::search_graph::CandidateHeadUsages; -use rustc_type_ir::solve::Certainty::Maybe; use rustc_type_ir::solve::{AliasBoundKind, SizedTraitKind}; use rustc_type_ir::{ self as ty, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -1286,16 +1285,19 @@ where return ControlFlow::Break(Err(NoSolution)); }; - if let ty::Placeholder(p) = ty.kind() { - if p.universe() == ty::UniverseIndex::ROOT { - ControlFlow::Break(Ok(Certainty::Yes)) - } else { - ControlFlow::Continue(()) + match ty.kind() { + ty::Placeholder(p) => { + if p.universe() == ty::UniverseIndex::ROOT { + ControlFlow::Break(Ok(Certainty::Yes)) + } else { + ControlFlow::Continue(()) + } } - } else if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) { - self.recursion_depth += 1; + ty::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)), + _ if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER) => { + self.recursion_depth += 1; if self.recursion_depth > self.ecx.cx().recursion_limit() { - return ControlFlow::Break(Ok(Maybe { + return ControlFlow::Break(Ok(Certainty::Maybe { cause: MaybeCause::Overflow { suggest_increasing_limit: true, keep_constraints: false, @@ -1306,8 +1308,8 @@ where let result = ty.super_visit_with(self); self.recursion_depth -= 1; result - } else { - ControlFlow::Continue(()) + } + _ => ControlFlow::Continue(()), } } @@ -1317,16 +1319,19 @@ where return ControlFlow::Break(Err(NoSolution)); }; - if let ty::ConstKind::Placeholder(p) = ct.kind() { - if p.universe() == ty::UniverseIndex::ROOT { - ControlFlow::Break(Ok(Certainty::Yes)) - } else { - ControlFlow::Continue(()) + match ct.kind() { + ty::ConstKind::Placeholder(p) => { + if p.universe() == ty::UniverseIndex::ROOT { + ControlFlow::Break(Ok(Certainty::Yes)) + } else { + ControlFlow::Continue(()) + } } - } else if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_RE_INFER) { - ct.super_visit_with(self) - } else { - ControlFlow::Continue(()) + ty::ConstKind::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)), + _ if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER) => { + ct.super_visit_with(self) + } + _ => ControlFlow::Continue(()), } } diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index f5fd9ce9864ce..e91a48f62aec3 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,6 +4,24 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `::Assoc well-formed` + --> $DIR/normalize-param-env-4.rs:19:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + +error[E0275]: overflow evaluating the requirement `T: Trait` + --> $DIR/normalize-param-env-4.rs:32:19 + | +LL | impls_trait::(); + | ^ + | +note: required by a bound in `impls_trait` + --> $DIR/normalize-param-env-4.rs:15:19 + | +LL | fn impls_trait() {} + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0275`. From b3b29ede805f7865f4d1e48f01219cabbb0ede4b Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 20 Mar 2026 16:31:50 +0100 Subject: [PATCH 60/61] handle concrete alias norm to generic see the added test --- .../src/solve/assembly/mod.rs | 34 +++++++++++-------- ...m-concrete-alias-to-generic.current.stderr | 19 +++++++++++ ...norm-concrete-alias-to-generic.next.stderr | 19 +++++++++++ ...s-global-norm-concrete-alias-to-generic.rs | 29 ++++++++++++++++ .../normalize-param-env-4.next.stderr | 2 +- 5 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr create mode 100644 tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.next.stderr create mode 100644 tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 1fa9edb152235..5645ee8f78ecf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1294,20 +1294,23 @@ where } } ty::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)), - _ if ty.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER) => { + _ if ty.has_type_flags( + TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER | TypeFlags::HAS_ALIAS, + ) => + { self.recursion_depth += 1; - if self.recursion_depth > self.ecx.cx().recursion_limit() { - return ControlFlow::Break(Ok(Certainty::Maybe { - cause: MaybeCause::Overflow { - suggest_increasing_limit: true, - keep_constraints: false, - }, - opaque_types_jank: OpaqueTypesJank::AllGood, - })); - } - let result = ty.super_visit_with(self); - self.recursion_depth -= 1; - result + if self.recursion_depth > self.ecx.cx().recursion_limit() { + return ControlFlow::Break(Ok(Certainty::Maybe { + cause: MaybeCause::Overflow { + suggest_increasing_limit: true, + keep_constraints: false, + }, + opaque_types_jank: OpaqueTypesJank::AllGood, + })); + } + let result = ty.super_visit_with(self); + self.recursion_depth -= 1; + result } _ => ControlFlow::Continue(()), } @@ -1328,7 +1331,10 @@ where } } ty::ConstKind::Infer(_) => ControlFlow::Break(Ok(Certainty::AMBIGUOUS)), - _ if ct.has_type_flags(TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER) => { + _ if ct.has_type_flags( + TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER | TypeFlags::HAS_ALIAS, + ) => + { ct.super_visit_with(self) } _ => ControlFlow::Continue(()), diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr new file mode 100644 index 0000000000000..0ad8e3444600b --- /dev/null +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.current.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/is-global-norm-concrete-alias-to-generic.rs:26:5 + | +LL | fn foo(x: <(*const T,) as Id>::This) -> (*const T,) + | ----------- expected `(*const T,)` because of return type +... +LL | x + | ^ expected `(*const T,)`, found associated type + | + = note: expected tuple `(*const T,)` + found associated type `<(*const T,) as Id>::This` + = help: consider constraining the associated type `<(*const T,) as Id>::This` to `(*const T,)` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + = note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition + see issue #152409 for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.next.stderr b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.next.stderr new file mode 100644 index 0000000000000..f16a17833368d --- /dev/null +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.next.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/is-global-norm-concrete-alias-to-generic.rs:26:5 + | +LL | fn foo(x: <(*const T,) as Id>::This) -> (*const T,) + | ----------- expected `(*const T,)` because of return type +... +LL | x + | ^ types differ + | + = note: expected tuple `(*const T,)` + found associated type `<(*const T,) as Id>::This` + = help: consider constraining the associated type `<(*const T,) as Id>::This` to `(*const T,)` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + = note: the associated type `<(*const T,) as Id>::This` is defined as `(*const T,)` in the implementation, but the where-bound `(*const T,)` shadows this definition + see issue #152409 for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.rs b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.rs new file mode 100644 index 0000000000000..c3f8bc75d6cce --- /dev/null +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-concrete-alias-to-generic.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// A regression test making sure that where-bounds with concrete aliases +// which normalize to something mentioning a generic parameters are +// considered non-global. +// +// When checking this, we previously didn't recur into types if they didn't +// mention any generic parameters, causing us to consider the `(<() as Id>::This,): Id` +// where-bound as global, even though it normalizes to `(T,): Id`. + +trait Id { + type This; +} + +impl Id for T { + type This = T; +} + +fn foo(x: <(*const T,) as Id>::This) -> (*const T,) +where + (): Id, + (<() as Id>::This,): Id, +{ + x //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index e91a48f62aec3..47d38365e970e 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `::Assoc: Trait` LL | ::Assoc: Trait, | ^^^^^ -error[E0275]: overflow evaluating the requirement `::Assoc well-formed` +error[E0275]: overflow evaluating whether `::Assoc` is well-formed --> $DIR/normalize-param-env-4.rs:19:26 | LL | ::Assoc: Trait, From 69148fd1900f0d2cbbb02a8ffed38b4ad014565b Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 2 Apr 2026 12:33:14 +0200 Subject: [PATCH 61/61] add mgca fixme --- compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 5645ee8f78ecf..c815ebaf7b669 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1335,6 +1335,7 @@ where TypeFlags::HAS_PLACEHOLDER | TypeFlags::HAS_INFER | TypeFlags::HAS_ALIAS, ) => { + // FIXME(mgca): we should also check the recursion limit here ct.super_visit_with(self) } _ => ControlFlow::Continue(()),