Auto merge of #152324 - Keith-Cancel:mgca4, r=BoxyUwU
Update mgca to use `type const` syntax instead of the `#[type_const]` attribute. This PR changes the `#[type_const]` attribute to the `type const` syntax for https://github.com/rust-lang/rust/issues/132980. This will fixes https://github.com/rust-lang/rust/issues/151273 and similar issues, since we need to check `type const` of items before expansion. The move to add a syntax was mentioned here: https://github.com/rust-lang/rust/pull/151289#issuecomment-3765241397 The first part of this PR adds support by allowing `type const <IDENT>: <TYPE> { = <EXPR> };` syntax in `rustc_parse/src/parser/item.rs`. The next part since the AST item does not contain enough information to determine if we have a `type const` was rework `ConstItemRhs` into `ConstItemRhsKind` to store the information since we no longer have the attribute acting as a source of extra data/metadata. The hir node `ConstItemRhsKind` current shape mostly works, except in the case of `TraitItemKind` where it is an option. I initially went about giving `hir::ConstItemRhsKind` a similar form the AST, but it touches a lot more lines of code and files so because of that, the less invasive option was to add a simple boolean flag to `TraitItemKind`. The forth part of this PR includes adding a query I called `is_rhs_type_const` so that we can handle both local and foreign def_ids. The fifth aspect of the PR is adding a `mgca_type_const_syntax` feature gate that is checked before expansion. The standard mgca feature gate is ran after expansion. This feature gate allows for conditional compilation (e.g #[cfg(..)]) of the `type const` syntax in nightly without `min_generic_const_args` being enabled. The last bit is updating all the the tests that used the `#[type_const]` attribute to use the new syntax that failed because of the changes. This is the bulk of touched/edited files in the PR. r? @BoxyUwU @rustbot label +F-associated_const_equality +F-min_generic_const_args
This commit is contained in:
commit
381e9ef09e
204 changed files with 1014 additions and 906 deletions
|
|
@ -3869,27 +3869,44 @@ pub struct ConstItem {
|
|||
pub ident: Ident,
|
||||
pub generics: Generics,
|
||||
pub ty: Box<Ty>,
|
||||
pub rhs: Option<ConstItemRhs>,
|
||||
pub rhs_kind: ConstItemRhsKind,
|
||||
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
pub enum ConstItemRhs {
|
||||
TypeConst(AnonConst),
|
||||
Body(Box<Expr>),
|
||||
pub enum ConstItemRhsKind {
|
||||
Body { rhs: Option<Box<Expr>> },
|
||||
TypeConst { rhs: Option<AnonConst> },
|
||||
}
|
||||
|
||||
impl ConstItemRhs {
|
||||
pub fn span(&self) -> Span {
|
||||
self.expr().span
|
||||
impl ConstItemRhsKind {
|
||||
pub fn new_body(rhs: Box<Expr>) -> Self {
|
||||
Self::Body { rhs: Some(rhs) }
|
||||
}
|
||||
|
||||
pub fn expr(&self) -> &Expr {
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
Some(self.expr()?.span)
|
||||
}
|
||||
|
||||
pub fn expr(&self) -> Option<&Expr> {
|
||||
match self {
|
||||
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
|
||||
ConstItemRhs::Body(expr) => expr,
|
||||
Self::Body { rhs: Some(body) } => Some(&body),
|
||||
Self::TypeConst { rhs: Some(anon) } => Some(&anon.value),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_expr(&self) -> bool {
|
||||
match self {
|
||||
Self::Body { rhs: Some(_) } => true,
|
||||
Self::TypeConst { rhs: Some(_) } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_type_const(&self) -> bool {
|
||||
matches!(self, &Self::TypeConst { .. })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
Const,
|
||||
ConstBlockItem,
|
||||
ConstItem,
|
||||
ConstItemRhs,
|
||||
ConstItemRhsKind,
|
||||
Defaultness,
|
||||
Delegation,
|
||||
DelegationMac,
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
}) => {
|
||||
let ident = self.lower_ident(*ident);
|
||||
|
|
@ -301,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
||||
);
|
||||
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), span);
|
||||
let rhs = this.lower_const_item_rhs(rhs_kind, span);
|
||||
(ty, rhs)
|
||||
},
|
||||
);
|
||||
|
|
@ -941,7 +941,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (ident, generics, kind, has_default) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem {
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
..
|
||||
}) => {
|
||||
let (generics, kind) = self.lower_generics(
|
||||
generics,
|
||||
|
|
@ -952,15 +957,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ty,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
||||
);
|
||||
let rhs = rhs
|
||||
.as_ref()
|
||||
.map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span));
|
||||
hir::TraitItemKind::Const(ty, rhs)
|
||||
// Trait associated consts don't need an expression/body.
|
||||
let rhs = if rhs_kind.has_expr() {
|
||||
Some(this.lower_const_item_rhs(rhs_kind, i.span))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into())
|
||||
},
|
||||
);
|
||||
|
||||
if define_opaque.is_some() {
|
||||
if rhs.is_some() {
|
||||
if rhs_kind.has_expr() {
|
||||
self.lower_define_opaque(hir_id, &define_opaque);
|
||||
} else {
|
||||
self.dcx().span_err(
|
||||
|
|
@ -970,7 +978,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
(*ident, generics, kind, rhs.is_some())
|
||||
(*ident, generics, kind, rhs_kind.has_expr())
|
||||
}
|
||||
AssocItemKind::Fn(box Fn {
|
||||
sig, ident, generics, body: None, define_opaque, ..
|
||||
|
|
@ -1154,7 +1162,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let (ident, (generics, kind)) = match &i.kind {
|
||||
AssocItemKind::Const(box ConstItem {
|
||||
ident, generics, ty, rhs, define_opaque, ..
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
..
|
||||
}) => (
|
||||
*ident,
|
||||
self.lower_generics(
|
||||
|
|
@ -1167,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
||||
);
|
||||
this.lower_define_opaque(hir_id, &define_opaque);
|
||||
let rhs = this.lower_const_item_rhs(attrs, rhs.as_ref(), i.span);
|
||||
let rhs = this.lower_const_item_rhs(rhs_kind, i.span);
|
||||
hir::ImplItemKind::Const(ty, rhs)
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2374,15 +2374,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn lower_const_item_rhs(
|
||||
&mut self,
|
||||
attrs: &[hir::Attribute],
|
||||
rhs: Option<&ConstItemRhs>,
|
||||
rhs_kind: &ConstItemRhsKind,
|
||||
span: Span,
|
||||
) -> hir::ConstItemRhs<'hir> {
|
||||
match rhs {
|
||||
Some(ConstItemRhs::TypeConst(anon)) => {
|
||||
match rhs_kind {
|
||||
ConstItemRhsKind::Body { rhs: Some(body) } => {
|
||||
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
|
||||
}
|
||||
ConstItemRhsKind::Body { rhs: None } => {
|
||||
hir::ConstItemRhs::Body(self.lower_const_body(span, None))
|
||||
}
|
||||
ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
|
||||
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg_and_alloc(anon))
|
||||
}
|
||||
None if find_attr!(attrs, AttributeKind::TypeConst(_)) => {
|
||||
ConstItemRhsKind::TypeConst { rhs: None } => {
|
||||
let const_arg = ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Error(
|
||||
|
|
@ -2392,10 +2397,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
|
||||
}
|
||||
Some(ConstItemRhs::Body(body)) => {
|
||||
hir::ConstItemRhs::Body(self.lower_const_body(span, Some(body)))
|
||||
}
|
||||
None => hir::ConstItemRhs::Body(self.lower_const_body(span, None)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1361,9 +1361,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
}
|
||||
});
|
||||
}
|
||||
ItemKind::Const(box ConstItem { defaultness, ident, rhs, .. }) => {
|
||||
ItemKind::Const(box ConstItem { defaultness, ident, rhs_kind, .. }) => {
|
||||
self.check_defaultness(item.span, *defaultness);
|
||||
if rhs.is_none() {
|
||||
if !rhs_kind.has_expr() {
|
||||
self.dcx().emit_err(errors::ConstWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
|
|
@ -1715,11 +1715,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
|
||||
if let AssocCtxt::Impl { .. } = ctxt {
|
||||
match &item.kind {
|
||||
AssocItemKind::Const(box ConstItem { rhs: None, .. }) => {
|
||||
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
});
|
||||
AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => {
|
||||
if !rhs_kind.has_expr() {
|
||||
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
||||
span: item.span,
|
||||
replace_span: self.ending_semi_or_hi(item.span),
|
||||
});
|
||||
}
|
||||
}
|
||||
AssocItemKind::Fn(box Fn { body, .. }) => {
|
||||
if body.is_none() && !self.is_sdylib_interface {
|
||||
|
|
|
|||
|
|
@ -249,6 +249,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
||||
self.check_impl_trait(ty, false)
|
||||
}
|
||||
ast::ItemKind::Const(box ast::ConstItem {
|
||||
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
|
||||
..
|
||||
}) => {
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
// #![feature(min_generic_const_args)]
|
||||
gate!(&self, min_generic_const_args, i.span, "top-level `type const` are unstable");
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -422,6 +430,20 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
false
|
||||
}
|
||||
ast::AssocItemKind::Const(box ast::ConstItem {
|
||||
rhs_kind: ast::ConstItemRhsKind::TypeConst { .. },
|
||||
..
|
||||
}) => {
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
// #![feature(min_generic_const_args)]
|
||||
gate!(
|
||||
&self,
|
||||
min_generic_const_args,
|
||||
i.span,
|
||||
"associated `type const` are unstable"
|
||||
);
|
||||
false
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
|
||||
|
|
@ -528,6 +550,27 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// `mgca_type_const_syntax` is part of `min_generic_const_args` so either
|
||||
// or both are enabled we don't need to emit a feature error.
|
||||
if let Some(spans) = spans.get(&sym::mgca_type_const_syntax) {
|
||||
for span in spans {
|
||||
if visitor.features.min_generic_const_args()
|
||||
|| visitor.features.mgca_type_const_syntax()
|
||||
|| span.allows_unstable(sym::min_generic_const_args)
|
||||
|| span.allows_unstable(sym::mgca_type_const_syntax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
feature_err(
|
||||
&visitor.sess,
|
||||
sym::min_generic_const_args,
|
||||
*span,
|
||||
"`type const` syntax is experimental",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
}) => {
|
||||
self.print_item_const(
|
||||
|
|
@ -229,7 +229,7 @@ impl<'a> State<'a> {
|
|||
None,
|
||||
generics,
|
||||
ty,
|
||||
rhs.as_ref().map(|ct| ct.expr()),
|
||||
rhs_kind.expr(),
|
||||
&item.vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
|
|
@ -573,7 +573,7 @@ impl<'a> State<'a> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
}) => {
|
||||
self.print_item_const(
|
||||
|
|
@ -581,7 +581,7 @@ impl<'a> State<'a> {
|
|||
None,
|
||||
generics,
|
||||
ty,
|
||||
rhs.as_ref().map(|ct| ct.expr()),
|
||||
rhs_kind.expr(),
|
||||
vis,
|
||||
ast::Safety::Default,
|
||||
*defaultness,
|
||||
|
|
|
|||
|
|
@ -66,15 +66,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
|
||||
}
|
||||
|
||||
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::Const), Allow(Target::AssocConst)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
|
||||
}
|
||||
|
||||
// Markers
|
||||
|
||||
pub(crate) struct MarkerParser;
|
||||
|
|
|
|||
|
|
@ -299,7 +299,6 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<ThreadLocalParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
Single<WithoutArgs<TypeConstParser>>,
|
||||
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub(crate) fn expand(
|
|||
|
||||
// Generate anonymous constant serving as container for the allocator methods.
|
||||
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
|
||||
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ fn generate_default_impl(
|
|||
span,
|
||||
underscore,
|
||||
unit,
|
||||
ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts))),
|
||||
ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts))),
|
||||
)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub(crate) fn expand(
|
|||
|
||||
// Generate anonymous constant serving as container for the allocator methods.
|
||||
let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
|
||||
let const_body = ast::ConstItemRhs::Body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_body = ast::ConstItemRhsKind::new_body(ecx.expr_block(ecx.block(span, stmts)));
|
||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||
let const_item = if is_stmt {
|
||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
|
|||
cx.attr_nested_word(sym::allow, sym::deprecated, span),
|
||||
]);
|
||||
|
||||
let block = ast::ConstItemRhs::Body(cx.expr_block(
|
||||
let block = ast::ConstItemRhsKind::new_body(cx.expr_block(
|
||||
cx.block(span, thin_vec![cx.stmt_item(span, krate), cx.stmt_item(span, decls_static)]),
|
||||
));
|
||||
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
||||
define_opaque: None,
|
||||
// test::TestDescAndFn {
|
||||
rhs: Some(ast::ConstItemRhs::Body(
|
||||
rhs_kind: ast::ConstItemRhsKind::new_body(
|
||||
cx.expr_struct(
|
||||
sp,
|
||||
test_path("TestDescAndFn"),
|
||||
|
|
@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
|
|||
field("testfn", test_fn), // }
|
||||
],
|
||||
), // }
|
||||
)),
|
||||
),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -345,7 +345,7 @@ where
|
|||
let uneval = match constant.const_ {
|
||||
Const::Ty(_, ct) => match ct.kind() {
|
||||
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None,
|
||||
// Unevaluated consts in MIR bodies don't have associated MIR (e.g. `#[type_const]`).
|
||||
// Unevaluated consts in MIR bodies don't have associated MIR (e.g. `type const`).
|
||||
ty::ConstKind::Unevaluated(_) => None,
|
||||
// FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly
|
||||
// strict, and if instead we should be doing some kind of value-based analysis.
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|||
typing_env: ty::TypingEnv<'tcx>,
|
||||
) -> Result<R, ErrorHandled> {
|
||||
let def = cid.instance.def.def_id();
|
||||
// #[type_const] don't have bodys
|
||||
// `type const` don't have bodys
|
||||
debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
|
||||
|
||||
let is_static = tcx.is_static(def);
|
||||
|
|
|
|||
|
|
@ -727,7 +727,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
span: Span,
|
||||
ident: Ident,
|
||||
ty: Box<ast::Ty>,
|
||||
rhs: ast::ConstItemRhs,
|
||||
rhs_kind: ast::ConstItemRhsKind,
|
||||
) -> Box<ast::Item> {
|
||||
let defaultness = ast::Defaultness::Final;
|
||||
self.item(
|
||||
|
|
@ -740,7 +740,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
// FIXME(generic_const_items): Pass the generics as a parameter.
|
||||
generics: ast::Generics::default(),
|
||||
ty,
|
||||
rhs: Some(rhs),
|
||||
rhs_kind,
|
||||
define_opaque: None,
|
||||
}
|
||||
.into(),
|
||||
|
|
|
|||
|
|
@ -888,13 +888,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
|
||||
),
|
||||
|
||||
// Probably temporary component of min_generic_const_args.
|
||||
// `#[type_const] const ASSOC: usize;`
|
||||
gated!(
|
||||
type_const, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
|
||||
),
|
||||
|
||||
// The `#[loop_match]` and `#[const_continue]` attributes are part of the
|
||||
// lang experiment for RFC 3720 tracked in:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -561,6 +561,8 @@ declare_features! (
|
|||
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
||||
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
||||
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
||||
/// Enable mgca `type const` syntax before expansion.
|
||||
(incomplete, mgca_type_const_syntax, "CURRENT_RUSTC_VERSION", Some(132980)),
|
||||
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
|
||||
(incomplete, min_generic_const_args, "1.84.0", Some(132980)),
|
||||
/// A minimal, sound subset of specialization intended to be used by the
|
||||
|
|
|
|||
|
|
@ -1298,9 +1298,6 @@ pub enum AttributeKind {
|
|||
/// Represents `#[track_caller]`
|
||||
TrackCaller(Span),
|
||||
|
||||
/// Represents `#[type_const]`.
|
||||
TypeConst(Span),
|
||||
|
||||
/// Represents `#[type_length_limit]`
|
||||
TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ impl AttributeKind {
|
|||
TargetFeature { .. } => No,
|
||||
ThreadLocal => No,
|
||||
TrackCaller(..) => Yes,
|
||||
TypeConst(..) => Yes,
|
||||
TypeLengthLimit { .. } => No,
|
||||
UnstableFeatureBound(..) => No,
|
||||
Used { .. } => No,
|
||||
|
|
|
|||
|
|
@ -3199,7 +3199,7 @@ impl<'hir> TraitItem<'hir> {
|
|||
|
||||
expect_methods_self_kind! {
|
||||
expect_const, (&'hir Ty<'hir>, Option<ConstItemRhs<'hir>>),
|
||||
TraitItemKind::Const(ty, rhs), (ty, *rhs);
|
||||
TraitItemKind::Const(ty, rhs, _), (ty, *rhs);
|
||||
|
||||
expect_fn, (&FnSig<'hir>, &TraitFn<'hir>),
|
||||
TraitItemKind::Fn(ty, trfn), (ty, trfn);
|
||||
|
|
@ -3219,11 +3219,32 @@ pub enum TraitFn<'hir> {
|
|||
Provided(BodyId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable_Generic)]
|
||||
pub enum IsTypeConst {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl From<bool> for IsTypeConst {
|
||||
fn from(value: bool) -> Self {
|
||||
if value { Self::Yes } else { Self::No }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IsTypeConst> for bool {
|
||||
fn from(value: IsTypeConst) -> Self {
|
||||
matches!(value, IsTypeConst::Yes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a trait method or associated constant or type
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub enum TraitItemKind<'hir> {
|
||||
// FIXME(mgca) eventually want to move the option that is around `ConstItemRhs<'hir>`
|
||||
// into `ConstItemRhs`, much like `ast::ConstItemRhsKind`, but for now mark whether
|
||||
// this node is a TypeConst with a flag.
|
||||
/// An associated constant with an optional value (otherwise `impl`s must contain a value).
|
||||
Const(&'hir Ty<'hir>, Option<ConstItemRhs<'hir>>),
|
||||
Const(&'hir Ty<'hir>, Option<ConstItemRhs<'hir>>, IsTypeConst),
|
||||
/// An associated function with an optional body.
|
||||
Fn(FnSig<'hir>, TraitFn<'hir>),
|
||||
/// An associated type with (possibly empty) bounds and optional concrete
|
||||
|
|
@ -4686,7 +4707,7 @@ impl<'hir> OwnerNode<'hir> {
|
|||
| OwnerNode::TraitItem(TraitItem {
|
||||
kind:
|
||||
TraitItemKind::Fn(_, TraitFn::Provided(body))
|
||||
| TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))),
|
||||
| TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _),
|
||||
..
|
||||
})
|
||||
| OwnerNode::ImplItem(ImplItem {
|
||||
|
|
@ -4913,7 +4934,7 @@ impl<'hir> Node<'hir> {
|
|||
_ => None,
|
||||
},
|
||||
Node::TraitItem(it) => match it.kind {
|
||||
TraitItemKind::Const(ty, _) => Some(ty),
|
||||
TraitItemKind::Const(ty, _, _) => Some(ty),
|
||||
TraitItemKind::Type(_, ty) => ty,
|
||||
_ => None,
|
||||
},
|
||||
|
|
@ -4956,7 +4977,7 @@ impl<'hir> Node<'hir> {
|
|||
| Node::TraitItem(TraitItem {
|
||||
owner_id,
|
||||
kind:
|
||||
TraitItemKind::Const(.., Some(ConstItemRhs::Body(body)))
|
||||
TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _)
|
||||
| TraitItemKind::Fn(_, TraitFn::Provided(body)),
|
||||
..
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1271,7 +1271,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_defaultness(&defaultness));
|
||||
try_visit!(visitor.visit_id(hir_id));
|
||||
match *kind {
|
||||
TraitItemKind::Const(ref ty, default) => {
|
||||
TraitItemKind::Const(ref ty, default, _) => {
|
||||
try_visit!(visitor.visit_ty_unambig(ty));
|
||||
visit_opt!(visitor, visit_const_item_rhs, default);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
|
|||
);
|
||||
check_where_clauses(wfcx, def_id);
|
||||
|
||||
if tcx.is_type_const(def_id.into()) {
|
||||
if tcx.is_type_const(def_id) {
|
||||
wfcheck::check_type_const(wfcx, def_id, ty, true)?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -2060,14 +2060,14 @@ fn compare_type_const<'tcx>(
|
|||
.dcx()
|
||||
.struct_span_err(
|
||||
tcx.def_span(impl_const_item.def_id),
|
||||
"implementation of `#[type_const]` const must be marked with `#[type_const]`",
|
||||
"implementation of a `type const` must also be marked as `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]`",
|
||||
"trait declaration of const is marked as `type const`",
|
||||
)
|
||||
.emit());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ pub(crate) fn check_associated_item(
|
|||
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||
|
||||
let has_value = item.defaultness(tcx).has_value();
|
||||
if tcx.is_type_const(def_id.into()) {
|
||||
if tcx.is_type_const(def_id) {
|
||||
check_type_const(wfcx, def_id, ty, has_value)?;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
const_param_default,
|
||||
anon_const_kind,
|
||||
const_of_item,
|
||||
is_rhs_type_const,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
|
@ -1550,7 +1551,8 @@ fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId)
|
|||
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)), ..
|
||||
kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _),
|
||||
..
|
||||
})) = grandparent_node
|
||||
else {
|
||||
return false;
|
||||
|
|
@ -1595,7 +1597,7 @@ fn const_of_item<'tcx>(
|
|||
let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
|
||||
hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Const(.., ct), ..
|
||||
kind: hir::TraitItemKind::Const(_, ct, _), ..
|
||||
}) => ct.expect("no default value for trait assoc const"),
|
||||
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
|
||||
_ => {
|
||||
|
|
@ -1625,3 +1627,22 @@ fn const_of_item<'tcx>(
|
|||
ty::EarlyBinder::bind(ct)
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a Const or AssocConst is a type const (mgca)
|
||||
fn is_rhs_type_const<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> bool {
|
||||
match tcx.hir_node_by_def_id(def) {
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Const(_, _, _, hir::ConstItemRhs::TypeConst(_)),
|
||||
..
|
||||
})
|
||||
| hir::Node::ImplItem(hir::ImplItem {
|
||||
kind: hir::ImplItemKind::Const(_, hir::ConstItemRhs::TypeConst(_)),
|
||||
..
|
||||
})
|
||||
| hir::Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Const(_, _, hir::IsTypeConst::Yes),
|
||||
..
|
||||
}) => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -859,7 +859,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
}
|
||||
})
|
||||
}
|
||||
Const(_, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
|
||||
Const(_, _, _) => self.visit_early(trait_item.hir_id(), trait_item.generics, |this| {
|
||||
intravisit::walk_trait_item(this, trait_item)
|
||||
}),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
|||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
||||
}
|
||||
TraitItemKind::Const(ty, rhs) => rhs
|
||||
TraitItemKind::Const(ty, rhs, _) => rhs
|
||||
.and_then(|rhs| {
|
||||
ty.is_suggestable_infer_ty().then(|| {
|
||||
infer_placeholder_type(
|
||||
|
|
@ -420,9 +420,9 @@ fn infer_placeholder_type<'tcx>(
|
|||
kind: &'static str,
|
||||
) -> Ty<'tcx> {
|
||||
let tcx = cx.tcx();
|
||||
// If the type is omitted on a #[type_const] we can't run
|
||||
// If the type is omitted on a `type const` we can't run
|
||||
// type check on since that requires the const have a body
|
||||
// which type_consts don't.
|
||||
// which `type const`s don't.
|
||||
let ty = if tcx.is_type_const(def_id.to_def_id()) {
|
||||
if let Some(trait_item_def_id) = tcx.trait_item_of(def_id.to_def_id()) {
|
||||
tcx.type_of(trait_item_def_id).instantiate_identity()
|
||||
|
|
@ -430,7 +430,7 @@ fn infer_placeholder_type<'tcx>(
|
|||
Ty::new_error_with_message(
|
||||
tcx,
|
||||
ty_span,
|
||||
"constant with #[type_const] requires an explicit type",
|
||||
"constant with `type const` requires an explicit type",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -609,14 +609,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
if tcx.features().min_generic_const_args() {
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
constraint.span,
|
||||
"use of trait associated const without `#[type_const]`",
|
||||
"use of trait associated const not defined as `type const`",
|
||||
);
|
||||
err.note("the declaration in the trait must be marked with `#[type_const]`");
|
||||
err.note("the declaration in the trait must begin with `type const` not just `const` alone");
|
||||
return Err(err.emit());
|
||||
} else {
|
||||
let err = self.dcx().span_delayed_bug(
|
||||
constraint.span,
|
||||
"use of trait associated const without `#[type_const]`",
|
||||
"use of trait associated const defined as `type const`",
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2849,19 +2849,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
if tcx.is_type_const(def_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
let mut err = self
|
||||
.dcx()
|
||||
.struct_span_err(span, "use of `const` in the type system without `#[type_const]`");
|
||||
let mut err = self.dcx().struct_span_err(
|
||||
span,
|
||||
"use of `const` in the type system not defined as `type const`",
|
||||
);
|
||||
if def_id.is_local() {
|
||||
let name = tcx.def_path_str(def_id);
|
||||
err.span_suggestion(
|
||||
tcx.def_span(def_id).shrink_to_lo(),
|
||||
format!("add `#[type_const]` attribute to `{name}`"),
|
||||
format!("#[type_const]\n"),
|
||||
format!("add `type` before `const` for `{name}`"),
|
||||
format!("type "),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
} else {
|
||||
err.note("only consts marked with `#[type_const]` may be used in types");
|
||||
err.note("only consts marked defined as `type const` may be used in types");
|
||||
}
|
||||
Err(err.emit())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
|||
},
|
||||
hir::Node::TraitItem(item) => match item.kind {
|
||||
hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(),
|
||||
hir::TraitItemKind::Const(ty, _) => vec![ty],
|
||||
hir::TraitItemKind::Const(ty, _, _) => vec![ty],
|
||||
ref item => bug!("Unexpected TraitItem {:?}", item),
|
||||
},
|
||||
hir::Node::Item(item) => match item.kind {
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||
}
|
||||
DefKind::Const
|
||||
if !tcx.generics_of(item_def_id).own_requires_monomorphization()
|
||||
&& !tcx.is_type_const(item_def_id.into()) =>
|
||||
&& !tcx.is_type_const(item_def_id) =>
|
||||
{
|
||||
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
|
||||
// seems to be fine for now. Revisit this!
|
||||
|
|
|
|||
|
|
@ -937,7 +937,7 @@ impl<'a> State<'a> {
|
|||
self.maybe_print_comment(ti.span.lo());
|
||||
self.print_attrs(self.attrs(ti.hir_id()));
|
||||
match ti.kind {
|
||||
hir::TraitItemKind::Const(ty, default) => {
|
||||
hir::TraitItemKind::Const(ty, default, _) => {
|
||||
self.print_associated_const(ti.ident, ti.generics, ty, default);
|
||||
}
|
||||
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => {
|
||||
|
|
|
|||
|
|
@ -1058,8 +1058,8 @@ trait UnusedDelimLint {
|
|||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
use ast::ItemKind::*;
|
||||
|
||||
let expr = if let Const(box ast::ConstItem { rhs: Some(rhs), .. }) = &item.kind {
|
||||
rhs.expr()
|
||||
let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind {
|
||||
if let Some(e) = rhs_kind.expr() { e } else { return }
|
||||
} else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind {
|
||||
expr
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -418,6 +418,7 @@ provide! { tcx, def_id, other, cdata,
|
|||
}
|
||||
anon_const_kind => { table }
|
||||
const_of_item => { table }
|
||||
is_rhs_type_const => { table }
|
||||
}
|
||||
|
||||
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
||||
|
|
|
|||
|
|
@ -1630,6 +1630,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
let table = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
|
||||
record!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table);
|
||||
}
|
||||
if let DefKind::AssocConst | DefKind::Const = def_kind {
|
||||
record!(self.tables.is_rhs_type_const[def_id] <- self.tcx.is_rhs_type_const(def_id));
|
||||
}
|
||||
}
|
||||
|
||||
for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
|
||||
|
|
|
|||
|
|
@ -476,6 +476,7 @@ define_tables! {
|
|||
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
|
||||
const_of_item: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
|
||||
associated_types_for_impl_traits_in_trait_or_impl: Table<DefIndex, LazyValue<DefIdMap<Vec<DefId>>>>,
|
||||
is_rhs_type_const: Table<DefIndex, LazyValue<bool>>,
|
||||
}
|
||||
|
||||
#[derive(TyEncodable, TyDecodable)]
|
||||
|
|
|
|||
|
|
@ -293,13 +293,13 @@ rustc_queries! {
|
|||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// Returns the const of the RHS of a (free or assoc) const item, if it is a `#[type_const]`.
|
||||
/// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`.
|
||||
///
|
||||
/// When a const item is used in a type-level expression, like in equality for an assoc const
|
||||
/// projection, this allows us to retrieve the typesystem-appropriate representation of the
|
||||
/// const value.
|
||||
///
|
||||
/// This query will ICE if given a const that is not marked with `#[type_const]`.
|
||||
/// This query will ICE if given a const that is not marked with `type const`.
|
||||
query const_of_item(def_id: DefId) -> ty::EarlyBinder<'tcx, ty::Const<'tcx>> {
|
||||
desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
|
|
@ -2764,6 +2764,12 @@ rustc_queries! {
|
|||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
query is_rhs_type_const(def_id: DefId) -> bool {
|
||||
desc { |tcx| "checking whether `{}` is a rhs type const", tcx.def_path_str(def_id) }
|
||||
cache_on_disk_if { def_id.is_local() }
|
||||
separate_provide_extern
|
||||
}
|
||||
}
|
||||
|
||||
rustc_with_all_queries! { define_callbacks! }
|
||||
|
|
|
|||
|
|
@ -845,7 +845,7 @@ impl DynCompatibilityViolation {
|
|||
format!("it contains generic associated const `{name}`").into()
|
||||
}
|
||||
Self::AssocConst(name, AssocConstViolation::NonType, _) => {
|
||||
format!("it contains associated const `{name}` that's not marked `#[type_const]`")
|
||||
format!("it contains associated const `{name}` that's not defined as `type const`")
|
||||
.into()
|
||||
}
|
||||
Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!(
|
||||
|
|
@ -999,7 +999,7 @@ pub enum AssocConstViolation {
|
|||
/// Has own generic parameters (GAC).
|
||||
Generic,
|
||||
|
||||
/// Isn't marked `#[type_const]`.
|
||||
/// Isn't defined as `type const`.
|
||||
NonType,
|
||||
|
||||
/// Its type mentions the `Self` type parameter.
|
||||
|
|
|
|||
|
|
@ -1890,14 +1890,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
pub fn type_const_span(self, def_id: DefId) -> Option<Span> {
|
||||
matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst)
|
||||
.then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp))
|
||||
.flatten()
|
||||
if !self.is_type_const(def_id) {
|
||||
return None;
|
||||
}
|
||||
Some(self.def_span(def_id))
|
||||
}
|
||||
|
||||
/// Check if the given `def_id` is a const with the `#[type_const]` attribute.
|
||||
pub fn is_type_const(self, def_id: DefId) -> bool {
|
||||
self.type_const_span(def_id).is_some()
|
||||
/// Check if the given `def_id` is a `type const` (mgca)
|
||||
pub fn is_type_const<I: Copy + IntoQueryParam<DefId>>(self, def_id: I) -> bool {
|
||||
// No need to call the query directly in this case always false.
|
||||
if !(matches!(
|
||||
self.def_kind(def_id.into_query_param()),
|
||||
DefKind::Const | DefKind::AssocConst
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
self.is_rhs_type_const(def_id)
|
||||
}
|
||||
|
||||
/// Returns the movability of the coroutine of `def_id`, or panics
|
||||
|
|
@ -2923,7 +2931,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
) -> bool {
|
||||
let generics = self.generics_of(def_id);
|
||||
|
||||
// IATs and IACs (inherent associated types/consts with #[type_const]) themselves have a
|
||||
// IATs and IACs (inherent associated types/consts with `type const`) themselves have a
|
||||
// weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e.
|
||||
// ATPITs) do not.
|
||||
let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy)
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@ fn construct_const<'a, 'tcx>(
|
|||
})
|
||||
| Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. })
|
||||
| Node::TraitItem(hir::TraitItem {
|
||||
kind: hir::TraitItemKind::Const(ty, Some(_)),
|
||||
kind: hir::TraitItemKind::Const(ty, Some(_), _),
|
||||
span,
|
||||
..
|
||||
}) => (*span, ty.span),
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ use rustc_ast::ast::*;
|
|||
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
|
||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::{
|
||||
attr, {self as ast},
|
||||
};
|
||||
use rustc_ast::{self as ast};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err};
|
||||
|
|
@ -286,13 +284,13 @@ impl<'a> Parser<'a> {
|
|||
// CONST ITEM
|
||||
self.recover_const_mut(const_span);
|
||||
self.recover_missing_kw_before_item()?;
|
||||
let (ident, generics, ty, rhs) = self.parse_const_item(attrs)?;
|
||||
let (ident, generics, ty, rhs_kind) = self.parse_const_item(false)?;
|
||||
ItemKind::Const(Box::new(ConstItem {
|
||||
defaultness: def_(),
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque: None,
|
||||
}))
|
||||
} else if let Some(kind) = self.is_reuse_item() {
|
||||
|
|
@ -303,8 +301,26 @@ impl<'a> Parser<'a> {
|
|||
// MODULE ITEM
|
||||
self.parse_item_mod(attrs)?
|
||||
} else if self.eat_keyword_case(exp!(Type), case) {
|
||||
// TYPE ITEM
|
||||
self.parse_type_alias(def_())?
|
||||
if let Const::Yes(const_span) = self.parse_constness(case) {
|
||||
// TYPE CONST (mgca)
|
||||
self.recover_const_mut(const_span);
|
||||
self.recover_missing_kw_before_item()?;
|
||||
let (ident, generics, ty, rhs_kind) = self.parse_const_item(true)?;
|
||||
// Make sure this is only allowed if the feature gate is enabled.
|
||||
// #![feature(mgca_type_const_syntax)]
|
||||
self.psess.gated_spans.gate(sym::mgca_type_const_syntax, lo.to(const_span));
|
||||
ItemKind::Const(Box::new(ConstItem {
|
||||
defaultness: def_(),
|
||||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs_kind,
|
||||
define_opaque: None,
|
||||
}))
|
||||
} else {
|
||||
// TYPE ITEM
|
||||
self.parse_type_alias(def_())?
|
||||
}
|
||||
} else if self.eat_keyword_case(exp!(Enum), case) {
|
||||
// ENUM ITEM
|
||||
self.parse_item_enum()?
|
||||
|
|
@ -1113,13 +1129,12 @@ impl<'a> Parser<'a> {
|
|||
define_opaque,
|
||||
}) => {
|
||||
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
||||
let rhs = expr.map(ConstItemRhs::Body);
|
||||
AssocItemKind::Const(Box::new(ConstItem {
|
||||
defaultness: Defaultness::Final,
|
||||
ident,
|
||||
generics: Generics::default(),
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind: ConstItemRhsKind::Body { rhs: expr },
|
||||
define_opaque,
|
||||
}))
|
||||
}
|
||||
|
|
@ -1360,7 +1375,7 @@ impl<'a> Parser<'a> {
|
|||
let kind = match ForeignItemKind::try_from(kind) {
|
||||
Ok(kind) => kind,
|
||||
Err(kind) => match kind {
|
||||
ItemKind::Const(box ConstItem { ident, ty, rhs, .. }) => {
|
||||
ItemKind::Const(box ConstItem { ident, ty, rhs_kind, .. }) => {
|
||||
let const_span = Some(span.with_hi(ident.span.lo()))
|
||||
.filter(|span| span.can_be_used_for_suggestions());
|
||||
self.dcx().emit_err(errors::ExternItemCannotBeConst {
|
||||
|
|
@ -1371,10 +1386,13 @@ impl<'a> Parser<'a> {
|
|||
ident,
|
||||
ty,
|
||||
mutability: Mutability::Not,
|
||||
expr: rhs.map(|b| match b {
|
||||
ConstItemRhs::TypeConst(anon_const) => anon_const.value,
|
||||
ConstItemRhs::Body(expr) => expr,
|
||||
}),
|
||||
expr: match rhs_kind {
|
||||
ConstItemRhsKind::Body { rhs } => rhs,
|
||||
ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
|
||||
Some(anon.value)
|
||||
}
|
||||
ConstItemRhsKind::TypeConst { rhs: None } => None,
|
||||
},
|
||||
safety: Safety::Default,
|
||||
define_opaque: None,
|
||||
}))
|
||||
|
|
@ -1516,13 +1534,16 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parse a constant item with the prefix `"const"` already parsed.
|
||||
///
|
||||
/// If `const_arg` is true, any expression assigned to the const will be parsed
|
||||
/// as a const_arg instead of a body expression.
|
||||
///
|
||||
/// ```ebnf
|
||||
/// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;
|
||||
/// ```
|
||||
fn parse_const_item(
|
||||
&mut self,
|
||||
attrs: &[Attribute],
|
||||
) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<ast::ConstItemRhs>)> {
|
||||
const_arg: bool,
|
||||
) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
|
||||
let ident = self.parse_ident_or_underscore()?;
|
||||
|
||||
let mut generics = self.parse_generics()?;
|
||||
|
|
@ -1549,16 +1570,15 @@ impl<'a> Parser<'a> {
|
|||
let before_where_clause =
|
||||
if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
|
||||
|
||||
let rhs = if self.eat(exp!(Eq)) {
|
||||
if attr::contains_name(attrs, sym::type_const) {
|
||||
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()?))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
let rhs = match (self.eat(exp!(Eq)), const_arg) {
|
||||
(true, true) => ConstItemRhsKind::TypeConst {
|
||||
rhs: Some(
|
||||
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?,
|
||||
),
|
||||
},
|
||||
(true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },
|
||||
(false, true) => ConstItemRhsKind::TypeConst { rhs: None },
|
||||
(false, false) => ConstItemRhsKind::Body { rhs: None },
|
||||
};
|
||||
|
||||
let after_where_clause = self.parse_where_clause()?;
|
||||
|
|
@ -1567,18 +1587,18 @@ impl<'a> Parser<'a> {
|
|||
// Users may be tempted to write such code if they are still used to the deprecated
|
||||
// where-clause location on type aliases and associated types. See also #89122.
|
||||
if before_where_clause.has_where_token
|
||||
&& let Some(rhs) = &rhs
|
||||
&& let Some(rhs_span) = rhs.span()
|
||||
{
|
||||
self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
|
||||
span: before_where_clause.span,
|
||||
name: ident.span,
|
||||
body: rhs.span(),
|
||||
body: rhs_span,
|
||||
sugg: if !after_where_clause.has_where_token {
|
||||
self.psess.source_map().span_to_snippet(rhs.span()).ok().map(|body_s| {
|
||||
self.psess.source_map().span_to_snippet(rhs_span).ok().map(|body_s| {
|
||||
errors::WhereClauseBeforeConstBodySugg {
|
||||
left: before_where_clause.span.shrink_to_lo(),
|
||||
snippet: body_s,
|
||||
right: before_where_clause.span.shrink_to_hi().to(rhs.span()),
|
||||
right: before_where_clause.span.shrink_to_hi().to(rhs_span),
|
||||
}
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -358,7 +358,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcVarianceOfOpaques
|
||||
| AttributeKind::ShouldPanic { .. }
|
||||
| AttributeKind::ThreadLocal
|
||||
| AttributeKind::TypeConst{..}
|
||||
| AttributeKind::TypeLengthLimit { .. }
|
||||
| AttributeKind::UnstableFeatureBound(..)
|
||||
| AttributeKind::Used { .. }
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
_ => false,
|
||||
},
|
||||
Node::TraitItem(trait_method) => match trait_method.kind {
|
||||
hir::TraitItemKind::Const(_, ref default) => default.is_some(),
|
||||
hir::TraitItemKind::Const(_, ref default, _) => default.is_some(),
|
||||
hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true,
|
||||
hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
|
||||
| hir::TraitItemKind::Type(..) => false,
|
||||
|
|
@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
self.visit_nested_body(body);
|
||||
}
|
||||
}
|
||||
// For #[type_const] we want to evaluate the RHS.
|
||||
// For `type const` we want to evaluate the RHS.
|
||||
hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => {
|
||||
self.visit_const_item_rhs(init);
|
||||
}
|
||||
|
|
@ -258,11 +258,11 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
}
|
||||
Node::TraitItem(trait_method) => {
|
||||
match trait_method.kind {
|
||||
hir::TraitItemKind::Const(_, None)
|
||||
hir::TraitItemKind::Const(_, None, _)
|
||||
| hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
|
||||
// Keep going, nothing to get exported
|
||||
}
|
||||
hir::TraitItemKind::Const(_, Some(rhs)) => self.visit_const_item_rhs(rhs),
|
||||
hir::TraitItemKind::Const(_, Some(rhs), _) => self.visit_const_item_rhs(rhs),
|
||||
hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
|
||||
self.visit_nested_body(body_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2847,11 +2847,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
defaultness: _,
|
||||
}) => {
|
||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::Item(
|
||||
|
|
@ -2871,7 +2870,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
this.with_lifetime_rib(
|
||||
LifetimeRibKind::Elided(LifetimeRes::Static),
|
||||
|this| {
|
||||
if is_type_const
|
||||
if rhs_kind.is_type_const()
|
||||
&& !this.r.tcx.features().generic_const_parameter_types()
|
||||
{
|
||||
this.with_rib(TypeNS, RibKind::ConstParamTy, |this| {
|
||||
|
|
@ -2888,12 +2887,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
},
|
||||
);
|
||||
|
||||
if let Some(rhs) = rhs {
|
||||
this.resolve_const_item_rhs(
|
||||
rhs,
|
||||
Some((*ident, ConstantItemKind::Const)),
|
||||
);
|
||||
}
|
||||
this.resolve_const_item_rhs(
|
||||
rhs_kind,
|
||||
Some((*ident, ConstantItemKind::Const)),
|
||||
);
|
||||
},
|
||||
);
|
||||
self.resolve_define_opaques(define_opaque);
|
||||
|
|
@ -3242,11 +3239,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
AssocItemKind::Const(box ast::ConstItem {
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
..
|
||||
}) => {
|
||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::AssocItem,
|
||||
|
|
@ -3261,7 +3257,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
},
|
||||
|this| {
|
||||
this.visit_generics(generics);
|
||||
if is_type_const
|
||||
if rhs_kind.is_type_const()
|
||||
&& !this.r.tcx.features().generic_const_parameter_types()
|
||||
{
|
||||
this.with_rib(TypeNS, RibKind::ConstParamTy, |this| {
|
||||
|
|
@ -3278,14 +3274,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
|
||||
// Only impose the restrictions of `ConstRibKind` for an
|
||||
// actual constant expression in a provided default.
|
||||
if let Some(rhs) = rhs {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_item_rhs(rhs, None);
|
||||
}
|
||||
//
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_item_rhs(rhs_kind, None);
|
||||
},
|
||||
)
|
||||
},
|
||||
|
|
@ -3463,12 +3458,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
ident,
|
||||
generics,
|
||||
ty,
|
||||
rhs,
|
||||
rhs_kind,
|
||||
define_opaque,
|
||||
..
|
||||
}) => {
|
||||
debug!("resolve_implementation AssocItemKind::Const");
|
||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
||||
self.with_generic_param_rib(
|
||||
&generics.params,
|
||||
RibKind::AssocItem,
|
||||
|
|
@ -3505,7 +3499,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
);
|
||||
|
||||
this.visit_generics(generics);
|
||||
if is_type_const
|
||||
if rhs_kind.is_type_const()
|
||||
&& !this
|
||||
.r
|
||||
.tcx
|
||||
|
|
@ -3527,14 +3521,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
} else {
|
||||
this.visit_ty(ty);
|
||||
}
|
||||
if let Some(rhs) = rhs {
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_item_rhs(rhs, None);
|
||||
}
|
||||
// We allow arbitrary const expressions inside of associated consts,
|
||||
// even if they are potentially not const evaluatable.
|
||||
//
|
||||
// Type parameters can already be used and as associated consts are
|
||||
// not used as part of the type system, this is far less surprising.
|
||||
this.resolve_const_item_rhs(rhs_kind, None);
|
||||
},
|
||||
)
|
||||
},
|
||||
|
|
@ -3756,18 +3748,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
|
||||
fn resolve_const_item_rhs(
|
||||
&mut self,
|
||||
rhs: &'ast ConstItemRhs,
|
||||
rhs_kind: &'ast ConstItemRhsKind,
|
||||
item: Option<(Ident, ConstantItemKind)>,
|
||||
) {
|
||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs {
|
||||
ConstItemRhs::TypeConst(anon_const) => {
|
||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs_kind {
|
||||
ConstItemRhsKind::TypeConst { rhs: Some(anon_const) } => {
|
||||
this.resolve_anon_const(anon_const, AnonConstKind::ConstArg(IsRepeatExpr::No));
|
||||
}
|
||||
ConstItemRhs::Body(expr) => {
|
||||
ConstItemRhsKind::Body { rhs: Some(expr) } => {
|
||||
this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
|
||||
this.visit_expr(expr)
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1453,6 +1453,7 @@ symbols! {
|
|||
meta,
|
||||
meta_sized,
|
||||
metadata_type,
|
||||
mgca_type_const_syntax,
|
||||
min_const_fn,
|
||||
min_const_generics,
|
||||
min_const_unsafe_fn,
|
||||
|
|
@ -2339,7 +2340,6 @@ symbols! {
|
|||
type_ascribe,
|
||||
type_ascription,
|
||||
type_changing_struct_update,
|
||||
type_const,
|
||||
type_id,
|
||||
type_id_eq,
|
||||
type_info,
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
|||
// been emitted earlier in compilation.
|
||||
//
|
||||
// That's because we can only end up with an Unevaluated ty::Const for a const item
|
||||
// if it was marked with `#[type_const]`. Using this attribute without the mgca
|
||||
// if it was marked with `type const`. Using this attribute without the mgca
|
||||
// feature gate causes a parse error.
|
||||
let ct = match tcx.def_kind(uv.def) {
|
||||
DefKind::AssocConst => match tcx.def_kind(tcx.parent(uv.def)) {
|
||||
|
|
|
|||
|
|
@ -1209,14 +1209,14 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
|
|||
let local_did = trait_item.owner_id.to_def_id();
|
||||
cx.with_param_env(local_did, |cx| {
|
||||
let inner = match trait_item.kind {
|
||||
hir::TraitItemKind::Const(ty, Some(default)) => {
|
||||
hir::TraitItemKind::Const(ty, Some(default), _) => {
|
||||
ProvidedAssocConstItem(Box::new(Constant {
|
||||
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
|
||||
kind: clean_const_item_rhs(default, local_did),
|
||||
type_: clean_ty(ty, cx),
|
||||
}))
|
||||
}
|
||||
hir::TraitItemKind::Const(ty, None) => {
|
||||
hir::TraitItemKind::Const(ty, None, _) => {
|
||||
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
|
||||
RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> {
|
|||
}
|
||||
|
||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
|
||||
if let TraitItemKind::Const(_, ct_rhs_opt) = item.kind
|
||||
if let TraitItemKind::Const(_, ct_rhs_opt, _) = item.kind
|
||||
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||
&& match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) {
|
||||
IsFreeze::No => true,
|
||||
|
|
@ -931,7 +931,7 @@ fn get_const_hir_value<'tcx>(
|
|||
{
|
||||
match tcx.hir_node(tcx.local_def_id_to_hir_id(did)) {
|
||||
Node::ImplItem(item) if let ImplItemKind::Const(.., ct_rhs) = item.kind => (did, ct_rhs),
|
||||
Node::TraitItem(item) if let TraitItemKind::Const(.., Some(ct_rhs)) = item.kind => (did, ct_rhs),
|
||||
Node::TraitItem(item) if let TraitItemKind::Const(_, Some(ct_rhs), _) = item.kind => (did, ct_rhs),
|
||||
_ => return None,
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
|||
};
|
||||
|
||||
match item.kind {
|
||||
TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
|
||||
TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => {
|
||||
self.check_ty(cx, ty, context);
|
||||
},
|
||||
TraitItemKind::Fn(ref sig, trait_method) => {
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
ident: li,
|
||||
generics: lg,
|
||||
ty: lt,
|
||||
rhs: lb,
|
||||
rhs_kind: lb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
Const(box ConstItem {
|
||||
|
|
@ -363,7 +363,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
ident: ri,
|
||||
generics: rg,
|
||||
ty: rt,
|
||||
rhs: rb,
|
||||
rhs_kind: rb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => {
|
||||
|
|
@ -371,7 +371,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
|||
&& eq_id(*li, *ri)
|
||||
&& eq_generics(lg, rg)
|
||||
&& eq_ty(lt, rt)
|
||||
&& both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs)
|
||||
&& both(Some(lb), Some(rb), eq_const_item_rhs)
|
||||
},
|
||||
(
|
||||
Fn(box ast::Fn {
|
||||
|
|
@ -615,7 +615,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
ident: li,
|
||||
generics: lg,
|
||||
ty: lt,
|
||||
rhs: lb,
|
||||
rhs_kind: lb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
Const(box ConstItem {
|
||||
|
|
@ -623,7 +623,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
ident: ri,
|
||||
generics: rg,
|
||||
ty: rt,
|
||||
rhs: rb,
|
||||
rhs_kind: rb,
|
||||
define_opaque: _,
|
||||
}),
|
||||
) => {
|
||||
|
|
@ -631,7 +631,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
|||
&& eq_id(*li, *ri)
|
||||
&& eq_generics(lg, rg)
|
||||
&& eq_ty(lt, rt)
|
||||
&& both(lb.as_ref(), rb.as_ref(), eq_const_item_rhs)
|
||||
&& both(Some(lb), Some(rb), eq_const_item_rhs)
|
||||
},
|
||||
(
|
||||
Fn(box ast::Fn {
|
||||
|
|
@ -791,12 +791,18 @@ pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
|
|||
eq_expr(&l.value, &r.value)
|
||||
}
|
||||
|
||||
pub fn eq_const_item_rhs(l: &ConstItemRhs, r: &ConstItemRhs) -> bool {
|
||||
use ConstItemRhs::*;
|
||||
pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool {
|
||||
use ConstItemRhsKind::*;
|
||||
match (l, r) {
|
||||
(TypeConst(l), TypeConst(r)) => eq_anon_const(l, r),
|
||||
(Body(l), Body(r)) => eq_expr(l, r),
|
||||
(TypeConst(..), Body(..)) | (Body(..), TypeConst(..)) => false,
|
||||
(TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r),
|
||||
(TypeConst { rhs: None }, TypeConst { rhs: None }) => true,
|
||||
(TypeConst { rhs: Some(..) }, TypeConst { rhs: None }) => false,
|
||||
(TypeConst { rhs: None }, TypeConst { rhs: Some(..) }) => false,
|
||||
(Body { rhs: Some(l) }, Body { rhs: Some(r) }) => eq_expr(l, r),
|
||||
(Body { rhs: None }, Body { rhs: None }) => true,
|
||||
(Body { rhs: None }, Body { rhs: Some(..) }) => false,
|
||||
(Body { rhs: Some(..) }, Body { rhs: None }) => false,
|
||||
(TypeConst {..}, Body { .. }) | ( Body { .. }, TypeConst { .. }) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#![feature(min_generic_const_args)]
|
||||
|
||||
trait AssocConstTrait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
|
||||
type const ASSOC: usize;
|
||||
}
|
||||
fn assoc_const_args<T>()
|
||||
where
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#![feature(min_generic_const_args)]
|
||||
|
||||
trait AssocConstTrait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
|
||||
type const ASSOC: usize;
|
||||
}
|
||||
fn assoc_const_args<T>()
|
||||
where
|
||||
|
|
|
|||
|
|
@ -2028,12 +2028,16 @@ impl<'a> StaticParts<'a> {
|
|||
),
|
||||
ast::ItemKind::Const(c) => (
|
||||
Some(c.defaultness),
|
||||
"const",
|
||||
if c.rhs_kind.is_type_const() {
|
||||
"type const"
|
||||
} else {
|
||||
"const"
|
||||
},
|
||||
ast::Safety::Default,
|
||||
c.ident,
|
||||
&c.ty,
|
||||
ast::Mutability::Not,
|
||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
||||
c.rhs_kind.expr(),
|
||||
Some(&c.generics),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -2053,17 +2057,25 @@ impl<'a> StaticParts<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
|
||||
let (defaultness, ty, expr_opt, generics) = match &ti.kind {
|
||||
ast::AssocItemKind::Const(c) => (
|
||||
c.defaultness,
|
||||
&c.ty,
|
||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
||||
Some(&c.generics),
|
||||
),
|
||||
let (defaultness, ty, expr_opt, generics, prefix) = match &ti.kind {
|
||||
ast::AssocItemKind::Const(c) => {
|
||||
let prefix = if c.rhs_kind.is_type_const() {
|
||||
"type const"
|
||||
} else {
|
||||
"const"
|
||||
};
|
||||
(
|
||||
c.defaultness,
|
||||
&c.ty,
|
||||
c.rhs_kind.expr(),
|
||||
Some(&c.generics),
|
||||
prefix,
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
StaticParts {
|
||||
prefix: "const",
|
||||
prefix,
|
||||
safety: ast::Safety::Default,
|
||||
vis: &ti.vis,
|
||||
ident,
|
||||
|
|
@ -2077,17 +2089,25 @@ impl<'a> StaticParts<'a> {
|
|||
}
|
||||
|
||||
pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
|
||||
let (defaultness, ty, expr_opt, generics) = match &ii.kind {
|
||||
ast::AssocItemKind::Const(c) => (
|
||||
c.defaultness,
|
||||
&c.ty,
|
||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
||||
Some(&c.generics),
|
||||
),
|
||||
let (defaultness, ty, expr_opt, generics, prefix) = match &ii.kind {
|
||||
ast::AssocItemKind::Const(c) => {
|
||||
let prefix = if c.rhs_kind.is_type_const() {
|
||||
"type const"
|
||||
} else {
|
||||
"const"
|
||||
};
|
||||
(
|
||||
c.defaultness,
|
||||
&c.ty,
|
||||
c.rhs_kind.expr(),
|
||||
Some(&c.generics),
|
||||
prefix,
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
StaticParts {
|
||||
prefix: "const",
|
||||
prefix,
|
||||
safety: ast::Safety::Default,
|
||||
vis: &ii.vis,
|
||||
ident,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ struct Qux<'a> {
|
|||
x: &'a (),
|
||||
}
|
||||
impl<'a> Qux<'a> {
|
||||
#[type_const]
|
||||
const LEN: usize = 4;
|
||||
type const LEN: usize = 4;
|
||||
fn foo(_: [u8; Qux::LEN]) {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,10 @@
|
|||
#![expect(unused_variables, incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: usize = 101;
|
||||
type const N: usize = 101;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ pub enum ParseMode {
|
|||
Raw,
|
||||
}
|
||||
pub trait Parse {
|
||||
#[type_const]
|
||||
const PARSE_MODE: ParseMode;
|
||||
type const PARSE_MODE: ParseMode;
|
||||
}
|
||||
pub trait RenderRaw {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,5 @@
|
|||
pub fn accept(_: impl Trait<K = 0>) {}
|
||||
|
||||
pub trait Trait {
|
||||
#[type_const]
|
||||
const K: i32;
|
||||
type const K: i32;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ trait T {
|
|||
}
|
||||
|
||||
trait S {
|
||||
#[type_const]
|
||||
const C: i32;
|
||||
type const C: i32;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
type const ASSOC: usize;
|
||||
}
|
||||
|
||||
pub fn foo<
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
struct OnDiskDirEntry<'a>(&'a ());
|
||||
|
||||
impl<'a> OnDiskDirEntry<'a> {
|
||||
#[type_const]
|
||||
const LFN_FRAGMENT_LEN: i64 = 2;
|
||||
type const LFN_FRAGMENT_LEN: i64 = 2;
|
||||
|
||||
fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
|
||||
//~^ ERROR the constant `2` is not of type `usize`
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ LL | #![feature(inherent_associated_types)]
|
|||
= note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
|
||||
|
||||
error: the constant `2` is not of type `usize`
|
||||
--> $DIR/type-const-in-array-len-wrong-type.rs:14:26
|
||||
--> $DIR/type-const-in-array-len-wrong-type.rs:13:26
|
||||
|
|
||||
LL | fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64`
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
// Test case from #138226: generic impl with multiple type parameters
|
||||
struct Foo<A, B>(A, B);
|
||||
impl<A, B> Foo<A, B> {
|
||||
#[type_const]
|
||||
const LEN: usize = 4;
|
||||
type const LEN: usize = 4;
|
||||
|
||||
fn foo() {
|
||||
let _ = [5; Self::LEN];
|
||||
|
|
@ -19,8 +18,7 @@ impl<A, B> Foo<A, B> {
|
|||
// Test case from #138226: generic impl with const parameter
|
||||
struct Bar<const N: usize>;
|
||||
impl<const N: usize> Bar<N> {
|
||||
#[type_const]
|
||||
const LEN: usize = 4;
|
||||
type const LEN: usize = 4;
|
||||
|
||||
fn bar() {
|
||||
let _ = [0; Self::LEN];
|
||||
|
|
@ -30,8 +28,7 @@ impl<const N: usize> Bar<N> {
|
|||
// Test case from #150960: non-generic impl with const block
|
||||
struct Baz;
|
||||
impl Baz {
|
||||
#[type_const]
|
||||
const LEN: usize = 4;
|
||||
type const LEN: usize = 4;
|
||||
|
||||
fn baz() {
|
||||
let _ = [0; { Self::LEN }];
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@ fn mismatch_2() -> impl Iterator<Item: Copy, Item: Send> {
|
|||
trait Trait {
|
||||
type Gat<T>;
|
||||
|
||||
#[type_const]
|
||||
const ASSOC: i32;
|
||||
type const ASSOC: i32;
|
||||
|
||||
fn foo() -> impl Sized;
|
||||
}
|
||||
|
|
@ -59,8 +58,7 @@ trait Trait {
|
|||
impl Trait for () {
|
||||
type Gat<T> = ();
|
||||
|
||||
#[type_const]
|
||||
const ASSOC: i32 = 3;
|
||||
type const ASSOC: i32 = 3;
|
||||
|
||||
fn foo() {}
|
||||
}
|
||||
|
|
@ -68,8 +66,7 @@ impl Trait for () {
|
|||
impl Trait for u32 {
|
||||
type Gat<T> = ();
|
||||
|
||||
#[type_const]
|
||||
const ASSOC: i32 = 4;
|
||||
type const ASSOC: i32 = 4;
|
||||
|
||||
fn foo() -> u32 {
|
||||
42
|
||||
|
|
@ -89,8 +86,7 @@ type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
|||
//~| ERROR conflicting associated type bindings
|
||||
|
||||
trait Trait2 {
|
||||
#[type_const]
|
||||
const ASSOC: u32;
|
||||
type const ASSOC: u32;
|
||||
}
|
||||
|
||||
type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ LL | iter::empty::<String>()
|
|||
| ----------------------- return type was inferred to be `std::iter::Empty<String>` here
|
||||
|
||||
error[E0271]: expected `IntoIter<u32, 1>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:111:17
|
||||
--> $DIR/duplicate-bound-err.rs:107:17
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
@ -109,19 +109,19 @@ LL | [2u32].into_iter()
|
|||
| ------------------ return type was inferred to be `std::array::IntoIter<u32, 1>` here
|
||||
|
||||
error[E0271]: expected `impl Iterator<Item = u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:111:17
|
||||
--> $DIR/duplicate-bound-err.rs:107:17
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
note: required by a bound in `Trait3::foo::{anon_assoc#0}`
|
||||
--> $DIR/duplicate-bound-err.rs:107:31
|
||||
--> $DIR/duplicate-bound-err.rs:103:31
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32>;
|
||||
| ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}`
|
||||
|
||||
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:87:42
|
||||
--> $DIR/duplicate-bound-err.rs:84:42
|
||||
|
|
||||
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
|
|
@ -129,7 +129,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
|||
| `Item` bound here first
|
||||
|
||||
error: conflicting associated type bindings for `Item`
|
||||
--> $DIR/duplicate-bound-err.rs:87:17
|
||||
--> $DIR/duplicate-bound-err.rs:84:17
|
||||
|
|
||||
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
| ^^^^^^^^^^^^^----------^^----------^
|
||||
|
|
@ -138,7 +138,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
|||
| `Item` is specified to be `i32` here
|
||||
|
||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:96:43
|
||||
--> $DIR/duplicate-bound-err.rs:92:43
|
||||
|
|
||||
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||
|
|
@ -146,7 +146,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
|||
| `ASSOC` bound here first
|
||||
|
||||
error: conflicting associated constant bindings for `ASSOC`
|
||||
--> $DIR/duplicate-bound-err.rs:96:18
|
||||
--> $DIR/duplicate-bound-err.rs:92:18
|
||||
|
|
||||
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
| ^^^^^^^^^^^------------^^------------^
|
||||
|
|
@ -155,7 +155,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
|||
| `ASSOC` is specified to be `3` here
|
||||
|
||||
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:100:43
|
||||
--> $DIR/duplicate-bound-err.rs:96:43
|
||||
|
|
||||
LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
|
|
@ -163,7 +163,7 @@ LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
|||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:103:43
|
||||
--> $DIR/duplicate-bound-err.rs:99:43
|
||||
|
|
||||
LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||
|
|
@ -171,7 +171,7 @@ LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
|||
| `ASSOC` bound here first
|
||||
|
||||
error[E0271]: expected `Empty<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:119:16
|
||||
--> $DIR/duplicate-bound-err.rs:115:16
|
||||
|
|
||||
LL | uncallable(iter::empty::<u32>());
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
@ -179,13 +179,13 @@ LL | uncallable(iter::empty::<u32>());
|
|||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `uncallable`
|
||||
--> $DIR/duplicate-bound-err.rs:79:32
|
||||
--> $DIR/duplicate-bound-err.rs:76:32
|
||||
|
|
||||
LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
||||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||
|
||||
error[E0271]: expected `Empty<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
--> $DIR/duplicate-bound-err.rs:120:16
|
||||
--> $DIR/duplicate-bound-err.rs:116:16
|
||||
|
|
||||
LL | uncallable(iter::empty::<i32>());
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
|
||||
|
|
@ -193,13 +193,13 @@ LL | uncallable(iter::empty::<i32>());
|
|||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `uncallable`
|
||||
--> $DIR/duplicate-bound-err.rs:79:44
|
||||
--> $DIR/duplicate-bound-err.rs:76:44
|
||||
|
|
||||
LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
||||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
||||
--> $DIR/duplicate-bound-err.rs:121:22
|
||||
--> $DIR/duplicate-bound-err.rs:117:22
|
||||
|
|
||||
LL | uncallable_const(());
|
||||
| ---------------- ^^ expected `4`, found `3`
|
||||
|
|
@ -209,13 +209,13 @@ LL | uncallable_const(());
|
|||
= note: expected constant `4`
|
||||
found constant `3`
|
||||
note: required by a bound in `uncallable_const`
|
||||
--> $DIR/duplicate-bound-err.rs:81:46
|
||||
--> $DIR/duplicate-bound-err.rs:78:46
|
||||
|
|
||||
LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||
|
||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
||||
--> $DIR/duplicate-bound-err.rs:122:22
|
||||
--> $DIR/duplicate-bound-err.rs:118:22
|
||||
|
|
||||
LL | uncallable_const(4u32);
|
||||
| ---------------- ^^^^ expected `3`, found `4`
|
||||
|
|
@ -225,13 +225,13 @@ LL | uncallable_const(4u32);
|
|||
= note: expected constant `3`
|
||||
found constant `4`
|
||||
note: required by a bound in `uncallable_const`
|
||||
--> $DIR/duplicate-bound-err.rs:81:35
|
||||
--> $DIR/duplicate-bound-err.rs:78:35
|
||||
|
|
||||
LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
||||
--> $DIR/duplicate-bound-err.rs:123:20
|
||||
--> $DIR/duplicate-bound-err.rs:119:20
|
||||
|
|
||||
LL | uncallable_rtn(());
|
||||
| -------------- ^^ expected `4`, found `3`
|
||||
|
|
@ -241,7 +241,7 @@ LL | uncallable_rtn(());
|
|||
= note: expected constant `4`
|
||||
found constant `3`
|
||||
note: required by a bound in `uncallable_rtn`
|
||||
--> $DIR/duplicate-bound-err.rs:84:61
|
||||
--> $DIR/duplicate-bound-err.rs:81:61
|
||||
|
|
||||
LL | fn uncallable_rtn(
|
||||
| -------------- required by a bound in this function
|
||||
|
|
@ -249,7 +249,7 @@ LL | _: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>
|
|||
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||
|
||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
||||
--> $DIR/duplicate-bound-err.rs:124:20
|
||||
--> $DIR/duplicate-bound-err.rs:120:20
|
||||
|
|
||||
LL | uncallable_rtn(17u32);
|
||||
| -------------- ^^^^^ expected `3`, found `4`
|
||||
|
|
@ -259,7 +259,7 @@ LL | uncallable_rtn(17u32);
|
|||
= note: expected constant `3`
|
||||
found constant `4`
|
||||
note: required by a bound in `uncallable_rtn`
|
||||
--> $DIR/duplicate-bound-err.rs:84:34
|
||||
--> $DIR/duplicate-bound-err.rs:81:34
|
||||
|
|
||||
LL | fn uncallable_rtn(
|
||||
| -------------- required by a bound in this function
|
||||
|
|
|
|||
|
|
@ -189,8 +189,7 @@ trait Tra3 {
|
|||
trait Trait {
|
||||
type Gat<T>;
|
||||
|
||||
#[type_const]
|
||||
const ASSOC: i32;
|
||||
type const ASSOC: i32;
|
||||
|
||||
fn foo() -> impl Sized;
|
||||
}
|
||||
|
|
@ -198,8 +197,7 @@ trait Trait {
|
|||
impl Trait for () {
|
||||
type Gat<T> = ();
|
||||
|
||||
#[type_const]
|
||||
const ASSOC: i32 = 3;
|
||||
type const ASSOC: i32 = 3;
|
||||
|
||||
fn foo() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
struct S<const N: usize>;
|
||||
impl<const N: usize> S<N> {
|
||||
#[type_const]
|
||||
//~^ ERROR: the `#[type_const]` attribute is an experimental feature
|
||||
const LEN: usize = 1;
|
||||
type const LEN: usize = 1;
|
||||
//~^ ERROR: associated `type const` are unstable [E0658]
|
||||
//~| ERROR: `type const` syntax is experimental [E0658]
|
||||
fn arr() {
|
||||
[8; Self::LEN]
|
||||
//~^ WARN: cannot use constants which depend on generic parameters in types
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
error[E0658]: the `#[type_const]` attribute is an experimental feature
|
||||
error[E0658]: `type const` syntax is experimental
|
||||
--> $DIR/type-const-inherent-impl-normalize.rs:3:5
|
||||
|
|
||||
LL | #[type_const]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL | type const LEN: usize = 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]: associated `type const` are unstable
|
||||
--> $DIR/type-const-inherent-impl-normalize.rs:3:5
|
||||
|
|
||||
LL | type const LEN: usize = 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
|
||||
|
|
@ -36,7 +46,7 @@ LL | fn arr() {
|
|||
LL | [8; Self::LEN]
|
||||
| ^^^^^^^^^^^^^^ expected `()`, found `[{integer}; 1]`
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
error: aborting due to 3 previous errors; 2 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0308, E0658.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
|
|
@ -145,8 +145,6 @@ struct Test;
|
|||
#[diagnostic::on_unimplemented = 1]
|
||||
//~^ WARN malformed
|
||||
trait Hey {
|
||||
#[type_const = 1]
|
||||
//~^ ERROR malformed
|
||||
const HEY: usize = 5;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ LL | #[cfg_attr]
|
|||
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
|
||||
|
||||
error[E0463]: can't find crate for `wloop`
|
||||
--> $DIR/malformed-attrs.rs:217:1
|
||||
--> $DIR/malformed-attrs.rs:215:1
|
||||
|
|
||||
LL | extern crate wloop;
|
||||
| ^^^^^^^^^^^^^^^^^^^ can't find crate
|
||||
|
||||
error: malformed `allow` attribute input
|
||||
--> $DIR/malformed-attrs.rs:183:1
|
||||
--> $DIR/malformed-attrs.rs:181:1
|
||||
|
|
||||
LL | #[allow]
|
||||
| ^^^^^^^^
|
||||
|
|
@ -43,7 +43,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")]
|
|||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `expect` attribute input
|
||||
--> $DIR/malformed-attrs.rs:185:1
|
||||
--> $DIR/malformed-attrs.rs:183:1
|
||||
|
|
||||
LL | #[expect]
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -59,7 +59,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")]
|
|||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `warn` attribute input
|
||||
--> $DIR/malformed-attrs.rs:187:1
|
||||
--> $DIR/malformed-attrs.rs:185:1
|
||||
|
|
||||
LL | #[warn]
|
||||
| ^^^^^^^
|
||||
|
|
@ -75,7 +75,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")]
|
|||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `deny` attribute input
|
||||
--> $DIR/malformed-attrs.rs:189:1
|
||||
--> $DIR/malformed-attrs.rs:187:1
|
||||
|
|
||||
LL | #[deny]
|
||||
| ^^^^^^^
|
||||
|
|
@ -91,7 +91,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")]
|
|||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `forbid` attribute input
|
||||
--> $DIR/malformed-attrs.rs:191:1
|
||||
--> $DIR/malformed-attrs.rs:189:1
|
||||
|
|
||||
LL | #[forbid]
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -125,7 +125,7 @@ LL | #[proc_macro_derive]
|
|||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
|
||||
--> $DIR/malformed-attrs.rs:222:1
|
||||
--> $DIR/malformed-attrs.rs:220:1
|
||||
|
|
||||
LL | #[allow_internal_unsafe = 1]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -541,7 +541,7 @@ LL | #[cfi_encoding = ""]
|
|||
| help: must be of the form: `#[cfi_encoding = "encoding"]`
|
||||
|
||||
error[E0565]: malformed `marker` attribute input
|
||||
--> $DIR/malformed-attrs.rs:160:1
|
||||
--> $DIR/malformed-attrs.rs:158:1
|
||||
|
|
||||
LL | #[marker = 3]
|
||||
| ^^^^^^^^^---^
|
||||
|
|
@ -550,7 +550,7 @@ LL | #[marker = 3]
|
|||
| help: must be of the form: `#[marker]`
|
||||
|
||||
error[E0565]: malformed `fundamental` attribute input
|
||||
--> $DIR/malformed-attrs.rs:162:1
|
||||
--> $DIR/malformed-attrs.rs:160:1
|
||||
|
|
||||
LL | #[fundamental()]
|
||||
| ^^^^^^^^^^^^^--^
|
||||
|
|
@ -559,7 +559,7 @@ LL | #[fundamental()]
|
|||
| help: must be of the form: `#[fundamental]`
|
||||
|
||||
error[E0565]: malformed `ffi_pure` attribute input
|
||||
--> $DIR/malformed-attrs.rs:170:5
|
||||
--> $DIR/malformed-attrs.rs:168:5
|
||||
|
|
||||
LL | #[unsafe(ffi_pure = 1)]
|
||||
| ^^^^^^^^^^^^^^^^^^---^^
|
||||
|
|
@ -568,7 +568,7 @@ LL | #[unsafe(ffi_pure = 1)]
|
|||
| help: must be of the form: `#[ffi_pure]`
|
||||
|
||||
error[E0539]: malformed `link_ordinal` attribute input
|
||||
--> $DIR/malformed-attrs.rs:172:5
|
||||
--> $DIR/malformed-attrs.rs:170:5
|
||||
|
|
||||
LL | #[link_ordinal]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
@ -579,7 +579,7 @@ LL | #[link_ordinal]
|
|||
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute>
|
||||
|
||||
error[E0565]: malformed `ffi_const` attribute input
|
||||
--> $DIR/malformed-attrs.rs:176:5
|
||||
--> $DIR/malformed-attrs.rs:174:5
|
||||
|
|
||||
LL | #[unsafe(ffi_const = 1)]
|
||||
| ^^^^^^^^^^^^^^^^^^^---^^
|
||||
|
|
@ -588,13 +588,13 @@ LL | #[unsafe(ffi_const = 1)]
|
|||
| help: must be of the form: `#[ffi_const]`
|
||||
|
||||
error[E0539]: malformed `linkage` attribute input
|
||||
--> $DIR/malformed-attrs.rs:178:5
|
||||
--> $DIR/malformed-attrs.rs:176:5
|
||||
|
|
||||
LL | #[linkage]
|
||||
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
|
||||
|
||||
error[E0539]: malformed `debugger_visualizer` attribute input
|
||||
--> $DIR/malformed-attrs.rs:193:1
|
||||
--> $DIR/malformed-attrs.rs:191:1
|
||||
|
|
||||
LL | #[debugger_visualizer]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -605,7 +605,7 @@ LL | #[debugger_visualizer]
|
|||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute>
|
||||
|
||||
error[E0565]: malformed `automatically_derived` attribute input
|
||||
--> $DIR/malformed-attrs.rs:195:1
|
||||
--> $DIR/malformed-attrs.rs:193:1
|
||||
|
|
||||
LL | #[automatically_derived = 18]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^----^
|
||||
|
|
@ -614,7 +614,7 @@ LL | #[automatically_derived = 18]
|
|||
| help: must be of the form: `#[automatically_derived]`
|
||||
|
||||
error[E0565]: malformed `non_exhaustive` attribute input
|
||||
--> $DIR/malformed-attrs.rs:203:1
|
||||
--> $DIR/malformed-attrs.rs:201:1
|
||||
|
|
||||
LL | #[non_exhaustive = 1]
|
||||
| ^^^^^^^^^^^^^^^^^---^
|
||||
|
|
@ -623,7 +623,7 @@ LL | #[non_exhaustive = 1]
|
|||
| help: must be of the form: `#[non_exhaustive]`
|
||||
|
||||
error[E0565]: malformed `thread_local` attribute input
|
||||
--> $DIR/malformed-attrs.rs:209:1
|
||||
--> $DIR/malformed-attrs.rs:207:1
|
||||
|
|
||||
LL | #[thread_local()]
|
||||
| ^^^^^^^^^^^^^^--^
|
||||
|
|
@ -632,7 +632,7 @@ LL | #[thread_local()]
|
|||
| help: must be of the form: `#[thread_local]`
|
||||
|
||||
error[E0565]: malformed `no_link` attribute input
|
||||
--> $DIR/malformed-attrs.rs:213:1
|
||||
--> $DIR/malformed-attrs.rs:211:1
|
||||
|
|
||||
LL | #[no_link()]
|
||||
| ^^^^^^^^^--^
|
||||
|
|
@ -641,7 +641,7 @@ LL | #[no_link()]
|
|||
| help: must be of the form: `#[no_link]`
|
||||
|
||||
error[E0539]: malformed `macro_use` attribute input
|
||||
--> $DIR/malformed-attrs.rs:215:1
|
||||
--> $DIR/malformed-attrs.rs:213:1
|
||||
|
|
||||
LL | #[macro_use = 1]
|
||||
| ^^^^^^^^^^^^---^
|
||||
|
|
@ -659,7 +659,7 @@ LL + #[macro_use]
|
|||
|
|
||||
|
||||
error[E0539]: malformed `macro_export` attribute input
|
||||
--> $DIR/malformed-attrs.rs:220:1
|
||||
--> $DIR/malformed-attrs.rs:218:1
|
||||
|
|
||||
LL | #[macro_export = 18]
|
||||
| ^^^^^^^^^^^^^^^----^
|
||||
|
|
@ -676,7 +676,7 @@ LL + #[macro_export]
|
|||
|
|
||||
|
||||
error[E0565]: malformed `allow_internal_unsafe` attribute input
|
||||
--> $DIR/malformed-attrs.rs:222:1
|
||||
--> $DIR/malformed-attrs.rs:220:1
|
||||
|
|
||||
LL | #[allow_internal_unsafe = 1]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^---^
|
||||
|
|
@ -684,15 +684,6 @@ LL | #[allow_internal_unsafe = 1]
|
|||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[allow_internal_unsafe]`
|
||||
|
||||
error[E0565]: malformed `type_const` attribute input
|
||||
--> $DIR/malformed-attrs.rs:148:5
|
||||
|
|
||||
LL | #[type_const = 1]
|
||||
| ^^^^^^^^^^^^^---^
|
||||
| | |
|
||||
| | didn't expect any arguments here
|
||||
| help: must be of the form: `#[type_const]`
|
||||
|
||||
error: attribute should be applied to `const fn`
|
||||
--> $DIR/malformed-attrs.rs:32:1
|
||||
|
|
||||
|
|
@ -820,13 +811,13 @@ LL | #[no_implicit_prelude = 23]
|
|||
= help: `#[no_implicit_prelude]` can be applied to crates and modules
|
||||
|
||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
||||
--> $DIR/malformed-attrs.rs:154:1
|
||||
--> $DIR/malformed-attrs.rs:152:1
|
||||
|
|
||||
LL | #[diagnostic::do_not_recommend()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: `#[automatically_derived]` attribute cannot be used on modules
|
||||
--> $DIR/malformed-attrs.rs:195:1
|
||||
--> $DIR/malformed-attrs.rs:193:1
|
||||
|
|
||||
LL | #[automatically_derived = 18]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -835,7 +826,7 @@ LL | #[automatically_derived = 18]
|
|||
= help: `#[automatically_derived]` can only be applied to trait impl blocks
|
||||
|
||||
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
|
||||
--> $DIR/malformed-attrs.rs:229:1
|
||||
--> $DIR/malformed-attrs.rs:227:1
|
||||
|
|
||||
LL | #[ignore = 1]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
@ -854,7 +845,7 @@ LL | #[coroutine = 63] || {}
|
|||
= note: expected unit type `()`
|
||||
found coroutine `{coroutine@$DIR/malformed-attrs.rs:116:23: 116:25}`
|
||||
|
||||
error: aborting due to 76 previous errors; 8 warnings emitted
|
||||
error: aborting due to 75 previous errors; 8 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805.
|
||||
For more information about an error, try `rustc --explain E0308`.
|
||||
|
|
@ -882,7 +873,7 @@ LL | #[ignore()]
|
|||
|
||||
Future breakage diagnostic:
|
||||
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
|
||||
--> $DIR/malformed-attrs.rs:229:1
|
||||
--> $DIR/malformed-attrs.rs:227:1
|
||||
|
|
||||
LL | #[ignore = 1]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
trait Trait0: Parent0<i32> + Parent0<u32> {}
|
||||
trait Parent0<T> {
|
||||
#[type_const]
|
||||
const K: ();
|
||||
type const K: ();
|
||||
}
|
||||
|
||||
fn take0(_: impl Trait0<K = const { }>) {}
|
||||
|
|
@ -15,12 +14,10 @@ fn take0(_: impl Trait0<K = const { }>) {}
|
|||
|
||||
trait Trait1: Parent1 + Parent2 {}
|
||||
trait Parent1 {
|
||||
#[type_const]
|
||||
const C: i32;
|
||||
type const C: i32;
|
||||
}
|
||||
trait Parent2 {
|
||||
#[type_const]
|
||||
const C: &'static str;
|
||||
type const C: &'static str;
|
||||
}
|
||||
|
||||
fn take1(_: impl Trait1<C = "?">) {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0222]: ambiguous associated constant `K` in bounds of `Trait0`
|
||||
--> $DIR/ambiguity.rs:13:25
|
||||
--> $DIR/ambiguity.rs:12:25
|
||||
|
|
||||
LL | const K: ();
|
||||
| -----------
|
||||
LL | type const K: ();
|
||||
| ----------------
|
||||
| |
|
||||
| ambiguous `K` from `Parent0<u32>`
|
||||
| ambiguous `K` from `Parent0<i32>`
|
||||
|
|
@ -17,13 +17,13 @@ LL | fn take0(_: impl Trait0<K = const { }>) {}
|
|||
T: Parent0<i32>::K = const { }
|
||||
|
||||
error[E0222]: ambiguous associated constant `C` in bounds of `Trait1`
|
||||
--> $DIR/ambiguity.rs:26:25
|
||||
--> $DIR/ambiguity.rs:23:25
|
||||
|
|
||||
LL | const C: i32;
|
||||
| ------------ ambiguous `C` from `Parent1`
|
||||
LL | type const C: i32;
|
||||
| ----------------- ambiguous `C` from `Parent1`
|
||||
...
|
||||
LL | const C: &'static str;
|
||||
| --------------------- ambiguous `C` from `Parent2`
|
||||
LL | type const C: &'static str;
|
||||
| -------------------------- ambiguous `C` from `Parent2`
|
||||
...
|
||||
LL | fn take1(_: impl Trait1<C = "?">) {}
|
||||
| ^^^^^^^ ambiguous associated constant `C`
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@
|
|||
#![allow(unused, incomplete_features)]
|
||||
|
||||
pub trait Foo {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
|
||||
impl Foo for Bar {
|
||||
#[type_const]
|
||||
const N: usize = 3;
|
||||
type const N: usize = 3;
|
||||
}
|
||||
|
||||
const TEST: usize = 3;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait<T: ConstParamTy_> {
|
||||
#[type_const]
|
||||
const K: T;
|
||||
type const K: T;
|
||||
}
|
||||
|
||||
fn take(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/bound-var-in-ty-not-wf.rs:21:13
|
||||
--> $DIR/bound-var-in-ty-not-wf.rs:20:13
|
||||
|
|
||||
LL | K = const { () }
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/bound-var-in-ty-not-wf.rs:21:13
|
||||
--> $DIR/bound-var-in-ty-not-wf.rs:20:13
|
||||
|
|
||||
LL | K = const { () }
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
use std::marker::ConstParamTy_;
|
||||
|
||||
trait Trait<T: ConstParamTy_> {
|
||||
#[type_const]
|
||||
const K: T;
|
||||
type const K: T;
|
||||
}
|
||||
|
||||
fn take(
|
||||
|
|
|
|||
|
|
@ -12,13 +12,11 @@ trait Trait: SuperTrait {
|
|||
type N;
|
||||
type Q;
|
||||
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
|
||||
trait SuperTrait {
|
||||
#[type_const]
|
||||
const Q: &'static str;
|
||||
type const Q: &'static str;
|
||||
}
|
||||
|
||||
fn take0(_: impl Trait<N = 0, N = ()>) {}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,10 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
pub trait IsVoid {
|
||||
#[type_const]
|
||||
const IS_VOID: bool;
|
||||
type const IS_VOID: bool;
|
||||
}
|
||||
impl IsVoid for () {
|
||||
#[type_const]
|
||||
const IS_VOID: bool = true;
|
||||
type const IS_VOID: bool = true;
|
||||
}
|
||||
|
||||
pub trait Maybe {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0119]: conflicting implementations of trait `Maybe` for type `()`
|
||||
--> $DIR/coherence.rs:15:1
|
||||
--> $DIR/coherence.rs:13:1
|
||||
|
|
||||
LL | impl Maybe for () {}
|
||||
| ----------------- first implementation here
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
#![allow(incomplete_features)]
|
||||
|
||||
trait TraitWAssocConst {
|
||||
#[type_const]
|
||||
const A: usize;
|
||||
type const A: usize;
|
||||
}
|
||||
|
||||
fn foo<T: TraitWAssocConst<A = 1>>() {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
|
||||
--> $DIR/const-projection-err.rs:12:11
|
||||
--> $DIR/const-projection-err.rs:11:11
|
||||
|
|
||||
LL | foo::<T>();
|
||||
| ^ expected `1`, found `0`
|
||||
|
|
@ -7,7 +7,7 @@ LL | foo::<T>();
|
|||
= note: expected constant `1`
|
||||
found constant `0`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/const-projection-err.rs:9:28
|
||||
--> $DIR/const-projection-err.rs:8:28
|
||||
|
|
||||
LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
|
||||
| ^^^^^ required by this bound in `foo`
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait TraitA<T> {
|
||||
#[type_const]
|
||||
const K: u8 = 0;
|
||||
type const K: u8 = 0;
|
||||
}
|
||||
pub trait TraitB<T> {}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,12 @@ trait Trait {
|
|||
// NOTE: The `ConstParamTy_` bound is intentionally on the assoc const and not on the trait as
|
||||
// doing the latter would already render the trait dyn incompatible due to it being
|
||||
// bounded by `PartialEq<Self>` and supertrait bounds cannot mention `Self` like this.
|
||||
#[type_const]
|
||||
const K: Self where Self: std::marker::ConstParamTy_;
|
||||
type const K: Self where Self: std::marker::ConstParamTy_;
|
||||
//~^ NOTE it contains associated const `K` whose type references the `Self` type
|
||||
|
||||
// This is not a "`Self` projection" in our sense (which would be allowed)
|
||||
// since the trait is not the principal trait or a supertrait thereof.
|
||||
#[type_const]
|
||||
const Q: <Self as SomeOtherTrait>::Output;
|
||||
type const Q: <Self as SomeOtherTrait>::Output;
|
||||
//~^ NOTE it contains associated const `Q` whose type references the `Self` type
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:38:16
|
||||
--> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:36: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:18:11
|
||||
--> $DIR/dyn-compat-assoc-const-ty-mentions-self.rs:17:16
|
||||
|
|
||||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
...
|
||||
LL | const K: Self where Self: std::marker::ConstParamTy_;
|
||||
| ^ ...because it contains associated const `K` whose type references the `Self` type
|
||||
LL | type const K: Self where Self: std::marker::ConstParamTy_;
|
||||
| ^ ...because it contains associated const `K` whose type references the `Self` type
|
||||
...
|
||||
LL | const Q: <Self as SomeOtherTrait>::Output;
|
||||
| ^ ...because it contains associated const `Q` whose type references the `Self` type
|
||||
LL | type const Q: <Self as SomeOtherTrait>::Output;
|
||||
| ^ ...because it contains associated const `Q` whose type references the `Self` type
|
||||
= help: consider moving `K` to another trait
|
||||
= help: consider moving `Q` to another trait
|
||||
|
||||
|
|
|
|||
|
|
@ -7,25 +7,20 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait: SuperTrait<C = 3> {
|
||||
#[type_const]
|
||||
const K: usize;
|
||||
type const K: usize;
|
||||
}
|
||||
|
||||
trait SuperTrait {
|
||||
#[type_const]
|
||||
const Q: usize;
|
||||
#[type_const]
|
||||
const C: usize;
|
||||
type const Q: usize;
|
||||
type const C: usize;
|
||||
}
|
||||
|
||||
trait Bound {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
|
||||
impl Bound for () {
|
||||
#[type_const]
|
||||
const N: usize = 10;
|
||||
type const N: usize = 10;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: usize = 1;
|
||||
type const N: usize = 1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0271]: type mismatch resolving `<() as Trait>::N == 0`
|
||||
--> $DIR/dyn-compat-const-mismatch.rs:17:32
|
||||
--> $DIR/dyn-compat-const-mismatch.rs:15:32
|
||||
|
|
||||
LL | let _: &dyn Trait<N = 0> = &();
|
||||
| ^^^ expected `0`, found `1`
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@
|
|||
trait X<const N: usize = { <Self as Y>::N }> {}
|
||||
|
||||
trait Y {
|
||||
#[type_const]
|
||||
const N: usize;
|
||||
type const N: usize;
|
||||
}
|
||||
|
||||
impl<T: ?Sized> Y for T {
|
||||
#[type_const]
|
||||
const N: usize = 1;
|
||||
type const N: usize = 1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0393]: the const parameter `N` must be explicitly specified
|
||||
--> $DIR/dyn-compat-const-param-default-mentions-self.rs:20:16
|
||||
--> $DIR/dyn-compat-const-param-default-mentions-self.rs:18:16
|
||||
|
|
||||
LL | trait X<const N: usize = { <Self as Y>::N }> {}
|
||||
| -------------------------------------------- const parameter `N` must be specified for this
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const Y: i32;
|
||||
type const Y: i32;
|
||||
}
|
||||
|
||||
struct Hold<T: ?Sized>(T);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: associated constant binding in trait object type mentions `Self`
|
||||
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:21:12
|
||||
--> $DIR/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs:20:12
|
||||
|
|
||||
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
|
||||
| -------------------- this binding mentions `Self`
|
||||
|
|
|
|||
|
|
@ -5,13 +5,11 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
trait X: Y<K = { Self::Q }> {
|
||||
#[type_const]
|
||||
const Q: usize;
|
||||
type const Q: usize;
|
||||
}
|
||||
|
||||
trait Y {
|
||||
#[type_const]
|
||||
const K: usize;
|
||||
type const K: usize;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0191]: the value of the associated constant `K` in `Y` must be specified
|
||||
--> $DIR/dyn-compat-const-projection-from-supertrait-mentions-self.rs:18:16
|
||||
--> $DIR/dyn-compat-const-projection-from-supertrait-mentions-self.rs:16:16
|
||||
|
|
||||
LL | const K: usize;
|
||||
| -------------- `K` defined here
|
||||
LL | type const K: usize;
|
||||
| ------------------- `K` defined here
|
||||
...
|
||||
LL | let _: dyn X<Q = 10>;
|
||||
| ^^^^^^^^^ help: specify the associated constant: `X<Q = 10, K = /* CONST */>`
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
trait Trait {
|
||||
const K: usize;
|
||||
//~^ NOTE it contains associated const `K` that's not marked `#[type_const]`
|
||||
//~^ NOTE it contains associated const `K` that's not defined as `type const`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -16,5 +16,5 @@ fn main() {
|
|||
// Check that specifying the non-type assoc const doesn't "magically make it work".
|
||||
let _: dyn Trait<K = 0>;
|
||||
//~^ ERROR the trait `Trait` is not dyn compatible
|
||||
//~| ERROR use of trait associated const without `#[type_const]`
|
||||
//~| ERROR use of trait associated const not defined as `type const`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,16 +11,16 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
|||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const K: usize;
|
||||
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
|
||||
| ^ ...because it contains associated const `K` that's not defined as `type const`
|
||||
= help: consider moving `K` to another trait
|
||||
|
||||
error: use of trait associated const without `#[type_const]`
|
||||
error: use of trait associated const not defined as `type const`
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:22
|
||||
|
|
||||
LL | let _: dyn Trait<K = 0>;
|
||||
| ^^^^^
|
||||
|
|
||||
= note: the declaration in the trait must be marked with `#[type_const]`
|
||||
= note: the declaration in the trait must begin with `type const` not just `const` alone
|
||||
|
||||
error[E0038]: the trait `Trait` is not dyn compatible
|
||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:16
|
||||
|
|
@ -35,7 +35,7 @@ note: for a trait to be dyn compatible it needs to allow building a vtable
|
|||
LL | trait Trait {
|
||||
| ----- this trait is not dyn compatible...
|
||||
LL | const K: usize;
|
||||
| ^ ...because it contains associated const `K` that's not marked `#[type_const]`
|
||||
| ^ ...because it contains associated const `K` that's not defined as `type const`
|
||||
= help: consider moving `K` to another trait
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
|
|
|||
|
|
@ -6,13 +6,11 @@
|
|||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const N: i32 where Self: Bound;
|
||||
type const N: i32 where Self: Bound;
|
||||
}
|
||||
|
||||
impl Trait for () {
|
||||
#[type_const]
|
||||
const N: i32 = 0;
|
||||
type const N: i32 = 0;
|
||||
}
|
||||
|
||||
trait Bound {}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
error[E0277]: the trait bound `(): Bound` is not satisfied
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:23:32
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:21:32
|
||||
|
|
||||
LL | let _: &dyn Trait<N = 0> = &();
|
||||
| ^^^ the trait `Bound` is not implemented for `()`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:18:1
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:16:1
|
||||
|
|
||||
LL | trait Bound {}
|
||||
| ^^^^^^^^^^^
|
||||
note: required by a bound in `Trait::N`
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:10:30
|
||||
--> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:9:35
|
||||
|
|
||||
LL | const N: i32 where Self: Bound;
|
||||
| ^^^^^ required by this bound in `Trait::N`
|
||||
LL | type const N: i32 where Self: Bound;
|
||||
| ^^^^^ required by this bound in `Trait::N`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,12 @@
|
|||
|
||||
trait A {
|
||||
type Ty: std::marker::ConstParamTy_;
|
||||
#[type_const]
|
||||
const CT: Self::Ty;
|
||||
type const CT: Self::Ty;
|
||||
}
|
||||
|
||||
impl A for () {
|
||||
type Ty = i32;
|
||||
#[type_const]
|
||||
const CT: i32 = 0;
|
||||
type 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:34:33
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:32: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:21:1
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20: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:36:34
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34: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:21:1
|
||||
--> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:20:1
|
||||
|
|
||||
LL | impl A for () {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue