Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5ac90c6
Clarify ascii whitespace exclusion of vertical tab in the doc
krtab Apr 3, 2026
335585b
add `const_param_ty_unchecked` gate
zedddie Mar 7, 2026
baf246f
gate tuple const params behind adt_const_params
zedddie Apr 6, 2026
a4c4944
A couple small comment cleanups, and update tests.
jackh726 Apr 11, 2026
b52a38d
Add link to Unicode White_Space property
krtab Apr 13, 2026
c681ae6
For supertrait-shadowing tests, assert str rather than println
jackh726 Apr 13, 2026
9a9f5b5
gate primitives behind `min_adt_const_params`; change suggestion to `…
zedddie Apr 11, 2026
7d4b12b
Add lexer test for vertical tab as Pattern_White_Space whitespace
Sandijigs Apr 14, 2026
15fd168
Tests for precise-capture through RPIT and TAIT
Zalathar Apr 14, 2026
aacac7e
Fix ICE when Self is used in enum discriminant of a generic enum
GokhanKabar Apr 14, 2026
05081b9
fix arch names in cfg pretty printer
usamoi Apr 14, 2026
2598b50
remove PointeeParser
Bryntet Apr 14, 2026
c5c1d2c
Rollup merge of #153536 - zedddie:const-param-ty-unchecked-gate, r=Bo…
JonathanBrouwer Apr 14, 2026
d8408cf
Rollup merge of #153815 - GokhanKabar:fix-ice-enum-discr-generic-self…
JonathanBrouwer Apr 14, 2026
2b3279d
Rollup merge of #154882 - zedddie:gate-tuple-const-params, r=BoxyUwU
JonathanBrouwer Apr 14, 2026
ced5143
Rollup merge of #155293 - usamoi:rustdoc-loongarch, r=GuillaumeGomez
JonathanBrouwer Apr 14, 2026
7d7bfd9
Rollup merge of #154765 - krtab:doc_ascii_whitespace, r=Mark-Simulacr…
JonathanBrouwer Apr 14, 2026
8d14b5c
Rollup merge of #155172 - jackh726:supertrait-shadowing-cleanup, r=lcnr
JonathanBrouwer Apr 14, 2026
ceea5ce
Rollup merge of #155279 - Sandijigs:test/lexer-unicode-pattern-white-…
JonathanBrouwer Apr 14, 2026
4d62420
Rollup merge of #155280 - Zalathar:opaque-capture-bug, r=JonathanBrouwer
JonathanBrouwer Apr 14, 2026
8b4c5ef
Rollup merge of #155304 - Bryntet:remove-pointee-parser, r=JonathanBr…
JonathanBrouwer Apr 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions compiler/rustc_attr_parsing/src/attributes/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use super::prelude::*;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::{Allow, Warn};
use crate::target_checking::{ALL_TARGETS, AllowedTargets};

pub(crate) struct RustcSkipDuringMethodDispatchParser;
impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser {
Expand Down Expand Up @@ -141,11 +141,3 @@ impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
}

pub(crate) struct PointeeParser;
impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
const PATH: &[Symbol] = &[sym::pointee];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
}
1 change: 0 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ attribute_parsers!(
Single<WithoutArgs<PanicHandlerParser>>,
Single<WithoutArgs<PanicRuntimeParser>>,
Single<WithoutArgs<PinV2Parser>>,
Single<WithoutArgs<PointeeParser>>,
Single<WithoutArgs<PreludeImportParser>>,
Single<WithoutArgs<ProcMacroAttributeParser>>,
Single<WithoutArgs<ProcMacroParser>>,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ declare_features! (
(internal, cfg_target_has_reliable_f16_f128, "1.88.0", None),
/// Allows identifying the `compiler_builtins` crate.
(internal, compiler_builtins, "1.13.0", None),
/// Allows skipping `ConstParamTy_` trait implementation checks
(internal, const_param_ty_unchecked, "CURRENT_RUSTC_VERSION", None),
/// Allows writing custom MIR
(internal, custom_mir, "1.65.0", None),
/// Implementation details of externally implementable items
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1233,9 +1233,6 @@ pub enum AttributeKind {
/// Represents `#[pin_v2]`
PinV2(Span),

/// Represents `#[pointee]`
Pointee(Span),

/// Represents `#[prelude_import]`
PreludeImport,

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ impl AttributeKind {
Path(..) => No,
PatternComplexityLimit { .. } => No,
PinV2(..) => Yes,
Pointee(..) => No,
PreludeImport => No,
ProcMacro(..) => No,
ProcMacroAttribute(..) => No,
Expand Down
29 changes: 19 additions & 10 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,12 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
let span = tcx.def_span(param.def_id);
let def_id = param.def_id.expect_local();

if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() {
if tcx.features().const_param_ty_unchecked() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_wf_obligation(span, None, ty.into());
Ok(())
})
} else if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() {
enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)),
Expand Down Expand Up @@ -904,7 +909,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
) => None,
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
Some(vec![
(adt_const_params_feature_string, sym::adt_const_params),
(adt_const_params_feature_string, sym::min_adt_const_params),
(
" references to implement the `ConstParamTy` trait".into(),
sym::unsized_const_params,
Expand All @@ -931,11 +936,13 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er

ty_is_local(ty).then_some(vec![(
adt_const_params_feature_string,
sym::adt_const_params,
sym::min_adt_const_params,
)])
}
// Implements `ConstParamTy`, suggest adding the feature to enable.
Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]),
Ok(..) => {
Some(vec![(adt_const_params_feature_string, sym::min_adt_const_params)])
}
};
if let Some(features) = may_suggest_feature {
tcx.disabled_nightly_features(&mut diag, features);
Expand Down Expand Up @@ -1346,12 +1353,14 @@ pub(super) fn check_type_const<'tcx>(
let tcx = wfcx.tcx();
let span = tcx.def_span(def_id);

wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
wfcx.param_env,
item_ty,
tcx.require_lang_item(LangItem::ConstParamTy, span),
);
if !tcx.features().const_param_ty_unchecked() {
wfcx.register_bound(
ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(item_ty)),
wfcx.param_env,
item_ty,
tcx.require_lang_item(LangItem::ConstParamTy, span),
);
}

if has_value {
let raw_ct = tcx.const_of_item(def_id).instantiate_identity();
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
return Ok(());
}

if tcx.features().const_param_ty_unchecked() {
return Ok(());
}

if !tcx.features().adt_const_params() {
match *self_type.kind() {
ty::Adt(adt, _) if adt.is_struct() => {
Expand Down
111 changes: 88 additions & 23 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,24 +380,44 @@ pub trait GenericArgsLowerer<'a, 'tcx> {
) -> ty::GenericArg<'tcx>;
}

struct ForbidMCGParamUsesFolder<'tcx> {
/// Context in which `ForbidParamUsesFolder` is being used, to emit appropriate diagnostics.
enum ForbidParamContext {
/// Anon const in a const argument position.
ConstArgument,
/// Enum discriminant expression.
EnumDiscriminant,
}

struct ForbidParamUsesFolder<'tcx> {
tcx: TyCtxt<'tcx>,
anon_const_def_id: LocalDefId,
span: Span,
is_self_alias: bool,
context: ForbidParamContext,
}

impl<'tcx> ForbidMCGParamUsesFolder<'tcx> {
impl<'tcx> ForbidParamUsesFolder<'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().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"
let msg = match self.context {
ForbidParamContext::EnumDiscriminant if self.is_self_alias => {
"generic `Self` types are not permitted in enum discriminant values"
}
ForbidParamContext::EnumDiscriminant => {
"generic parameters may not be used in enum discriminant values"
}
ForbidParamContext::ConstArgument if self.is_self_alias => {
"generic `Self` types are currently not permitted in anonymous constants"
}
ForbidParamContext::ConstArgument => {
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"
}
}
};
let mut diag = self.tcx.dcx().struct_span_err(self.span, msg);
if self.is_self_alias {
if self.is_self_alias && matches!(self.context, ForbidParamContext::ConstArgument) {
let anon_const_hir_id: HirId = HirId::make_owner(self.anon_const_def_id);
let parent_impl = self.tcx.hir_parent_owner_iter(anon_const_hir_id).find_map(
|(_, node)| match node {
Expand All @@ -411,18 +431,20 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> {
diag.span_note(impl_.self_ty.span, "not a concrete type");
}
}
if self.tcx.features().min_generic_const_args() {
if matches!(self.context, ForbidParamContext::ConstArgument)
&& self.tcx.features().min_generic_const_args()
{
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");
}
};
}
diag.emit()
}
}

impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for ForbidMCGParamUsesFolder<'tcx> {
impl<'tcx> ty::TypeFolder<TyCtxt<'tcx>> for ForbidParamUsesFolder<'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}
Expand Down Expand Up @@ -464,37 +486,80 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&& tcx.def_kind(parent_def_id) == DefKind::AnonConst
&& let ty::AnonConstKind::MCG = tcx.anon_const_kind(parent_def_id)
{
let folder = ForbidMCGParamUsesFolder {
let folder = ForbidParamUsesFolder {
tcx,
anon_const_def_id: parent_def_id,
span,
is_self_alias: false,
context: ForbidParamContext::ConstArgument,
};
return Err(folder.error());
}
Ok(())
}

/// Returns the `ForbidParamContext` for the current anon const if it is a context that
/// forbids uses of generic parameters. `None` if the current item is not such a context.
///
/// Name resolution handles most invalid generic parameter uses in these contexts, but it
/// cannot reject `Self` that aliases a generic type, nor generic parameters introduced by
/// type-dependent name resolution (e.g. `<Self as Trait>::Assoc` resolving to a type that
/// contains params). Those cases are handled by `check_param_uses_if_mcg`.
fn anon_const_forbids_generic_params(&self) -> Option<ForbidParamContext> {
let tcx = self.tcx();
let parent_def_id = self.item_def_id();

// Inline consts and closures can be nested inside anon consts that forbid generic
// params (e.g. an enum discriminant). Walk up the def parent chain to find the
// nearest enclosing AnonConst and use that to determine the context.
let anon_const_def_id = match tcx.def_kind(parent_def_id) {
DefKind::AnonConst => parent_def_id,
DefKind::InlineConst | DefKind::Closure => {
let root = tcx.typeck_root_def_id(parent_def_id.into());
match tcx.def_kind(root) {
DefKind::AnonConst => root.expect_local(),
_ => return None,
}
}
_ => return None,
};

match tcx.anon_const_kind(anon_const_def_id) {
ty::AnonConstKind::MCG => Some(ForbidParamContext::ConstArgument),
ty::AnonConstKind::NonTypeSystem => {
// NonTypeSystem anon consts only have accessible generic parameters in specific
// positions (ty patterns and field defaults — see `generics_of`). In all other
// positions (e.g. enum discriminants) generic parameters are not in scope.
if tcx.generics_of(anon_const_def_id).count() == 0 {
Some(ForbidParamContext::EnumDiscriminant)
} else {
None
}
}
ty::AnonConstKind::GCE
| ty::AnonConstKind::GCA
| ty::AnonConstKind::RepeatExprCount => None,
}
}

/// Check for uses of generic parameters that are not in scope due to this being
/// in a non-generic anon const context.
/// in a non-generic anon const context (e.g. MCG or an enum discriminant).
///
/// Name resolution rejects most invalid uses, but cannot handle `Self` aliasing a
/// generic type or generic parameters introduced by type-dependent name resolution.
#[must_use = "need to use transformed output"]
fn check_param_uses_if_mcg<T>(&self, term: T, span: Span, is_self_alias: bool) -> T
where
T: ty::TypeFoldable<TyCtxt<'tcx>>,
{
let tcx = self.tcx();
let parent_def_id = self.item_def_id();
if tcx.def_kind(parent_def_id) == DefKind::AnonConst
&& let ty::AnonConstKind::MCG = tcx.anon_const_kind(parent_def_id)
if let Some(context) = self.anon_const_forbids_generic_params()
// Fast path if contains no params/escaping bound vars.
&& (term.has_param() || term.has_escaping_bound_vars())
{
let mut folder = ForbidMCGParamUsesFolder {
tcx,
anon_const_def_id: parent_def_id,
span,
is_self_alias,
};
let anon_const_def_id = self.item_def_id();
let mut folder =
ForbidParamUsesFolder { tcx, anon_const_def_id, span, is_self_alias, context };
term.fold_with(&mut folder)
} else {
term
Expand Down
7 changes: 4 additions & 3 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2377,8 +2377,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
continue;
}

// This pick is not a supertrait of the `child_pick`.
// Check if it's a subtrait of the `child_pick`, instead.
// This candidate is not a supertrait of the `child_trait`.
// Check if it's a subtrait of the `child_trait`, instead.
// If it is, then it must have been a subtrait of every
// other pick we've eliminated at this point. It will
// take over at this point.
Expand All @@ -2392,7 +2392,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
continue;
}

// `child_pick` is not a supertrait of this pick.
// Neither `child_trait` or the current candidate are
// supertraits of each other.
// Don't bail here, since we may be comparing two supertraits
// of a common subtrait. These two supertraits won't be related
// at all, but we will pick them up next round when we find their
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::Path(..)
| AttributeKind::PatternComplexityLimit { .. }
| AttributeKind::PinV2(..)
| AttributeKind::Pointee(..)
| AttributeKind::PreludeImport
| AttributeKind::ProfilerRuntime
| AttributeKind::RecursionLimit { .. }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ symbols! {
const_panic,
const_panic_fmt,
const_param_ty,
const_param_ty_unchecked,
const_precise_live_drops,
const_ptr_cast,
const_raw_ptr_deref,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_trait_selection/src/traits/wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
if self.tcx().is_lang_item(def_id, LangItem::Sized) {
return Default::default();
}
if self.tcx().is_lang_item(def_id, LangItem::ConstParamTy)
&& self.tcx().features().const_param_ty_unchecked()
{
return Default::default();
}

let predicates = self.tcx().predicates_of(def_id);
let mut origins = vec![def_id; predicates.predicates.len()];
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/char/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1932,6 +1932,9 @@ impl char {
/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
/// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
///
/// **Warning:** Because the list above excludes U+000B VERTICAL TAB,
/// `c.is_ascii_whitespace()` is **not** equivalent to `c.is_ascii() && c.is_whitespace()`.
///
/// Rust uses the WhatWG Infra Standard's [definition of ASCII
/// whitespace][infra-aw]. There are several other definitions in
/// wide use. For instance, [the POSIX locale][pct] includes
Expand Down
6 changes: 5 additions & 1 deletion library/core/src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,9 +1095,13 @@ pub macro ConstParamTy($item:item) {
/* compiler built-in */
}

// For `adt_const_params` to be recognized as a feature
#[unstable(feature = "adt_const_params", issue = "95174")]
const _: () = ();

// FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure`
marker_impls! {
#[unstable(feature = "adt_const_params", issue = "95174")]
#[unstable(feature = "min_adt_const_params", issue = "154042")]
ConstParamTy_ for
usize, u8, u16, u32, u64, u128,
isize, i8, i16, i32, i64, i128,
Expand Down
3 changes: 3 additions & 0 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,9 @@ impl u8 {
/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
/// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
///
/// **Warning:** Because the list above excludes U+000B VERTICAL TAB,
/// `b.is_ascii_whitespace()` is **not** equivalent to `char::from(b).is_whitespace()`.
///
/// Rust uses the WhatWG Infra Standard's [definition of ASCII
/// whitespace][infra-aw]. There are several other definitions in
/// wide use. For instance, [the POSIX locale][pct] includes
Expand Down
Loading
Loading