Allow provisional mgca syntax of type const <IDENT> = <EXPR> to be reconized.
Revert, but without type const. Update symbol for feature err, then update suggestion output, and lastly update tests that change because of those. Update these new tests with the correct syntax, and few existing tests with the new outputs the merge with main added. Fix for tidyfmt and some errors when manually resolving a merge conflicts. Update these tests to use update error messages and type const syntax. Update comments and error message to use new syntax instead of old type_const attribute. Remove the type_const attribute update some more tests to use the new syntax. Update these test cases. update feature gate test Change gate logic for `mgca_type_const_syntax` to work also if `min_generic_const_args` is enabled. Create a new feature gate that checks for the feature before expansion. Make rustfmt handle the `type const` syntax correctly. Add a convience method to check if a RhsKind is type const. Rename `Const` discriminant to `Body` for `ConstItemRhsKind` Give the `TraitItemKind` flag an enum instead of a simple bool to better describe what the flag is for. Update formatting for these match statements. Update clippy test to use type const syntax. Update test to use type const syntax. update rustfmt to match ast items. Update clippy to match ast and hir items. Few more test cases that used old attribute, instead of 'type const' Update to match the output from the feature gate checks. tidyfmt adjustments. Update the is_type_const, so I can constrain record!(..) in encoder.rs Update conditional compilation test. Move the feature gate to after expansion to allow for cfg(...) to work. Update some more tests to use the new syntax. Update type const tests in associated-const-bindings to use new syntax. Don't check based off the attribute, but the item here. Update some tests outside of the const_generics folder that were using #[type_const] update the tests in associated consts that use #[type_const] to use type const Update these mgca tests with the type const syntax. Add a flag to TraitItemKind for detecting type const for now. Maybe later change ItemConstRhs to have optional consts but that touches a lot more lines of code. Don't need into for these now that it's a query. Add is_type_const query to handle foreign def ids. update this test to use type const syntax. Fix logic here, we only want to lower if there is expression in this case. Update built-in macros to use ConstItemRhsKind Update more instance of the old ConstItemRhs. Rename ConstItemKind to ConstItemRhsKind, I noticed there is a typed called ConstantItemKind, so add the Rhs to the name to avoid confusion. Update lower to use ConstItemKind Add an other helper method to check if the rhs kinda has an expr. Update item parse to use ConstItemKind enum. Felt the field name could a be little clear when editing a few other things. Change the ConstItem struct see know if we have a type const or regular const. Make sure this syntax is properly feature gated.
This commit is contained in:
parent
4cd4c18438
commit
73a991fb9d
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;
|
||||
|
|
|
|||
|
|
@ -297,7 +297,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
|
||||
|
|
|
|||
|
|
@ -1292,9 +1292,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 },
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,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
|
||||
};
|
||||
}
|
||||
|
|
@ -1549,7 +1550,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;
|
||||
|
|
@ -1594,7 +1596,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,
|
||||
_ => {
|
||||
|
|
@ -1624,3 +1626,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 {
|
||||
|
|
|
|||
|
|
@ -607,14 +607,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 {
|
||||
|
|
|
|||
|
|
@ -356,7 +356,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