Rollup merge of #148716 - camelid:finish-type_const, r=BoxyUwU
mgca: Finish implementation of `#[type_const]` tracking issue: rust-lang/rust#132980 fixes rust-lang/rust#140729 fixes rust-lang/rust#140860 - **Fix `#[type_const]` attribute placement validation** - **Perform WF-checking on type_const RHS's** - **Check type_const type is ConstParamTy_ and that RHS matches it** - **Check that impls of `#[type_const]` consts also have the attr** r? ```@BoxyUwU```
This commit is contained in:
commit
7e9b67d355
34 changed files with 537 additions and 171 deletions
|
|
@ -66,7 +66,8 @@ pub(crate) struct TypeConstParser;
|
|||
impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
|
||||
const PATH: &[Symbol] = &[sym::type_const];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]);
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3065,7 +3065,7 @@ macro_rules! expect_methods_self_kind {
|
|||
$(
|
||||
#[track_caller]
|
||||
pub fn $name(&self) -> $ret_ty {
|
||||
let $pat = &self.kind else { expect_failed(stringify!($ident), self) };
|
||||
let $pat = &self.kind else { expect_failed(stringify!($name), self) };
|
||||
$ret_val
|
||||
}
|
||||
)*
|
||||
|
|
@ -3077,7 +3077,7 @@ macro_rules! expect_methods_self {
|
|||
$(
|
||||
#[track_caller]
|
||||
pub fn $name(&self) -> $ret_ty {
|
||||
let $pat = self else { expect_failed(stringify!($ident), self) };
|
||||
let $pat = self else { expect_failed(stringify!($name), self) };
|
||||
$ret_val
|
||||
}
|
||||
)*
|
||||
|
|
@ -4790,6 +4790,11 @@ impl<'hir> Node<'hir> {
|
|||
ForeignItemKind::Static(ty, ..) => Some(ty),
|
||||
_ => None,
|
||||
},
|
||||
Node::GenericParam(param) => match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => None,
|
||||
GenericParamKind::Type { default, .. } => default,
|
||||
GenericParamKind::Const { ty, .. } => Some(ty),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -757,22 +757,18 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
}
|
||||
|
||||
match tcx.def_kind(def_id) {
|
||||
def_kind @ (DefKind::Static { .. } | DefKind::Const) => {
|
||||
DefKind::Static { .. } => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
match def_kind {
|
||||
DefKind::Static { .. } => {
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
res = res.and(wfcheck::check_static_item(
|
||||
tcx, def_id, ty, /* should_check_for_sync */ true,
|
||||
));
|
||||
}
|
||||
DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
res = res.and(wfcheck::check_static_item(
|
||||
tcx, def_id, ty, /* should_check_for_sync */ true,
|
||||
));
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
|
|
@ -900,6 +896,39 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::Const => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
tcx.ensure_ok().predicates_of(def_id);
|
||||
|
||||
res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let ty_span = tcx.ty_span(def_id);
|
||||
let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
|
||||
wfcx.register_bound(
|
||||
traits::ObligationCause::new(
|
||||
ty_span,
|
||||
def_id,
|
||||
ObligationCauseCode::SizedConstOrStatic,
|
||||
),
|
||||
tcx.param_env(def_id),
|
||||
ty,
|
||||
tcx.require_lang_item(LangItem::Sized, ty_span),
|
||||
);
|
||||
check_where_clauses(wfcx, def_id);
|
||||
|
||||
if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) {
|
||||
wfcheck::check_type_const(wfcx, def_id, ty, true)?;
|
||||
}
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::TyAlias => {
|
||||
tcx.ensure_ok().generics_of(def_id);
|
||||
tcx.ensure_ok().type_of(def_id);
|
||||
|
|
@ -920,6 +949,11 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
}));
|
||||
check_variances_for_type_defn(tcx, def_id);
|
||||
}
|
||||
|
||||
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
|
||||
// checks. Returning early here does not miss any checks and
|
||||
// avoids this query from having a direct dependency edge on the HIR
|
||||
return res;
|
||||
}
|
||||
DefKind::ForeignMod => {
|
||||
let it = tcx.hir_expect_item(def_id);
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId};
|
|||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::intravisit::VisitorExt;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit};
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit};
|
||||
use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt};
|
||||
use rustc_infer::traits::util;
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
|
|
@ -1984,12 +1985,46 @@ fn compare_impl_const<'tcx>(
|
|||
trait_const_item: ty::AssocItem,
|
||||
impl_trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
compare_type_const(tcx, impl_const_item, trait_const_item)?;
|
||||
compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
|
||||
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
|
||||
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
|
||||
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
|
||||
}
|
||||
|
||||
fn compare_type_const<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
impl_const_item: ty::AssocItem,
|
||||
trait_const_item: ty::AssocItem,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let impl_is_type_const =
|
||||
find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_));
|
||||
let trait_type_const_span = find_attr!(
|
||||
tcx.get_all_attrs(trait_const_item.def_id),
|
||||
AttributeKind::TypeConst(sp) => *sp
|
||||
);
|
||||
|
||||
if let Some(trait_type_const_span) = trait_type_const_span
|
||||
&& !impl_is_type_const
|
||||
{
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
tcx.def_span(impl_const_item.def_id),
|
||||
"implementation of `#[type_const]` const must be marked with `#[type_const]`",
|
||||
)
|
||||
.with_span_note(
|
||||
MultiSpan::from_spans(vec![
|
||||
tcx.def_span(trait_const_item.def_id),
|
||||
trait_type_const_span,
|
||||
]),
|
||||
"trait declaration of const is marked with `#[type_const]`",
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The equivalent of [compare_method_predicate_entailment], but for associated constants
|
||||
/// instead of associated functions.
|
||||
// FIXME(generic_const_items): If possible extract the common parts of `compare_{type,const}_predicate_entailment`.
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ use rustc_abi::ExternAbi;
|
|||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{AmbigArg, ItemKind};
|
||||
use rustc_hir::{AmbigArg, ItemKind, find_attr};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};
|
||||
use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
|
||||
|
|
@ -925,11 +926,11 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
|
|||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub(crate) fn check_associated_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
item_id: LocalDefId,
|
||||
def_id: LocalDefId,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let loc = Some(WellFormedLoc::Ty(item_id));
|
||||
enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
|
||||
let item = tcx.associated_item(item_id);
|
||||
let loc = Some(WellFormedLoc::Ty(def_id));
|
||||
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let item = tcx.associated_item(def_id);
|
||||
|
||||
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
|
||||
// other `Foo` impls are incoherent.
|
||||
|
|
@ -942,27 +943,36 @@ pub(crate) fn check_associated_item(
|
|||
}
|
||||
};
|
||||
|
||||
let span = tcx.def_span(item_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
match item.kind {
|
||||
ty::AssocKind::Const { .. } => {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
check_sized_if_body(
|
||||
wfcx,
|
||||
item.def_id.expect_local(),
|
||||
ty,
|
||||
Some(span),
|
||||
ObligationCauseCode::SizedConstOrStatic,
|
||||
);
|
||||
|
||||
let has_value = item.defaultness(tcx).has_value();
|
||||
if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) {
|
||||
check_type_const(wfcx, def_id, ty, has_value)?;
|
||||
}
|
||||
|
||||
if has_value {
|
||||
let code = ObligationCauseCode::SizedConstOrStatic;
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(span, def_id, code),
|
||||
wfcx.param_env,
|
||||
ty,
|
||||
tcx.require_lang_item(LangItem::Sized, span),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
ty::AssocKind::Fn { .. } => {
|
||||
let sig = tcx.fn_sig(item.def_id).instantiate_identity();
|
||||
let sig = tcx.fn_sig(def_id).instantiate_identity();
|
||||
let hir_sig =
|
||||
tcx.hir_node_by_def_id(item_id).fn_sig().expect("bad signature for method");
|
||||
check_fn_or_method(wfcx, sig, hir_sig.decl, item_id);
|
||||
tcx.hir_node_by_def_id(def_id).fn_sig().expect("bad signature for method");
|
||||
check_fn_or_method(wfcx, sig, hir_sig.decl, def_id);
|
||||
check_method_receiver(wfcx, hir_sig, item, self_ty)
|
||||
}
|
||||
ty::AssocKind::Type { .. } => {
|
||||
|
|
@ -970,8 +980,8 @@ pub(crate) fn check_associated_item(
|
|||
check_associated_type_bounds(wfcx, item, span)
|
||||
}
|
||||
if item.defaultness(tcx).has_value() {
|
||||
let ty = tcx.type_of(item.def_id).instantiate_identity();
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -1222,28 +1232,36 @@ pub(crate) fn check_static_item<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
|
||||
enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
|
||||
let ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let ty_span = tcx.ty_span(def_id);
|
||||
let ty = wfcx.deeply_normalize(ty_span, Some(WellFormedLoc::Ty(def_id)), ty);
|
||||
#[instrument(level = "debug", skip(wfcx))]
|
||||
pub(super) fn check_type_const<'tcx>(
|
||||
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
||||
def_id: LocalDefId,
|
||||
item_ty: Ty<'tcx>,
|
||||
has_value: bool,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = wfcx.tcx();
|
||||
let span = tcx.def_span(def_id);
|
||||
|
||||
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(def_id)), ty.into());
|
||||
wfcx.register_bound(
|
||||
traits::ObligationCause::new(
|
||||
ty_span,
|
||||
wfcx.body_def_id,
|
||||
ObligationCauseCode::SizedConstOrStatic,
|
||||
),
|
||||
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();
|
||||
let norm_ct = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), raw_ct);
|
||||
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(def_id)), norm_ct.into());
|
||||
|
||||
wfcx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
ObligationCause::new(span, def_id, ObligationCauseCode::WellFormed(None)),
|
||||
wfcx.param_env,
|
||||
ty,
|
||||
tcx.require_lang_item(LangItem::Sized, ty_span),
|
||||
);
|
||||
|
||||
check_where_clauses(wfcx, def_id);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(norm_ct, item_ty)),
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx, impl_))]
|
||||
|
|
@ -1583,33 +1601,16 @@ fn check_fn_or_method<'tcx>(
|
|||
}
|
||||
|
||||
// If the function has a body, additionally require that the return type is sized.
|
||||
check_sized_if_body(
|
||||
wfcx,
|
||||
def_id,
|
||||
sig.output(),
|
||||
match hir_decl.output {
|
||||
hir::FnRetTy::Return(ty) => Some(ty.span),
|
||||
hir::FnRetTy::DefaultReturn(_) => None,
|
||||
},
|
||||
ObligationCauseCode::SizedReturnType,
|
||||
);
|
||||
}
|
||||
|
||||
fn check_sized_if_body<'tcx>(
|
||||
wfcx: &WfCheckingCtxt<'_, 'tcx>,
|
||||
def_id: LocalDefId,
|
||||
ty: Ty<'tcx>,
|
||||
maybe_span: Option<Span>,
|
||||
code: ObligationCauseCode<'tcx>,
|
||||
) {
|
||||
let tcx = wfcx.tcx();
|
||||
if let Some(body) = tcx.hir_maybe_body_owned_by(def_id) {
|
||||
let span = maybe_span.unwrap_or(body.value.span);
|
||||
let span = match hir_decl.output {
|
||||
hir::FnRetTy::Return(ty) => ty.span,
|
||||
hir::FnRetTy::DefaultReturn(_) => body.value.span,
|
||||
};
|
||||
|
||||
wfcx.register_bound(
|
||||
ObligationCause::new(span, def_id, code),
|
||||
ObligationCause::new(span, def_id, ObligationCauseCode::SizedReturnType),
|
||||
wfcx.param_env,
|
||||
ty,
|
||||
sig.output(),
|
||||
tcx.require_lang_item(LangItem::Sized, span),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1611,8 +1611,12 @@ fn const_of_item<'tcx>(
|
|||
};
|
||||
let ct_arg = match ct_rhs {
|
||||
hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
|
||||
hir::ConstItemRhs::Body(body_id) => {
|
||||
bug!("cannot call const_of_item on a non-type_const {body_id:?}")
|
||||
hir::ConstItemRhs::Body(_) => {
|
||||
let e = tcx.dcx().span_delayed_bug(
|
||||
tcx.def_span(def_id),
|
||||
"cannot call const_of_item on a non-type_const",
|
||||
);
|
||||
return ty::EarlyBinder::bind(Const::new_error(tcx, e));
|
||||
}
|
||||
};
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
|
|
|
|||
|
|
@ -150,9 +150,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
|
||||
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => {
|
||||
self.check_type_const(hir_id, attr_span, target)
|
||||
}
|
||||
Attribute::Parsed(
|
||||
AttributeKind::Stability {
|
||||
span: attr_span,
|
||||
|
|
@ -242,6 +239,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::ParenSugar(..)
|
||||
| AttributeKind::AllowIncoherentImpl(..)
|
||||
| AttributeKind::Confusables { .. }
|
||||
| AttributeKind::TypeConst{..}
|
||||
// `#[doc]` is actually a lot more than just doc comments, so is checked below
|
||||
| AttributeKind::DocComment {..}
|
||||
// handled below this loop and elsewhere
|
||||
|
|
@ -2114,16 +2112,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_type_const(&self, _hir_id: HirId, attr_span: Span, target: Target) {
|
||||
if matches!(target, Target::AssocConst | Target::Const) {
|
||||
return;
|
||||
} else {
|
||||
self.dcx()
|
||||
.struct_span_err(attr_span, "`#[type_const]` must only be applied to const items")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
|
||||
if !find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent))
|
||||
.unwrap_or(false)
|
||||
|
|
|
|||
|
|
@ -1286,12 +1286,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
ty: Ty<'tcx>,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
) -> Diag<'a> {
|
||||
let param = obligation.cause.body_id;
|
||||
let hir::GenericParamKind::Const { ty: &hir::Ty { span, .. }, .. } =
|
||||
self.tcx.hir_node_by_def_id(param).expect_generic_param().kind
|
||||
else {
|
||||
bug!()
|
||||
};
|
||||
let def_id = obligation.cause.body_id;
|
||||
let span = self.tcx.ty_span(def_id);
|
||||
|
||||
let mut file = None;
|
||||
let ty_str = self.tcx.short_string(ty, &mut file);
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
//@ known-bug: #140729
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
const C: usize = 0;
|
||||
pub struct A<const M: usize> {}
|
||||
impl A<C> {
|
||||
fn fun1() {}
|
||||
}
|
||||
impl A {
|
||||
fn fun1() {}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
//@ known-bug: #140860
|
||||
#![feature(min_generic_const_args)]
|
||||
#![feature(unsized_const_params)]
|
||||
#![feature(with_negative_coherence, negative_impls)]
|
||||
trait a < const b : &'static str> {} trait c {} struct d< e >(e);
|
||||
impl<e> c for e where e: a<""> {}
|
||||
impl<e> c for d<e> {}
|
||||
impl<e> !a<f> for e {}
|
||||
const f : &str = "";
|
||||
fn main() {}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
// We used to say "ambiguous associated type" on ambiguous associated consts.
|
||||
// Ensure that we now use the correct label.
|
||||
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait0: Parent0<i32> + Parent0<u32> {}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
// Check that we eventually catch types of assoc const bounds
|
||||
// (containing late-bound vars) that are ill-formed.
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(
|
||||
associated_const_equality,
|
||||
min_generic_const_args,
|
||||
adt_const_params,
|
||||
unsized_const_params,
|
||||
)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait<T> {
|
||||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait<T: ConstParamTy_> {
|
||||
#[type_const]
|
||||
const K: T;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:14:13
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
|
|
@ -13,7 +13,7 @@ LL | K = { () }
|
|||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: implementation of `Project` is not general enough
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:12:13
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:19:13
|
||||
|
|
||||
LL | _: impl Trait<
|
||||
| _____________^
|
||||
|
|
|
|||
|
|
@ -3,10 +3,17 @@
|
|||
//
|
||||
//@ check-pass
|
||||
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(
|
||||
associated_const_equality,
|
||||
min_generic_const_args,
|
||||
adt_const_params,
|
||||
unsized_const_params,
|
||||
)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait<T> {
|
||||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait<T: ConstParamTy_> {
|
||||
#[type_const]
|
||||
const K: T;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Detect and reject escaping late-bound generic params in
|
||||
// the type of assoc consts used in an equality bound.
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait<'a> {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
// Regression test for issue #108271.
|
||||
// Detect and reject generic params in the type of assoc consts used in an equality bound.
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(
|
||||
associated_const_equality,
|
||||
min_generic_const_args,
|
||||
adt_const_params,
|
||||
unsized_const_params,
|
||||
)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait<'a, T: 'a, const N: usize> {
|
||||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> {
|
||||
#[type_const]
|
||||
const K: &'a [T; N];
|
||||
}
|
||||
|
||||
fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
//~| NOTE the lifetime parameter `'r` is defined here
|
||||
|
|
@ -22,7 +29,7 @@ fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
|||
//~| NOTE the const parameter `Q` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
|
||||
trait Project {
|
||||
trait Project: ConstParamTy_ {
|
||||
#[type_const]
|
||||
const SELF: Self;
|
||||
}
|
||||
|
|
@ -38,7 +45,7 @@ fn take2<P: Project<SELF = {}>>(_: P) {}
|
|||
//~| NOTE the type parameter `P` is defined here
|
||||
//~| NOTE `SELF` has type `P`
|
||||
|
||||
trait Iface<'r> {
|
||||
trait Iface<'r>: ConstParamTy_ {
|
||||
//~^ NOTE the lifetime parameter `'r` is defined here
|
||||
//~| NOTE the lifetime parameter `'r` is defined here
|
||||
type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:11:61
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:11:61
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:11:61
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
|
|
||||
LL | fn take0<'r, A: 'r, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on `impl Trait`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:30:26
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:37:26
|
||||
|
|
||||
LL | fn take1(_: impl Project<SELF = {}>) {}
|
||||
| -------------^^^^------
|
||||
|
|
@ -34,7 +34,7 @@ LL | fn take1(_: impl Project<SELF = {}>) {}
|
|||
| the `impl Trait` is specified here
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:35:21
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:42:21
|
||||
|
|
||||
LL | fn take2<P: Project<SELF = {}>>(_: P) {}
|
||||
| - ^^^^ its type must not depend on the type parameter `P`
|
||||
|
|
@ -44,9 +44,9 @@ LL | fn take2<P: Project<SELF = {}>>(_: P) {}
|
|||
= note: `SELF` has type `P`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | trait Iface<'r> {
|
||||
LL | trait Iface<'r>: ConstParamTy_ {
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
...
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
|
|
@ -55,7 +55,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on `Self`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| ^ its type must not depend on `Self`
|
||||
|
|
@ -63,7 +63,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
|
|
@ -73,9 +73,9 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | trait Iface<'r> {
|
||||
LL | trait Iface<'r>: ConstParamTy_ {
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
...
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
|
|
@ -85,7 +85,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on `Self`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| ^ its type must not depend on `Self`
|
||||
|
|
@ -94,7 +94,7 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
|
|
|
|||
|
|
@ -3,12 +3,19 @@
|
|||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(
|
||||
associated_const_equality,
|
||||
min_generic_const_args,
|
||||
adt_const_params,
|
||||
unsized_const_params,
|
||||
)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait: SuperTrait {}
|
||||
trait SuperTrait: SuperSuperTrait<i32> {}
|
||||
trait SuperSuperTrait<T> {
|
||||
trait SuperSuperTrait<T: ConstParamTy_> {
|
||||
#[type_const]
|
||||
const K: T;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
//@ check-pass
|
||||
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait: SuperTrait {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
//@ check-pass
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args, generic_const_items)]
|
||||
|
||||
pub trait Tr<const X: usize> {
|
||||
#[type_const]
|
||||
const N1<T>: usize;
|
||||
#[type_const]
|
||||
const N2<const I: usize>: usize;
|
||||
#[type_const]
|
||||
const N3: usize;
|
||||
}
|
||||
|
||||
pub struct S;
|
||||
|
||||
impl<const X: usize> Tr<X> for S {
|
||||
#[type_const]
|
||||
const N1<T>: usize = 0;
|
||||
#[type_const]
|
||||
const N2<const I: usize>: usize = 1;
|
||||
#[type_const]
|
||||
const N3: usize = 2;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Regression test for #140729
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
const C: usize = 0;
|
||||
pub struct A<const M: usize> {}
|
||||
impl A<C> {
|
||||
fn fun1() {}
|
||||
//~^ ERROR duplicate definitions with name `fun1`
|
||||
}
|
||||
impl A {
|
||||
//~^ ERROR missing generics for struct `A`
|
||||
fn fun1() {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
error[E0107]: missing generics for struct `A`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:12:6
|
||||
|
|
||||
LL | impl A {
|
||||
| ^ expected 1 generic argument
|
||||
|
|
||||
note: struct defined here, with 1 generic parameter: `M`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:7:12
|
||||
|
|
||||
LL | pub struct A<const M: usize> {}
|
||||
| ^ --------------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | impl A<M> {
|
||||
| +++
|
||||
|
||||
error[E0592]: duplicate definitions with name `fun1`
|
||||
--> $DIR/const-arg-coherence-conflicting-methods.rs:9:5
|
||||
|
|
||||
LL | fn fun1() {}
|
||||
| ^^^^^^^^^ duplicate definitions for `fun1`
|
||||
...
|
||||
LL | fn fun1() {}
|
||||
| --------- other definition for `fun1`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0592.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
23
tests/ui/const-generics/mgca/type_const-mismatched-types.rs
Normal file
23
tests/ui/const-generics/mgca/type_const-mismatched-types.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
#[type_const]
|
||||
const FREE: u32 = 5_usize;
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
#[type_const]
|
||||
const FREE2: isize = FREE;
|
||||
//~^ ERROR the constant `5` is not of type `isize`
|
||||
|
||||
trait Tr {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
}
|
||||
|
||||
impl Tr for () {
|
||||
#[type_const]
|
||||
const N: usize = false;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
error: the constant `5` is not of type `isize`
|
||||
--> $DIR/type_const-mismatched-types.rs:9:1
|
||||
|
|
||||
LL | const FREE2: isize = FREE;
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `isize`, found `u32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_const-mismatched-types.rs:5:19
|
||||
|
|
||||
LL | const FREE: u32 = 5_usize;
|
||||
| ^^^^^^^ expected `u32`, found `usize`
|
||||
|
|
||||
help: change the type of the numeric literal from `usize` to `u32`
|
||||
|
|
||||
LL - const FREE: u32 = 5_usize;
|
||||
LL + const FREE: u32 = 5_u32;
|
||||
|
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/type_const-mismatched-types.rs:19:22
|
||||
|
|
||||
LL | const N: usize = false;
|
||||
| ^^^^^ expected `usize`, found `bool`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
26
tests/ui/const-generics/mgca/type_const-not-constparamty.rs
Normal file
26
tests/ui/const-generics/mgca/type_const-not-constparamty.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args)]
|
||||
|
||||
struct S;
|
||||
|
||||
// FIXME(mgca): need support for ctors without anon const
|
||||
// (we use double-braces to trigger an anon const here)
|
||||
#[type_const]
|
||||
const FREE: S = { { S } };
|
||||
//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
|
||||
trait Tr {
|
||||
#[type_const]
|
||||
const N: S;
|
||||
//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
}
|
||||
|
||||
impl Tr for S {
|
||||
// FIXME(mgca): need support for ctors without anon const
|
||||
// (we use double-braces to trigger an anon const here)
|
||||
#[type_const]
|
||||
const N: S = { { S } };
|
||||
//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
--> $DIR/type_const-not-constparamty.rs:9:13
|
||||
|
|
||||
LL | const FREE: S = { { S } };
|
||||
| ^
|
||||
|
|
||||
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
||||
|
|
||||
LL + #[derive(ConstParamTy, PartialEq, Eq)]
|
||||
LL | struct S;
|
||||
|
|
||||
|
||||
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
--> $DIR/type_const-not-constparamty.rs:22:14
|
||||
|
|
||||
LL | const N: S = { { S } };
|
||||
| ^
|
||||
|
|
||||
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
||||
|
|
||||
LL + #[derive(ConstParamTy, PartialEq, Eq)]
|
||||
LL | struct S;
|
||||
|
|
||||
|
||||
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
--> $DIR/type_const-not-constparamty.rs:14:14
|
||||
|
|
||||
LL | const N: S;
|
||||
| ^
|
||||
|
|
||||
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
||||
|
|
||||
LL + #[derive(ConstParamTy, PartialEq, Eq)]
|
||||
LL | struct S;
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0741`.
|
||||
34
tests/ui/const-generics/mgca/type_const-on-generic-expr.rs
Normal file
34
tests/ui/const-generics/mgca/type_const-on-generic-expr.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#![expect(incomplete_features)]
|
||||
#![feature(min_generic_const_args, generic_const_items)]
|
||||
|
||||
#[type_const]
|
||||
const FREE1<T>: usize = std::mem::size_of::<T>();
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const FREE2<const I: usize>: usize = I + 1;
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
|
||||
pub trait Tr<const X: usize> {
|
||||
#[type_const]
|
||||
const N1<T>: usize;
|
||||
#[type_const]
|
||||
const N2<const I: usize>: usize;
|
||||
#[type_const]
|
||||
const N3: usize;
|
||||
}
|
||||
|
||||
pub struct S;
|
||||
|
||||
impl<const X: usize> Tr<X> for S {
|
||||
#[type_const]
|
||||
const N1<T>: usize = std::mem::size_of::<T>();
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const N2<const I: usize>: usize = I + 1;
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const N3: usize = 2 & X;
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:5:45
|
||||
|
|
||||
LL | const FREE1<T>: usize = std::mem::size_of::<T>();
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
||||
= note: type parameters may not be used in const expressions
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:8:38
|
||||
|
|
||||
LL | const FREE2<const I: usize>: usize = I + 1;
|
||||
| ^ cannot perform const operation using `I`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `I`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:24:46
|
||||
|
|
||||
LL | const N1<T>: usize = std::mem::size_of::<T>();
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
||||
= note: type parameters may not be used in const expressions
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:27:39
|
||||
|
|
||||
LL | const N2<const I: usize>: usize = I + 1;
|
||||
| ^ cannot perform const operation using `I`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `I`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:30:27
|
||||
|
|
||||
LL | const N3: usize = 2 & X;
|
||||
| ^ cannot perform const operation using `X`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `X`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
//@ known-bug: #132980
|
||||
// Move this test to tests/ui/const-generics/mgca/type_const-only-in-trait.rs
|
||||
// once fixed.
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
|
||||
|
|
@ -14,6 +10,7 @@ struct BadS;
|
|||
|
||||
impl GoodTr for BadS {
|
||||
const NUM: usize = 42;
|
||||
//~^ ERROR implementation of `#[type_const]` const must be marked with `#[type_const]`
|
||||
}
|
||||
|
||||
fn accept_good_tr<const N: usize, T: GoodTr<NUM = { N }>>(_x: &T) {}
|
||||
16
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr
Normal file
16
tests/ui/const-generics/mgca/type_const-only-in-trait.stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
error: implementation of `#[type_const]` const must be marked with `#[type_const]`
|
||||
--> $DIR/type_const-only-in-trait.rs:12:5
|
||||
|
|
||||
LL | const NUM: usize = 42;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: trait declaration of const is marked with `#[type_const]`
|
||||
--> $DIR/type_const-only-in-trait.rs:5:5
|
||||
|
|
||||
LL | #[type_const]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | const NUM: usize;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
//@ known-bug: #119783
|
||||
// Regression test for #119783
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const F: fn();
|
||||
//~^ ERROR using function pointers as const generic parameters is forbidden
|
||||
}
|
||||
|
||||
fn take(_: impl Trait<F = { || {} }>) {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
error[E0741]: using function pointers as const generic parameters is forbidden
|
||||
--> $DIR/using-fnptr-as-type_const.rs:8:14
|
||||
|
|
||||
LL | const F: fn();
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0741`.
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// ICE: assertion failed: !value.has_infer()
|
||||
// issue: rust-lang/rust#115806
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![feature(associated_const_equality, min_generic_const_args, unsized_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub struct NoPin;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ trait Owner {
|
|||
const C<const N: u32>: u32;
|
||||
#[type_const]
|
||||
const K<const N: u32>: u32;
|
||||
#[type_const]
|
||||
const Q<T>: Maybe<T>;
|
||||
// #[type_const]
|
||||
// const Q<T>: Maybe<T>;
|
||||
}
|
||||
|
||||
impl Owner for () {
|
||||
|
|
@ -18,13 +18,15 @@ impl Owner for () {
|
|||
const C<const N: u32>: u32 = N;
|
||||
#[type_const]
|
||||
const K<const N: u32>: u32 = 99 + 1;
|
||||
#[type_const]
|
||||
const Q<T>: Maybe<T> = Maybe::Nothing;
|
||||
// FIXME(mgca): re-enable once we properly support ctors and generics on paths
|
||||
// #[type_const]
|
||||
// const Q<T>: Maybe<T> = Maybe::Nothing;
|
||||
}
|
||||
|
||||
fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
|
||||
fn take1(_: impl Owner<K<99> = 100>) {}
|
||||
fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
|
||||
// FIXME(mgca): re-enable once we properly support ctors and generics on paths
|
||||
// fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
|
||||
|
||||
fn main() {
|
||||
take0::<128>(());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue