From 84140cf4e10409b54bdbaeef21751d8b6276640f Mon Sep 17 00:00:00 2001 From: LaneAsade Date: Sun, 8 Feb 2026 23:06:35 +0530 Subject: [PATCH 1/3] gate defaulted type consts with associated_type_defaults --- compiler/rustc_ast_passes/src/feature_gate.rs | 13 ++++++++++++- .../const_evaluatable_unchecked.rs | 2 +- .../mgca/type-const-associated-default.rs | 9 +++++++++ .../mgca/type-const-associated-default.stderr | 13 +++++++++++++ .../assoc-const-no-infer-ice-115806.rs | 1 + .../assoc-const-no-infer-ice-115806.stderr | 2 +- .../cfi/assoc-const-projection-issue-151878.rs | 2 +- 7 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 tests/ui/const-generics/mgca/type-const-associated-default.rs create mode 100644 tests/ui/const-generics/mgca/type-const-associated-default.stderr diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index eac7f03d8450c..f22c10949d1ed 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -431,7 +431,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { false } ast::AssocItemKind::Const(box ast::ConstItem { - rhs_kind: ast::ConstItemRhsKind::TypeConst { .. }, + rhs_kind: ast::ConstItemRhsKind::TypeConst { rhs }, .. }) => { // Make sure this is only allowed if the feature gate is enabled. @@ -442,6 +442,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { 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, + associated_type_defaults, + i.span, + "associated type defaults are unstable" + ); + } false } _ => false, diff --git a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs index 578904ea18918..54ba1093325a3 100644 --- a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs +++ b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs @@ -4,7 +4,7 @@ // // issue: //@ check-pass -#![feature(min_generic_const_args)] +#![feature(min_generic_const_args, associated_type_defaults)] #![allow(incomplete_features)] pub trait TraitA { diff --git a/tests/ui/const-generics/mgca/type-const-associated-default.rs b/tests/ui/const-generics/mgca/type-const-associated-default.rs new file mode 100644 index 0000000000000..7492ccbc60af5 --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-associated-default.rs @@ -0,0 +1,9 @@ +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] +trait Trait { + type const N: usize = 10; + //~^ ERROR associated type defaults are unstable +} + +fn main(){ +} diff --git a/tests/ui/const-generics/mgca/type-const-associated-default.stderr b/tests/ui/const-generics/mgca/type-const-associated-default.stderr new file mode 100644 index 0000000000000..a1d635801513e --- /dev/null +++ b/tests/ui/const-generics/mgca/type-const-associated-default.stderr @@ -0,0 +1,13 @@ +error[E0658]: associated type defaults are unstable + --> $DIR/type-const-associated-default.rs:4:5 + | +LL | type const N: usize = 10; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #29661 for more information + = help: add `#![feature(associated_type_defaults)]` 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/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index df680f30fed98..354880e6d573e 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -1,6 +1,7 @@ // ICE: assertion failed: !value.has_infer() // issue: rust-lang/rust#115806 #![feature(adt_const_params, min_generic_const_args, unsized_const_params)] +#![feature(associated_type_defaults)] #![allow(incomplete_features)] pub struct NoPin; diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr index b719ebe0664f2..f57fd74ad99df 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Pins<_>` for type `NoPin` - --> $DIR/assoc-const-no-infer-ice-115806.rs:16:1 + --> $DIR/assoc-const-no-infer-ice-115806.rs:17:1 | LL | impl Pins for NoPin {} | --------------------------- first implementation here diff --git a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs index 6bd995449fc64..ec7a6d1605588 100644 --- a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs +++ b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs @@ -4,7 +4,7 @@ //@ build-pass //@ no-prefer-dynamic -#![feature(min_generic_const_args)] +#![feature(min_generic_const_args, associated_type_defaults)] #![expect(incomplete_features)] trait Trait { From 7df748542c53e937613ce0f85ab813467ed62eaa Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Fri, 20 Feb 2026 09:24:06 -0700 Subject: [PATCH 2/3] Add build.rustdoc option to bootstrap config --- bootstrap.example.toml | 5 +++++ src/bootstrap/src/core/config/config.rs | 6 ++++++ src/bootstrap/src/core/config/toml/build.rs | 1 + src/bootstrap/src/lib.rs | 4 +--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index e0cbb0c0e747c..662bcc5d61e75 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -302,6 +302,11 @@ # If you set this, you likely want to set `cargo` as well. #build.rustc = "/path/to/rustc" +# Use this rustdoc binary as the stage0 snapshot rustdoc. +# If unspecified, then the binary "rustdoc" (with platform-specific extension, e.g. ".exe") +# in the same directory as "rustc" will be used. +#build.rustdoc = "/path/to/rustdoc" + # Instead of downloading the src/stage0 version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. #build.rustfmt = "/path/to/rustfmt" diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index bc68bfe396425..e975d71c8c70b 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -298,6 +298,7 @@ pub struct Config { // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + pub initial_rustdoc: PathBuf, pub initial_cargo_clippy: Option, pub initial_sysroot: PathBuf, pub initial_rustfmt: Option, @@ -456,6 +457,7 @@ impl Config { build_dir: build_build_dir, cargo: mut build_cargo, rustc: mut build_rustc, + rustdoc: build_rustdoc, rustfmt: build_rustfmt, cargo_clippy: build_cargo_clippy, docs: build_docs, @@ -751,6 +753,9 @@ impl Config { default_stage0_rustc_path(&out) }); + let initial_rustdoc = build_rustdoc + .unwrap_or_else(|| initial_rustc.with_file_name(exe("rustdoc", host_target))); + let initial_sysroot = t!(PathBuf::from_str( command(&initial_rustc) .args(["--print", "sysroot"]) @@ -1348,6 +1353,7 @@ impl Config { initial_cargo, initial_cargo_clippy: build_cargo_clippy, initial_rustc, + initial_rustdoc, initial_rustfmt, initial_sysroot, jemalloc: rust_jemalloc.unwrap_or(false), diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs index 192f875587209..27bf753f6914d 100644 --- a/src/bootstrap/src/core/config/toml/build.rs +++ b/src/bootstrap/src/core/config/toml/build.rs @@ -25,6 +25,7 @@ define_config! { build_dir: Option = "build-dir", cargo: Option = "cargo", rustc: Option = "rustc", + rustdoc: Option = "rustdoc", rustfmt: Option = "rustfmt", cargo_clippy: Option = "cargo-clippy", docs: Option = "docs", diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ec5c6fbe1d01d..b9a914f53cec1 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -535,9 +535,7 @@ impl Build { initial_lld, initial_relative_libdir, initial_rustc: config.initial_rustc.clone(), - initial_rustdoc: config - .initial_rustc - .with_file_name(exe("rustdoc", config.host_target)), + initial_rustdoc: config.initial_rustdoc.clone(), initial_cargo: config.initial_cargo.clone(), initial_sysroot: config.initial_sysroot.clone(), local_rebuild: config.local_rebuild, From bde075b6f34b06938c4349832a593ef129d00a97 Mon Sep 17 00:00:00 2001 From: Makai Date: Sun, 22 Feb 2026 23:42:15 +0800 Subject: [PATCH 3/3] Fix ICE when an associated type or const is wrongly marked as `final` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: León Orell Valerian Liehr --- compiler/rustc_ast_lowering/src/item.rs | 15 +++++-- .../traits/final/final-on-assoc-type-const.rs | 12 +++++ .../final/final-on-assoc-type-const.stderr | 18 ++++++++ tests/ui/traits/final/positions.rs | 2 - tests/ui/traits/final/positions.stderr | 44 +++++-------------- 5 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 tests/ui/traits/final/final-on-assoc-type-const.rs create mode 100644 tests/ui/traits/final/final-on-assoc-type-const.stderr diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8ae117f62786f..b63a7b25d197c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1088,9 +1088,18 @@ impl<'hir> LoweringContext<'_, 'hir> { } }; - let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value, || { - hir::Defaultness::Default { has_value } - }); + let defaultness = match i.kind.defaultness() { + // We do not yet support `final` on trait associated items other than functions. + // Even though we reject `final` on non-functions during AST validation, we still + // need to stop propagating it here because later compiler passes do not expect + // and cannot handle such items. + Defaultness::Final(..) if !matches!(i.kind, AssocItemKind::Fn(..)) => { + Defaultness::Implicit + } + defaultness => defaultness, + }; + let (defaultness, _) = self + .lower_defaultness(defaultness, has_value, || hir::Defaultness::Default { has_value }); let item = hir::TraitItem { owner_id: trait_item_def_id, diff --git a/tests/ui/traits/final/final-on-assoc-type-const.rs b/tests/ui/traits/final/final-on-assoc-type-const.rs new file mode 100644 index 0000000000000..9d20c0515476c --- /dev/null +++ b/tests/ui/traits/final/final-on-assoc-type-const.rs @@ -0,0 +1,12 @@ +// This is a regression test for . +#![feature(final_associated_functions)] +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] +trait Uwu { + final type Ovo; + //~^ error: `final` is only allowed on associated functions in traits + final type const QwQ: (); + //~^ error: `final` is only allowed on associated functions in traits +} + +fn main() {} diff --git a/tests/ui/traits/final/final-on-assoc-type-const.stderr b/tests/ui/traits/final/final-on-assoc-type-const.stderr new file mode 100644 index 0000000000000..ac2ab123e1d17 --- /dev/null +++ b/tests/ui/traits/final/final-on-assoc-type-const.stderr @@ -0,0 +1,18 @@ +error: `final` is only allowed on associated functions in traits + --> $DIR/final-on-assoc-type-const.rs:6:5 + | +LL | final type Ovo; + | -----^^^^^^^^^^ + | | + | `final` because of this + +error: `final` is only allowed on associated functions in traits + --> $DIR/final-on-assoc-type-const.rs:8:5 + | +LL | final type const QwQ: (); + | -----^^^^^^^^^^^^^^^^^^^^ + | | + | `final` because of this + +error: aborting due to 2 previous errors + diff --git a/tests/ui/traits/final/positions.rs b/tests/ui/traits/final/positions.rs index 9bf659e12431e..4b8d9536ad4cf 100644 --- a/tests/ui/traits/final/positions.rs +++ b/tests/ui/traits/final/positions.rs @@ -38,11 +38,9 @@ final impl Trait for Foo { final type Foo = (); //~^ ERROR `final` is only allowed on associated functions in traits - //~^^ ERROR cannot override `Foo` because it already has a `final` definition in the trait final const FOO: usize = 1; //~^ ERROR `final` is only allowed on associated functions in traits - //~^^ ERROR cannot override `FOO` because it already has a `final` definition in the trait } diff --git a/tests/ui/traits/final/positions.stderr b/tests/ui/traits/final/positions.stderr index bcb300e49d1a9..ff19c01b39617 100644 --- a/tests/ui/traits/final/positions.stderr +++ b/tests/ui/traits/final/positions.stderr @@ -15,7 +15,7 @@ LL | final trait Trait { = note: only associated functions in traits can be `final` error: a static item cannot be `final` - --> $DIR/positions.rs:67:5 + --> $DIR/positions.rs:65:5 | LL | final static FOO_EXTERN: usize = 0; | ^^^^^ `final` because of this @@ -23,7 +23,7 @@ LL | final static FOO_EXTERN: usize = 0; = note: only associated functions in traits can be `final` error: an extern block cannot be `final` - --> $DIR/positions.rs:58:1 + --> $DIR/positions.rs:56:1 | LL | final unsafe extern "C" { | ^^^^^ `final` because of this @@ -87,7 +87,7 @@ LL | final type Foo = (); | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:43:5 + --> $DIR/positions.rs:42:5 | LL | final const FOO: usize = 1; | -----^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | final const FOO: usize = 1; | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:49:1 + --> $DIR/positions.rs:47:1 | LL | final fn foo() {} | -----^^^^^^^^^ @@ -103,7 +103,7 @@ LL | final fn foo() {} | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:52:1 + --> $DIR/positions.rs:50:1 | LL | final type FooTy = (); | -----^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | final type FooTy = (); | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:55:1 + --> $DIR/positions.rs:53:1 | LL | final const FOO: usize = 0; | -----^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | final const FOO: usize = 0; | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:61:5 + --> $DIR/positions.rs:59:5 | LL | final fn foo_extern(); | -----^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | final fn foo_extern(); | `final` because of this error: `final` is only allowed on associated functions in traits - --> $DIR/positions.rs:64:5 + --> $DIR/positions.rs:62:5 | LL | final type FooExtern; | -----^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | final type FooExtern; | `final` because of this error: incorrect `static` inside `extern` block - --> $DIR/positions.rs:67:18 + --> $DIR/positions.rs:65:18 | LL | final unsafe extern "C" { | ----------------------- `extern` blocks define existing foreign statics and statics inside of them cannot have a body @@ -159,29 +159,5 @@ note: `method` is marked final here LL | final fn method() {} | ^^^^^^^^^^^^^^^^^ -error: cannot override `Foo` because it already has a `final` definition in the trait - --> $DIR/positions.rs:39:5 - | -LL | final type Foo = (); - | ^^^^^^^^^^^^^^ - | -note: `Foo` is marked final here - --> $DIR/positions.rs:16:5 - | -LL | final type Foo = (); - | ^^^^^^^^^^^^^^ - -error: cannot override `FOO` because it already has a `final` definition in the trait - --> $DIR/positions.rs:43:5 - | -LL | final const FOO: usize = 1; - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: `FOO` is marked final here - --> $DIR/positions.rs:19:5 - | -LL | final const FOO: usize = 1; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 21 previous errors +error: aborting due to 19 previous errors