From 9a30ec81498592914950d7a63253965e61d8cc05 Mon Sep 17 00:00:00 2001 From: Noah Lev Date: Wed, 7 Jan 2026 15:22:47 -0800 Subject: [PATCH] Implement MVP for opaque generic const arguments This is meant to be the interim successor to generic const expressions. Essentially, const item RHS's will be allowed to do arbitrary const operations using generics. The limitation is that these const items will be treated opaquely, like ADTs in nominal typing, such that uses of them will only be equal if the same const item is referenced. In other words, two const items with the exact same RHS will not be considered equal. I also added some logic to check feature gates that depend on others being enabled (like oGCA depending on mGCA). = Coherence = During coherence, OGCA 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 as distinct for coherence purposes. (Just like opaque types.) This actually doesn't work yet because there are pre-existing fundamental issues with equate relations involving consts that need to be normalized. The problem is that we normalize only one layer of the const item and don't actually process the resulting anon const. Normally the created inference variable should be handled, which in this case would cause us to hit the anon const, but that's not happening. Specifically, `visit_const` on `Generalizer` should be updated to be similar to `visit_ty`. --- compiler/rustc_ast_passes/src/errors.rs | 10 +++ compiler/rustc_ast_passes/src/feature_gate.rs | 22 +++++++ compiler/rustc_ast_passes/src/lib.rs | 1 + compiler/rustc_feature/src/lib.rs | 3 +- compiler/rustc_feature/src/unstable.rs | 8 +++ compiler/rustc_hir_analysis/src/collect.rs | 64 ++++++++++++++++++- .../src/collect/generics_of.rs | 2 + .../src/hir_ty_lowering/mod.rs | 5 ++ compiler/rustc_middle/src/ty/consts.rs | 15 +---- compiler/rustc_middle/src/ty/context.rs | 3 + compiler/rustc_middle/src/ty/mod.rs | 4 +- .../src/solve/normalizes_to/anon_const.rs | 15 ++++- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_span/src/symbol.rs | 1 + .../rustc_trait_selection/src/traits/mod.rs | 14 ++++ compiler/rustc_type_ir/src/const_kind.rs | 20 ++++++ compiler/rustc_type_ir/src/interner.rs | 1 + .../non_valtreeable_const_arg-2.rs | 2 +- .../non_valtreeable_const_arg-2.stderr | 6 +- .../associated-const-bindings/ambiguity.rs | 2 +- .../coexisting-with-type-binding.rs | 2 +- ...dyn-compat-assoc-const-ty-mentions-self.rs | 1 + ...compat-assoc-const-ty-mentions-self.stderr | 4 +- ...elf-const-projections-in-assoc-const-ty.rs | 13 +++- ...const-projections-in-assoc-const-ty.stderr | 8 +-- .../esc-bound-var-in-ty.rs | 1 + .../esc-bound-var-in-ty.stderr | 2 +- .../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 | 1 + .../ui/const-generics/mgca/selftyparam.stderr | 2 + .../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 ++ .../unbraced_const_block_const_arg_gated.rs | 1 - ...nbraced_const_block_const_arg_gated.stderr | 12 +--- tests/ui/const-generics/ogca/basic-fail.rs | 22 +++++++ .../ui/const-generics/ogca/basic-fail.stderr | 9 +++ tests/ui/const-generics/ogca/basic.rs | 22 +++++++ .../ogca/coherence-ambiguous.rs | 21 ++++++ .../const-generics/ogca/rhs-but-not-root.rs | 14 ++++ .../ogca/rhs-but-not-root.stderr | 8 +++ .../feature-gate-opaque-generic-const-args.rs | 9 +++ ...ture-gate-opaque-generic-const-args.stderr | 10 +++ .../assoc-const-no-infer-ice-115806.rs | 2 +- 48 files changed, 347 insertions(+), 53 deletions(-) create mode 100644 tests/ui/const-generics/ogca/basic-fail.rs create mode 100644 tests/ui/const-generics/ogca/basic-fail.stderr create mode 100644 tests/ui/const-generics/ogca/basic.rs create mode 100644 tests/ui/const-generics/ogca/coherence-ambiguous.rs create mode 100644 tests/ui/const-generics/ogca/rhs-but-not-root.rs create mode 100644 tests/ui/const-generics/ogca/rhs-but-not-root.stderr create mode 100644 tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs create mode 100644 tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index baf6f6beaeed7..7282a5168213c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -950,6 +950,16 @@ pub(crate) struct IncompatibleFeatures { pub f2: Symbol, } +#[derive(Diagnostic)] +#[diag("`{$parent}` requires {$missing} to be enabled")] +#[help("enable all of these features")] +pub(crate) struct MissingDependentFeatures { + #[primary_span] + pub parent_span: Span, + pub parent: Symbol, + pub missing: String, +} + #[derive(Diagnostic)] #[diag("negative bounds are not supported")] pub(crate) struct NegativeBoundUnsupported { diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 1b1bbb1564c46..ce9001d659318 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -441,6 +441,7 @@ 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); + check_dependent_features(sess, features); check_new_solver_banned_features(sess, features); let mut visitor = PostExpansionVisitor { sess, features }; @@ -649,6 +650,27 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } } +fn check_dependent_features(sess: &Session, features: &Features) { + for &(parent, children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + { + if children.iter().any(|f| !features.enabled(*f)) { + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = children + .iter() + .filter(|f| !features.enabled(**f)) + .map(|s| format!("`{}`", s.as_str())) + .intersperse(String::from(", ")) + .collect(); + sess.dcx().emit_err(errors::MissingDependentFeatures { parent_span, parent, missing }); + } + } +} + fn check_new_solver_banned_features(sess: &Session, features: &Features) { if !sess.opts.unstable_opts.next_solver.globally { return; diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 2630348c49c1f..7793f786cefee 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![feature(box_patterns)] #![feature(if_let_guard)] +#![feature(iter_intersperse)] #![feature(iter_is_partitioned)] // tidy-alphabetical-end diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 4ba50d03d707b..619726f0d5d8f 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -136,5 +136,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, + UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 2ab7714f22ca9..a941eb1f459ed 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -605,6 +605,8 @@ 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, "CURRENT_RUSTC_VERSION", Some(151972)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows specifying nop padding on functions for dynamic patching. @@ -782,3 +784,9 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ // boolean logic required to tell which typing rules to use. (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; + +/// 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::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 f50aff187f252..f3086266eec00 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -16,7 +16,7 @@ use std::cell::Cell; use std::iter; -use std::ops::Bound; +use std::ops::{Bound, ControlFlow}; use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; @@ -26,12 +26,13 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err, }; use rustc_hir::attrs::AttributeKind; -use rustc_hir::def::DefKind; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; +use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; +use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ @@ -1511,6 +1512,20 @@ 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. + // 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) { + return ty::AnonConstKind::MCG; + } + + let body = tcx.hir_body_owned_by(def); + let mut visitor = OGCAParamVisitor(tcx); + match visitor.visit_body(body) { + ControlFlow::Break(UsesParam) => ty::AnonConstKind::OGCA, + ControlFlow::Continue(()) => ty::AnonConstKind::MCG, + } } else if tcx.features().min_generic_const_args() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { @@ -1528,6 +1543,49 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } } +fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false }; + let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) + | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) + | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. + })) = grandparent_node + else { + return false; + }; + let hir::ConstItemRhs::TypeConst(hir::ConstArg { + kind: hir::ConstArgKind::Anon(rhs_anon), .. + }) = ct_rhs + else { + return false; + }; + def_id == rhs_anon.def_id +} + +struct OGCAParamVisitor<'tcx>(TyCtxt<'tcx>); + +struct UsesParam; + +impl<'tcx> Visitor<'tcx> for OGCAParamVisitor<'tcx> { + type NestedFilter = nested_filter::OnlyBodies; + type Result = ControlFlow; + + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { + self.0 + } + + fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow { + if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) = + path.res + { + return ControlFlow::Break(UsesParam); + } + + intravisit::walk_path(self, path) + } +} + #[instrument(level = "debug", skip(tcx), ret)] fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 511d513216eb2..0723418d8ddfe 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -92,6 +92,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), // 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 a79170452fae8..7a03d8b220c5c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -404,6 +404,11 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { diag.span_note(impl_.self_ty.span, "not a concrete type"); } } + if self.tcx.features().min_generic_const_args() + && !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"); + } diag.emit() } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5581ad5669aa9..3e17943a88574 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_data_structures::intern::Interned; use rustc_error_messages::MultiSpan; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::HashStable; use rustc_type_ir::walk::TypeWalker; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; @@ -335,16 +335,3 @@ impl<'tcx> Const<'tcx> { TypeWalker::new(self.into()) } } - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum AnonConstKind { - /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope - GCE, - /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - MCG, - /// 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, - /// anon consts outside of the type system, e.g. enum discriminants - NonTypeSystem, -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e43a30091f507..1bb83530487df 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -238,6 +238,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn const_of_item(self, def_id: DefId) -> ty::EarlyBinder<'tcx, Const<'tcx>> { self.const_of_item(def_id) } + fn anon_const_kind(self, def_id: DefId) -> ty::AnonConstKind { + self.anon_const_kind(def_id) + } type AdtDef = ty::AdtDef<'tcx>; fn adt_def(self, adt_def_id: DefId) -> Self::AdtDef { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0220531b09fa8..37871aad4a775 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -76,8 +76,8 @@ pub use self::closure::{ place_to_string_for_capture, }; pub use self::consts::{ - AnonConstKind, AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, - ExprKind, ScalarInt, SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, + AtomicOrdering, Const, ConstInt, ConstKind, ConstToValTreeResult, Expr, ExprKind, ScalarInt, + SimdAlign, UnevaluatedConst, ValTree, ValTreeKindExt, Value, }; pub use self::context::{ CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, 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 46312be5ea9a9..eb6a1b51421ca 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}; +use rustc_type_ir::{self as ty, Interner, TypingMode}; use tracing::instrument; use crate::delegate::SolverDelegate; @@ -14,7 +14,18 @@ where &mut self, goal: Goal>, ) -> QueryResult { - if let Some(normalized_const) = self.evaluate_const( + if self.typing_mode() == TypingMode::Coherence + && self.cx().anon_const_kind(goal.predicate.alias.def_id) == ty::AnonConstKind::OGCA + { + // During coherence, OGCA 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 + // 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( goal.param_env, ty::UnevaluatedConst::new( goal.predicate.alias.def_id.try_into().unwrap(), diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index c35ddc4dc9438..9ac9bd5c0e466 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1551,7 +1551,9 @@ impl<'a> Parser<'a> { let rhs = if self.eat(exp!(Eq)) { if attr::contains_name(attrs, sym::type_const) { - Some(ConstItemRhs::TypeConst(self.parse_const_arg()?)) + let ct = + self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?; + Some(ConstItemRhs::TypeConst(ct)) } else { Some(ConstItemRhs::Body(self.parse_expr()?)) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 1915ff0380fda..6aa2eae556e25 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1628,6 +1628,7 @@ symbols! { on_const, on_unimplemented, opaque, + opaque_generic_const_args, opaque_module_name_placeholder: "", open_options_new, ops, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 4e027a301cc8b..08f1d947dfb5c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -681,6 +681,20 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } + Some(ty::AnonConstKind::OGCA) => { + if infcx.typing_mode() != TypingMode::PostAnalysis { + // OGCA 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 => { // We are only dealing with "truly" generic/uninferred constants here: // - GCEConsts have been handled separately diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index b215230ea443c..1c39f31469b1c 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -200,3 +200,23 @@ impl ValTreeKind { } } } + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] +pub enum AnonConstKind { + /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope + 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 + /// generic parameters in scope, but only if they syntactically reference them. + OGCA, + /// 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, + /// anon consts outside of the type system, e.g. enum discriminants + NonTypeSystem, +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 59ae6733fb847..8f446cdfba6d5 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -205,6 +205,7 @@ pub trait Interner: fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId) -> ty::EarlyBinder; fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder; + fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; type AdtDef: AdtDef; fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef; diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs index 6b87ad86d4bc2..e364368b8a4cf 100644 --- a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.rs @@ -1,4 +1,4 @@ -#![feature(generic_const_exprs, unsized_const_params)] +#![feature(adt_const_params, generic_const_exprs, unsized_const_params)] #![allow(incomplete_features)] // Regression test for 128232 diff --git a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr index 72dfda50ea5ca..b13f76eabadbc 100644 --- a/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr +++ b/tests/ui/const-generics/adt_const_params/non_valtreeable_const_arg-2.stderr @@ -9,13 +9,11 @@ help: you might be missing a const parameter LL | impl Wrapper<{ bar() }> { | +++++++++++++++++++++++ -error: using function pointers as const generic parameters is forbidden +error[E0741]: using function pointers as const generic parameters is forbidden --> $DIR/non_valtreeable_const_arg-2.rs:8:25 | LL | struct Wrapper; | ^^^^ - | - = note: the only supported types are integers, `bool`, and `char` error[E0599]: the function or associated item `call` exists for struct `Wrapper`, but its trait bounds were not satisfied --> $DIR/non_valtreeable_const_arg-2.rs:17:26 @@ -37,5 +35,5 @@ note: the trait `Fn` must be implemented error: aborting due to 3 previous errors -Some errors have detailed explanations: E0425, E0599. +Some errors have detailed explanations: E0425, E0599, E0741. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs index 6bc2a6d5d1533..785d43e51b3d8 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs @@ -1,7 +1,7 @@ // We used to say "ambiguous associated type" on ambiguous associated consts. // Ensure that we now use the correct label. -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait0: Parent0 + Parent0 {} diff --git a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs index 0042159867113..0af91bfe7da80 100644 --- a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs +++ b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs @@ -5,7 +5,7 @@ //@ check-pass -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] trait Trait: SuperTrait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs index d19e7acbaff0d..bd26acce681fc 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs @@ -3,6 +3,7 @@ //@ dont-require-annotations: NOTE +#![feature(adt_const_params)] #![feature(generic_const_items)] #![feature(generic_const_parameter_types)] #![feature(min_generic_const_args)] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr index dba1643d2c5c6..dedbdd7f82bbb 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:37:16 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:38:16 | LL | let _: dyn Trait; | ^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:17:11 + --> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:18:11 | LL | trait Trait { | ----- this trait is not dyn compatible... diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs index 936556e957cad..fc3bd1d2e753f 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs @@ -4,17 +4,24 @@ // to the rest of the compiler and by extension the user via diagnostics. //@ known-bug: unknown -#![feature(min_generic_const_args, unsized_const_params, generic_const_parameter_types)] +#![feature( + adt_const_params, + min_generic_const_args, + unsized_const_params, + generic_const_parameter_types +)] #![expect(incomplete_features)] trait A { type Ty: std::marker::ConstParamTy_; - #[type_const] const CT: Self::Ty; + #[type_const] + const CT: Self::Ty; } impl A for () { type Ty = i32; - #[type_const] const CT: i32 = 0; + #[type_const] + const CT: i32 = 0; } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index 8ee231ec070fd..0b8dae1aac43a 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:27:33 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:33 | LL | let _: dyn A; | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 | LL | impl A for () { | ^^^^^^^^^^^^^ error[E0277]: the trait bound `FreshTy(0): A` is not satisfied - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:29:34 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:36:34 | LL | let _: &dyn A = &(); | ^ the trait `A` is not implemented for `FreshTy(0)` | help: the trait `A` is implemented for `()` - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:15:1 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:21:1 | LL | impl A for () { | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs index d32737fcb62f5..4d06cdc7620f4 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs @@ -1,6 +1,7 @@ // Detect and reject escaping late-bound generic params in // the type of assoc consts used in an equality bound. #![feature( + adt_const_params, min_generic_const_args, unsized_const_params, generic_const_parameter_types, diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr index 122893662933d..3966483aa6002 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.stderr @@ -1,5 +1,5 @@ error: the type of the associated constant `K` cannot capture late-bound generic parameters - --> $DIR/esc-bound-var-in-ty.rs:15:35 + --> $DIR/esc-bound-var-in-ty.rs:16:35 | LL | fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {} | -- ^ its type cannot capture the late-bound lifetime parameter `'r` 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 8b9c228c1ee53..f1d5e5c674756 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -9,6 +9,8 @@ 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 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 461a26e33a3ce..e0804158952d1 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 @@ -3,6 +3,8 @@ 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 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 551815c4c31a0..1251f4415171d 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -39,42 +39,56 @@ error: generic parameters may not be used in const operations | LL | const ITEM3: usize = const { N }; | ^ + | + = help: add `#![feature(opaque_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 | LL | T3: Trait, | ^ + | + = help: add `#![feature(opaque_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 | LL | struct Default3; | ^ + | + = help: add `#![feature(opaque_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 | LL | let _3 = [(); const { N }]; | ^ + | + = help: add `#![feature(opaque_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 | LL | let _6: [(); const { N }] = todo!(); | ^ + | + = help: add `#![feature(opaque_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 | LL | type Adt3 = Foo; | ^ + | + = help: add `#![feature(opaque_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 | LL | type Arr3 = [(); const { N }]; | ^ + | + = help: add `#![feature(opaque_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 fdd3e6efdf653..1c841e39e6739 100644 --- a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr +++ b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr @@ -9,6 +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 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 376e63da9a759..c3e0770fb978e 100644 --- a/tests/ui/const-generics/mgca/selftyparam.stderr +++ b/tests/ui/const-generics/mgca/selftyparam.stderr @@ -3,6 +3,8 @@ 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 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 913d8195fe21d..6d8d3b4054d34 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 @@ -9,6 +9,8 @@ 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 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 e0ea3fd5560c8..2961c714d1415 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -9,6 +9,8 @@ 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 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 b294e1032ce8f..b4853d3c2e38c 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -21,6 +21,8 @@ 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 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 f339e82beeeda..8d43f2177562f 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 @@ -3,12 +3,16 @@ error: generic parameters may not be used in const operations | LL | 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 error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic-expr.rs:8:46 | LL | const FREE2: usize = const { I + 1 }; | ^ + | + = help: add `#![feature(opaque_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 9d4e99ca0aaf3..1a6097752e335 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 @@ -3,18 +3,24 @@ error: generic parameters may not be used in const operations | LL | 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 error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:20:47 | LL | const N2: usize = const { I + 1 }; | ^ + | + = help: add `#![feature(opaque_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:23:35 | LL | const N3: usize = const { 2 & X }; | ^ + | + = help: add `#![feature(opaque_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/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs index 588fa2f913b63..c01fb47002b24 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -35,7 +35,6 @@ const NON_TYPE_CONST: usize = const { 1 }; #[type_const] //~^ ERROR: the `#[type_const]` attribute is an experimental feature const TYPE_CONST: usize = const { 1 }; -//~^ ERROR: unbraced const blocks as const args are experimental static STATIC: usize = const { 1 }; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr index 00db630c27e9e..bbcd9f9897a63 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -48,16 +48,6 @@ LL | generic::(); = help: add `#![feature(min_generic_const_args)]` 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]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:37:27 - | -LL | const TYPE_CONST: usize = const { 1 }; - | ^^^^^^^^^^^ - | - = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` 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]: the `#[type_const]` attribute is an experimental feature --> $DIR/unbraced_const_block_const_arg_gated.rs:35:1 | @@ -68,6 +58,6 @@ LL | #[type_const] = help: add `#![feature(min_generic_const_args)]` 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 7 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/ogca/basic-fail.rs b/tests/ui/const-generics/ogca/basic-fail.rs new file mode 100644 index 0000000000000..87176c7b067e6 --- /dev/null +++ b/tests/ui/const-generics/ogca/basic-fail.rs @@ -0,0 +1,22 @@ +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const ADD1: usize = const { N + 1 }; + +#[type_const] +const INC: usize = const { N + 1 }; + +#[type_const] +const ONE: usize = ADD1::<0>; + +#[type_const] +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/ogca/basic-fail.stderr b/tests/ui/const-generics/ogca/basic-fail.stderr new file mode 100644 index 0000000000000..05de01b132c6f --- /dev/null +++ b/tests/ui/const-generics/ogca/basic-fail.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/basic-fail.rs:19: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 } + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/ogca/basic.rs b/tests/ui/const-generics/ogca/basic.rs new file mode 100644 index 0000000000000..c8aec9ee24ce2 --- /dev/null +++ b/tests/ui/const-generics/ogca/basic.rs @@ -0,0 +1,22 @@ +//@ check-pass + +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const ADD1: usize = const { N + 1 }; + +#[type_const] +const INC: usize = ADD1::; + +#[type_const] +const ONE: usize = ADD1::<0>; + +#[type_const] +const OTHER_ONE: usize = INC::<0>; + +const ARR: [(); ADD1::<0>] = [(); INC::<0>]; + +fn main() {} diff --git a/tests/ui/const-generics/ogca/coherence-ambiguous.rs b/tests/ui/const-generics/ogca/coherence-ambiguous.rs new file mode 100644 index 0000000000000..c8c088b1e8fc3 --- /dev/null +++ b/tests/ui/const-generics/ogca/coherence-ambiguous.rs @@ -0,0 +1,21 @@ +// FIXME(ogca): this should ERROR not pass!! +//@ check-pass + +#![feature(generic_const_items, min_generic_const_args, opaque_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const FOO: usize = const { N + 1 }; + +#[type_const] +const BAR: usize = const { N + 1 }; + +trait Trait {} + +impl Trait for [(); FOO::<1>] {} +impl Trait for [(); BAR::<1>] {} +// FIXME(ogca): this should ERROR! +impl Trait for [(); BAR::<2>] {} +// FIXME(ogca): this should ERROR! + +fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.rs b/tests/ui/const-generics/ogca/rhs-but-not-root.rs new file mode 100644 index 0000000000000..4ed136f04ced3 --- /dev/null +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.rs @@ -0,0 +1,14 @@ +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(opaque_generic_const_args)] +#![expect(incomplete_features)] + +// Anon consts must be the root of the RHS to be OGCA. +#[type_const] +const FOO: usize = ID::; +//~^ ERROR generic parameters may not be used in const operations + +#[type_const] +const ID: usize = N; + +fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr new file mode 100644 index 0000000000000..f4fdf5fb981b7 --- /dev/null +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr @@ -0,0 +1,8 @@ +error: generic parameters may not be used in const operations + --> $DIR/rhs-but-not-root.rs:8:49 + | +LL | const FOO: usize = ID::; + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs new file mode 100644 index 0000000000000..0b78911158ba2 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.rs @@ -0,0 +1,9 @@ +#![feature(generic_const_items, min_generic_const_args)] +#![expect(incomplete_features)] + +#[type_const] +const INC: usize = const { N + 1 }; +//~^ ERROR generic parameters may not be used in const operations +//~| HELP add `#![feature(opaque_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-opaque-generic-const-args.stderr new file mode 100644 index 0000000000000..1b87443aa3cba --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-opaque-generic-const-args.stderr @@ -0,0 +1,10 @@ +error: generic parameters may not be used in const operations + --> $DIR/feature-gate-opaque-generic-const-args.rs:5:44 + | +LL | const INC: usize = const { N + 1 }; + | ^ + | + = help: add `#![feature(opaque_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/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index fb2506daf078d..518ed64523691 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,6 @@ // ICE: assertion failed: !value.has_infer() // issue: rust-lang/rust#115806 -#![feature(min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] pub struct NoPin;