Auto merge of #152373 - Zalathar:rollup-wDsfoHs, r=Zalathar
Rollup of 4 pull requests Successful merges: - rust-lang/rust#150823 (Implement MVP for opaque generic const arguments) - rust-lang/rust#152071 (Implement stdio FD constants) - rust-lang/rust#152171 (Port `rustc_strict_coherence` to the new attribute parser) - rust-lang/rust#152291 (Port `rustc_insignificant_dtor`) Failed merges: - rust-lang/rust#152180 (Port `rustc_reservation_impl` to the new attribute parser)
This commit is contained in:
commit
4cd4c18438
59 changed files with 457 additions and 73 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// tidy-alphabetical-start
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_is_partitioned)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -739,6 +739,19 @@ impl<S: Stage> CombineAttributeParser<S> for RustcThenThisWouldNeedParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcInsignificantDtorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcInsignificantDtorParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::ForeignTy),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcEffectiveVisibilityParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
|
||||
|
|
@ -845,3 +858,18 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicConstStableIndirectPar
|
|||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcStrictCoherenceParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_strict_coherence];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Trait),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::ForeignTy),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcEvaluateWhereClausesParser>>,
|
||||
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
|
||||
Single<WithoutArgs<RustcHiddenTypeOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcInsignificantDtorParser>>,
|
||||
Single<WithoutArgs<RustcIntrinsicConstStableIndirectParser>>,
|
||||
Single<WithoutArgs<RustcIntrinsicParser>>,
|
||||
Single<WithoutArgs<RustcLintOptTyParser>>,
|
||||
|
|
@ -289,6 +290,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<RustcReallocatorParser>>,
|
||||
Single<WithoutArgs<RustcRegionsParser>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<RustcStrictCoherenceParser>>,
|
||||
Single<WithoutArgs<RustcVarianceOfOpaquesParser>>,
|
||||
Single<WithoutArgs<RustcVarianceParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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]),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1126,6 +1126,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_if_this_changed]`
|
||||
RustcIfThisChanged(Span, Option<Symbol>),
|
||||
|
||||
/// Represents `#[rustc_insignificant_dtor]`
|
||||
RustcInsignificantDtor,
|
||||
|
||||
/// Represents `#[rustc_intrinsic]`
|
||||
RustcIntrinsic,
|
||||
|
||||
|
|
@ -1239,6 +1242,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_std_internal_symbol]`.
|
||||
RustcStdInternalSymbol(Span),
|
||||
|
||||
/// Represents `#[rustc_strict_coherence]`.
|
||||
RustcStrictCoherence(Span),
|
||||
|
||||
/// Represents `#[rustc_symbol_name]`
|
||||
RustcSymbolName(Span),
|
||||
|
||||
|
|
@ -1275,6 +1281,7 @@ pub enum AttributeKind {
|
|||
/// Span of the attribute.
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Represents `#[target_feature(enable = "...")]` and
|
||||
/// `#[unsafe(force_target_feature(enable = "...")]`.
|
||||
TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ impl AttributeKind {
|
|||
RustcHasIncoherentInherentImpls => Yes,
|
||||
RustcHiddenTypeOfOpaques => No,
|
||||
RustcIfThisChanged(..) => No,
|
||||
RustcInsignificantDtor => Yes,
|
||||
RustcIntrinsic => Yes,
|
||||
RustcIntrinsicConstStableIndirect => No,
|
||||
RustcLayout(..) => No,
|
||||
|
|
@ -156,6 +157,7 @@ impl AttributeKind {
|
|||
RustcSkipDuringMethodDispatch { .. } => No,
|
||||
RustcSpecializationTrait(..) => No,
|
||||
RustcStdInternalSymbol(..) => No,
|
||||
RustcStrictCoherence(..) => Yes,
|
||||
RustcSymbolName(..) => Yes,
|
||||
RustcThenThisWouldNeed(..) => No,
|
||||
RustcUnsafeSpecializationMarker(..) => No,
|
||||
|
|
|
|||
|
|
@ -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<UsesParam>;
|
||||
|
||||
fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow<UsesParam> {
|
||||
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>,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label("due to this attribute")]
|
||||
pub attr_span: Option<Span>,
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::{DefId, DefIdMap};
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::error::StrictCoherenceNeedsNegativeCoherence;
|
||||
use crate::ty::fast_reject::SimplifiedType;
|
||||
|
|
@ -61,23 +62,15 @@ pub enum OverlapMode {
|
|||
impl OverlapMode {
|
||||
pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
|
||||
let with_negative_coherence = tcx.features().with_negative_coherence();
|
||||
let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
|
||||
let strict_coherence = find_attr!(tcx.get_all_attrs(trait_id), AttributeKind::RustcStrictCoherence(span) => *span);
|
||||
|
||||
if with_negative_coherence {
|
||||
if strict_coherence { OverlapMode::Strict } else { OverlapMode::WithNegative }
|
||||
if strict_coherence.is_some() { OverlapMode::Strict } else { OverlapMode::WithNegative }
|
||||
} else {
|
||||
if strict_coherence {
|
||||
let attr_span = trait_id
|
||||
.as_local()
|
||||
.into_iter()
|
||||
.flat_map(|local_def_id| {
|
||||
tcx.hir_attrs(tcx.local_def_id_to_hir_id(local_def_id))
|
||||
})
|
||||
.find(|attr| attr.has_name(sym::rustc_strict_coherence))
|
||||
.map(|attr| attr.span());
|
||||
if let Some(span) = strict_coherence {
|
||||
tcx.dcx().emit_err(StrictCoherenceNeedsNegativeCoherence {
|
||||
span: tcx.def_span(trait_id),
|
||||
attr_span,
|
||||
attr_span: span,
|
||||
});
|
||||
}
|
||||
OverlapMode::Stable
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<I, ty::NormalizesTo<I>>,
|
||||
) -> QueryResult<I> {
|
||||
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(),
|
||||
|
|
|
|||
|
|
@ -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()?))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcHasIncoherentInherentImpls
|
||||
| AttributeKind::RustcHiddenTypeOfOpaques
|
||||
| AttributeKind::RustcIfThisChanged(..)
|
||||
| AttributeKind::RustcInsignificantDtor
|
||||
| AttributeKind::RustcIntrinsic
|
||||
| AttributeKind::RustcIntrinsicConstStableIndirect
|
||||
| AttributeKind::RustcLayout(..)
|
||||
|
|
@ -347,6 +348,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcSkipDuringMethodDispatch { .. }
|
||||
| AttributeKind::RustcSpecializationTrait(..)
|
||||
| AttributeKind::RustcStdInternalSymbol (..)
|
||||
| AttributeKind::RustcStrictCoherence(..)
|
||||
| AttributeKind::RustcSymbolName(..)
|
||||
| AttributeKind::RustcThenThisWouldNeed(..)
|
||||
| AttributeKind::RustcUnsafeSpecializationMarker(..)
|
||||
|
|
@ -389,7 +391,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| sym::default_lib_allocator
|
||||
| sym::rustc_diagnostic_item
|
||||
| sym::rustc_no_mir_inline
|
||||
| sym::rustc_insignificant_dtor
|
||||
| sym::rustc_nonnull_optimization_guaranteed
|
||||
| sym::rustc_inherit_overflow_checks
|
||||
| sym::rustc_trivial_field_reads
|
||||
|
|
@ -405,7 +406,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| sym::rustc_never_type_options
|
||||
| sym::rustc_autodiff
|
||||
| sym::rustc_capture_analysis
|
||||
| sym::rustc_strict_coherence
|
||||
| sym::rustc_mir
|
||||
| sym::rustc_partition_reused
|
||||
| sym::rustc_partition_codegened
|
||||
|
|
|
|||
|
|
@ -1628,6 +1628,7 @@ symbols! {
|
|||
on_const,
|
||||
on_unimplemented,
|
||||
opaque,
|
||||
opaque_generic_const_args,
|
||||
opaque_module_name_placeholder: "<opaque>",
|
||||
open_options_new,
|
||||
ops,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
//! Check whether a type has (potentially) non-trivial drop glue.
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components};
|
||||
use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
|
||||
use rustc_span::sym;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::errors::NeedsDropOverflow;
|
||||
|
|
@ -396,8 +397,7 @@ fn adt_consider_insignificant_dtor<'tcx>(
|
|||
tcx: TyCtxt<'tcx>,
|
||||
) -> impl Fn(ty::AdtDef<'tcx>) -> Option<DtorType> {
|
||||
move |adt_def: ty::AdtDef<'tcx>| {
|
||||
let is_marked_insig = tcx.has_attr(adt_def.did(), sym::rustc_insignificant_dtor);
|
||||
if is_marked_insig {
|
||||
if find_attr!(tcx.get_all_attrs(adt_def.did()), AttributeKind::RustcInsignificantDtor) {
|
||||
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
|
||||
// a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies
|
||||
// outside stdlib, we might choose to still annotate the wrapper (std HashMap) with
|
||||
|
|
|
|||
|
|
@ -200,3 +200,23 @@ impl<I: Interner> ValTreeKind<I> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ pub trait Interner:
|
|||
fn type_of_opaque_hir_typeck(self, def_id: Self::LocalDefId)
|
||||
-> ty::EarlyBinder<Self, Self::Ty>;
|
||||
fn const_of_item(self, def_id: Self::DefId) -> ty::EarlyBinder<Self, Self::Const>;
|
||||
fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind;
|
||||
|
||||
type AdtDef: AdtDef<Self>;
|
||||
fn adt_def(self, adt_def_id: Self::AdtId) -> Self::AdtDef;
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ use crate::vec::Vec;
|
|||
/// and other memory errors.
|
||||
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
|
||||
#[rustc_diagnostic_item = "cstring_type"]
|
||||
#[rustc_insignificant_dtor]
|
||||
#[stable(feature = "alloc_c_string", since = "1.64.0")]
|
||||
pub struct CString {
|
||||
// Invariant 1: the slice ends with a zero byte and has a length of at least one.
|
||||
|
|
@ -694,7 +695,6 @@ impl CString {
|
|||
// memory-unsafe code from working by accident. Inline
|
||||
// to prevent LLVM from optimizing it away in debug builds.
|
||||
#[stable(feature = "cstring_drop", since = "1.13.0")]
|
||||
#[rustc_insignificant_dtor]
|
||||
impl Drop for CString {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ mod owned;
|
|||
#[cfg(not(target_os = "trusty"))]
|
||||
mod net;
|
||||
|
||||
// Implementation of stdio file descriptor constants.
|
||||
mod stdio;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
|
|
@ -24,3 +27,5 @@ mod tests;
|
|||
pub use owned::*;
|
||||
#[stable(feature = "os_fd", since = "1.66.0")]
|
||||
pub use raw::*;
|
||||
#[unstable(feature = "stdio_fd_consts", issue = "150836")]
|
||||
pub use stdio::*;
|
||||
|
|
|
|||
53
library/std/src/os/fd/stdio.rs
Normal file
53
library/std/src/os/fd/stdio.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use super::BorrowedFd;
|
||||
|
||||
/// The file descriptor for the standard input stream of the current process.
|
||||
///
|
||||
/// See [`io::stdin()`][`crate::io::stdin`] for the higher level handle, which should be preferred
|
||||
/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats.
|
||||
#[unstable(feature = "stdio_fd_consts", issue = "150836")]
|
||||
pub const STDIN: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(0) };
|
||||
|
||||
/// The file descriptor for the standard output stream of the current process.
|
||||
///
|
||||
/// See [`io::stdout()`][`crate::io::stdout`] for the higher level handle, which should be preferred
|
||||
/// whenever possible. See [`STDERR`] for why the file descriptor might be required and caveats. In
|
||||
/// addition to the issues discussed there, note that [`Stdout`][`crate::io::Stdout`] is buffered by
|
||||
/// default, and writing to the file descriptor will bypass this buffer.
|
||||
#[unstable(feature = "stdio_fd_consts", issue = "150836")]
|
||||
pub const STDOUT: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(1) };
|
||||
|
||||
/// The file descriptor for the standard error stream of the current process.
|
||||
///
|
||||
/// See [`io::stderr()`][`crate::io::stderr`] for the higher level handle, which should be preferred
|
||||
/// whenever possible. However, there are situations where touching the `std::io` handles (or most
|
||||
/// other parts of the standard library) risks deadlocks or other subtle bugs. For example:
|
||||
///
|
||||
/// - Global allocators must be careful to [avoid reentrancy][global-alloc-reentrancy], and the
|
||||
/// `std::io` handles may allocate memory on (some) accesses.
|
||||
/// - Signal handlers must be *async-signal-safe*, which rules out panicking, taking locks (may
|
||||
/// deadlock if the signal handler interrupted a thread holding that lock), allocating memory, or
|
||||
/// anything else that is not explicitly declared async-signal-safe.
|
||||
/// - `CommandExt::pre_exec` callbacks can safely panic (with some limitations), but otherwise must
|
||||
/// abide by similar limitations as signal handlers. In particular, at the time these callbacks
|
||||
/// run, the stdio file descriptors have already been replaced, but the locks protecting the
|
||||
/// `std::io` handles may be permanently locked if another thread held the lock at `fork()` time.
|
||||
///
|
||||
/// In these and similar cases, direct access to the file descriptor may be required. However, in
|
||||
/// most cases, using the `std::io` handles and accessing the file descriptor via the `AsFd`
|
||||
/// implementations is preferable, as it enables cooperation with the standard library's locking and
|
||||
/// buffering.
|
||||
///
|
||||
/// # I/O safety
|
||||
///
|
||||
/// This is a `BorrowedFd<'static>` because the standard input/output/error streams are shared
|
||||
/// resources that must remain available for the lifetime of the process. This is only true when
|
||||
/// linking `std`, and may not always hold for [code running before `main()`][before-after-main] or
|
||||
/// in `no_std` environments. It is [unsound][io-safety] to close these file descriptors. Safe
|
||||
/// patterns for changing these file descriptors are available on Unix via the `StdioExt` extension
|
||||
/// trait.
|
||||
///
|
||||
/// [before-after-main]: ../../../std/index.html#use-before-and-after-main
|
||||
/// [io-safety]: ../../../std/io/index.html#io-safety
|
||||
/// [global-alloc-reentrancy]: ../../../std/alloc/trait.GlobalAlloc.html#re-entrance
|
||||
#[unstable(feature = "stdio_fd_consts", issue = "150836")]
|
||||
pub const STDERR: BorrowedFd<'static> = unsafe { BorrowedFd::borrow_raw(2) };
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -9,13 +9,11 @@ help: you might be missing a const parameter
|
|||
LL | impl<const bar: /* Type */> 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<const F: fn()>;
|
||||
| ^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool`, and `char`
|
||||
|
||||
error[E0599]: the function or associated item `call` exists for struct `Wrapper<function>`, 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`.
|
||||
|
|
|
|||
|
|
@ -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<i32> + Parent0<u32> {}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
|
||||
--> $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...
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<Ty = i32, CT = 0>;
|
||||
| ^ 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<Ty = i32, CT = 0> = &();
|
||||
| ^ 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 () {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ error: generic parameters may not be used in const operations
|
|||
|
|
||||
LL | foo::<{ Some::<u32> { 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
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ error: generic parameters may not be used in const operations
|
|||
|
|
||||
LL | T: Trait<const { let a: &'a (); 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
|
||||
|
||||
|
|
|
|||
|
|
@ -39,42 +39,56 @@ error: generic parameters may not be used in const operations
|
|||
|
|
||||
LL | const ITEM3<const N: usize>: 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<ASSOC = 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:69:58
|
||||
|
|
||||
LL | struct Default3<const N: usize, const M: 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: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<const N: usize> = Foo<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:19:42
|
||||
|
|
||||
LL | type Arr3<const N: usize> = [(); 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
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ note: not a concrete type
|
|||
|
|
||||
LL | impl<const N: usize> S<N> {
|
||||
| ^^^^
|
||||
= help: add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,16 @@ error: generic parameters may not be used in const operations
|
|||
|
|
||||
LL | const FREE1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
| ^
|
||||
|
|
||||
= 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<const I: usize>: 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
|
||||
|
||||
|
|
|
|||
|
|
@ -3,18 +3,24 @@ error: generic parameters may not be used in const operations
|
|||
|
|
||||
LL | const N1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
| ^
|
||||
|
|
||||
= 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<const I: usize>: 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
||||
|
|
|
|||
|
|
@ -48,16 +48,6 @@ LL | generic::<const { 1 }>();
|
|||
= 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 <https://github.com/rust-lang/rust/issues/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`.
|
||||
|
|
|
|||
22
tests/ui/const-generics/ogca/basic-fail.rs
Normal file
22
tests/ui/const-generics/ogca/basic-fail.rs
Normal file
|
|
@ -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<const N: usize>: usize = const { N + 1 };
|
||||
|
||||
#[type_const]
|
||||
const INC<const N: usize>: 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() {}
|
||||
9
tests/ui/const-generics/ogca/basic-fail.stderr
Normal file
9
tests/ui/const-generics/ogca/basic-fail.stderr
Normal file
|
|
@ -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`.
|
||||
22
tests/ui/const-generics/ogca/basic.rs
Normal file
22
tests/ui/const-generics/ogca/basic.rs
Normal file
|
|
@ -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<const N: usize>: usize = const { N + 1 };
|
||||
|
||||
#[type_const]
|
||||
const INC<const N: usize>: usize = ADD1::<N>;
|
||||
|
||||
#[type_const]
|
||||
const ONE: usize = ADD1::<0>;
|
||||
|
||||
#[type_const]
|
||||
const OTHER_ONE: usize = INC::<0>;
|
||||
|
||||
const ARR: [(); ADD1::<0>] = [(); INC::<0>];
|
||||
|
||||
fn main() {}
|
||||
21
tests/ui/const-generics/ogca/coherence-ambiguous.rs
Normal file
21
tests/ui/const-generics/ogca/coherence-ambiguous.rs
Normal file
|
|
@ -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<const N: usize>: usize = const { N + 1 };
|
||||
|
||||
#[type_const]
|
||||
const BAR<const N: usize>: 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() {}
|
||||
14
tests/ui/const-generics/ogca/rhs-but-not-root.rs
Normal file
14
tests/ui/const-generics/ogca/rhs-but-not-root.rs
Normal file
|
|
@ -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<const N: usize>: usize = ID::<const { N + 1 }>;
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
|
||||
#[type_const]
|
||||
const ID<const N: usize>: usize = N;
|
||||
|
||||
fn main() {}
|
||||
8
tests/ui/const-generics/ogca/rhs-but-not-root.stderr
Normal file
8
tests/ui/const-generics/ogca/rhs-but-not-root.stderr
Normal file
|
|
@ -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<const N: usize>: usize = ID::<const { N + 1 }>;
|
||||
| ^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#![feature(generic_const_items, min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
#[type_const]
|
||||
const INC<const N: usize>: usize = const { N + 1 };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
//~| HELP add `#![feature(opaque_generic_const_args)]`
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -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<const N: usize>: 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
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue