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 ident: Ident,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub ty: Box<Ty>,
|
pub ty: Box<Ty>,
|
||||||
pub rhs: Option<ConstItemRhs>,
|
pub rhs_kind: ConstItemRhsKind,
|
||||||
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||||
pub enum ConstItemRhs {
|
pub enum ConstItemRhsKind {
|
||||||
TypeConst(AnonConst),
|
Body { rhs: Option<Box<Expr>> },
|
||||||
Body(Box<Expr>),
|
TypeConst { rhs: Option<AnonConst> },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConstItemRhs {
|
impl ConstItemRhsKind {
|
||||||
pub fn span(&self) -> Span {
|
pub fn new_body(rhs: Box<Expr>) -> Self {
|
||||||
self.expr().span
|
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 {
|
match self {
|
||||||
ConstItemRhs::TypeConst(anon_const) => &anon_const.value,
|
Self::Body { rhs: Some(body) } => Some(&body),
|
||||||
ConstItemRhs::Body(expr) => expr,
|
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)]
|
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
|
||||||
|
|
|
||||||
|
|
@ -427,7 +427,7 @@ macro_rules! common_visitor_and_walkers {
|
||||||
Const,
|
Const,
|
||||||
ConstBlockItem,
|
ConstBlockItem,
|
||||||
ConstItem,
|
ConstItem,
|
||||||
ConstItemRhs,
|
ConstItemRhsKind,
|
||||||
Defaultness,
|
Defaultness,
|
||||||
Delegation,
|
Delegation,
|
||||||
DelegationMac,
|
DelegationMac,
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
}) => {
|
}) => {
|
||||||
let ident = self.lower_ident(*ident);
|
let ident = self.lower_ident(*ident);
|
||||||
|
|
@ -301,7 +301,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ty,
|
ty,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
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)
|
(ty, rhs)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -941,7 +941,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
let (ident, generics, kind, has_default) = match &i.kind {
|
let (ident, generics, kind, has_default) = match &i.kind {
|
||||||
AssocItemKind::Const(box ConstItem {
|
AssocItemKind::Const(box ConstItem {
|
||||||
ident, generics, ty, rhs, define_opaque, ..
|
ident,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
rhs_kind,
|
||||||
|
define_opaque,
|
||||||
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let (generics, kind) = self.lower_generics(
|
let (generics, kind) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
|
|
@ -952,15 +957,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ty,
|
ty,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
||||||
);
|
);
|
||||||
let rhs = rhs
|
// Trait associated consts don't need an expression/body.
|
||||||
.as_ref()
|
let rhs = if rhs_kind.has_expr() {
|
||||||
.map(|rhs| this.lower_const_item_rhs(attrs, Some(rhs), i.span));
|
Some(this.lower_const_item_rhs(rhs_kind, i.span))
|
||||||
hir::TraitItemKind::Const(ty, rhs)
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
hir::TraitItemKind::Const(ty, rhs, rhs_kind.is_type_const().into())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if define_opaque.is_some() {
|
if define_opaque.is_some() {
|
||||||
if rhs.is_some() {
|
if rhs_kind.has_expr() {
|
||||||
self.lower_define_opaque(hir_id, &define_opaque);
|
self.lower_define_opaque(hir_id, &define_opaque);
|
||||||
} else {
|
} else {
|
||||||
self.dcx().span_err(
|
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 {
|
AssocItemKind::Fn(box Fn {
|
||||||
sig, ident, generics, body: None, define_opaque, ..
|
sig, ident, generics, body: None, define_opaque, ..
|
||||||
|
|
@ -1154,7 +1162,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
let (ident, (generics, kind)) = match &i.kind {
|
let (ident, (generics, kind)) = match &i.kind {
|
||||||
AssocItemKind::Const(box ConstItem {
|
AssocItemKind::Const(box ConstItem {
|
||||||
ident, generics, ty, rhs, define_opaque, ..
|
ident,
|
||||||
|
generics,
|
||||||
|
ty,
|
||||||
|
rhs_kind,
|
||||||
|
define_opaque,
|
||||||
|
..
|
||||||
}) => (
|
}) => (
|
||||||
*ident,
|
*ident,
|
||||||
self.lower_generics(
|
self.lower_generics(
|
||||||
|
|
@ -1167,7 +1180,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
|
||||||
);
|
);
|
||||||
this.lower_define_opaque(hir_id, &define_opaque);
|
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)
|
hir::ImplItemKind::Const(ty, rhs)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -2374,15 +2374,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
fn lower_const_item_rhs(
|
fn lower_const_item_rhs(
|
||||||
&mut self,
|
&mut self,
|
||||||
attrs: &[hir::Attribute],
|
rhs_kind: &ConstItemRhsKind,
|
||||||
rhs: Option<&ConstItemRhs>,
|
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> hir::ConstItemRhs<'hir> {
|
) -> hir::ConstItemRhs<'hir> {
|
||||||
match rhs {
|
match rhs_kind {
|
||||||
Some(ConstItemRhs::TypeConst(anon)) => {
|
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))
|
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 {
|
let const_arg = ConstArg {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
kind: hir::ConstArgKind::Error(
|
kind: hir::ConstArgKind::Error(
|
||||||
|
|
@ -2392,10 +2397,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
};
|
};
|
||||||
hir::ConstItemRhs::TypeConst(self.arena.alloc(const_arg))
|
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);
|
self.check_defaultness(item.span, *defaultness);
|
||||||
if rhs.is_none() {
|
if !rhs_kind.has_expr() {
|
||||||
self.dcx().emit_err(errors::ConstWithoutBody {
|
self.dcx().emit_err(errors::ConstWithoutBody {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
replace_span: self.ending_semi_or_hi(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 {
|
if let AssocCtxt::Impl { .. } = ctxt {
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Const(box ConstItem { rhs: None, .. }) => {
|
AssocItemKind::Const(box ConstItem { rhs_kind, .. }) => {
|
||||||
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
if !rhs_kind.has_expr() {
|
||||||
span: item.span,
|
self.dcx().emit_err(errors::AssocConstWithoutBody {
|
||||||
replace_span: self.ending_semi_or_hi(item.span),
|
span: item.span,
|
||||||
});
|
replace_span: self.ending_semi_or_hi(item.span),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AssocItemKind::Fn(box Fn { body, .. }) => {
|
AssocItemKind::Fn(box Fn { body, .. }) => {
|
||||||
if body.is_none() && !self.is_sdylib_interface {
|
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), .. }) => {
|
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
||||||
self.check_impl_trait(ty, false)
|
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
|
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,
|
_ => false,
|
||||||
};
|
};
|
||||||
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
|
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!(global_registration, "global registration is experimental");
|
||||||
gate_all!(return_type_notation, "return type notation is experimental");
|
gate_all!(return_type_notation, "return type notation is experimental");
|
||||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ impl<'a> State<'a> {
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
}) => {
|
}) => {
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
|
|
@ -229,7 +229,7 @@ impl<'a> State<'a> {
|
||||||
None,
|
None,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs.as_ref().map(|ct| ct.expr()),
|
rhs_kind.expr(),
|
||||||
&item.vis,
|
&item.vis,
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
*defaultness,
|
*defaultness,
|
||||||
|
|
@ -573,7 +573,7 @@ impl<'a> State<'a> {
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
}) => {
|
}) => {
|
||||||
self.print_item_const(
|
self.print_item_const(
|
||||||
|
|
@ -581,7 +581,7 @@ impl<'a> State<'a> {
|
||||||
None,
|
None,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs.as_ref().map(|ct| ct.expr()),
|
rhs_kind.expr(),
|
||||||
vis,
|
vis,
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
*defaultness,
|
*defaultness,
|
||||||
|
|
|
||||||
|
|
@ -66,15 +66,6 @@ impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
|
||||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
|
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
|
// Markers
|
||||||
|
|
||||||
pub(crate) struct MarkerParser;
|
pub(crate) struct MarkerParser;
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,6 @@ attribute_parsers!(
|
||||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||||
Single<WithoutArgs<ThreadLocalParser>>,
|
Single<WithoutArgs<ThreadLocalParser>>,
|
||||||
Single<WithoutArgs<TrackCallerParser>>,
|
Single<WithoutArgs<TrackCallerParser>>,
|
||||||
Single<WithoutArgs<TypeConstParser>>,
|
|
||||||
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
|
||||||
// tidy-alphabetical-end
|
// tidy-alphabetical-end
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ pub(crate) fn expand(
|
||||||
|
|
||||||
// Generate anonymous constant serving as container for the allocator methods.
|
// Generate anonymous constant serving as container for the allocator methods.
|
||||||
let const_ty = ecx.ty(sig_span, TyKind::Tup(ThinVec::new()));
|
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 = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||||
let const_item = if is_stmt {
|
let const_item = if is_stmt {
|
||||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ fn generate_default_impl(
|
||||||
span,
|
span,
|
||||||
underscore,
|
underscore,
|
||||||
unit,
|
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.
|
// Generate anonymous constant serving as container for the allocator methods.
|
||||||
let const_ty = ecx.ty(ty_span, TyKind::Tup(ThinVec::new()));
|
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 = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||||
let const_item = if is_stmt {
|
let const_item = if is_stmt {
|
||||||
Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
|
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),
|
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)]),
|
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"))),
|
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
|
||||||
define_opaque: None,
|
define_opaque: None,
|
||||||
// test::TestDescAndFn {
|
// test::TestDescAndFn {
|
||||||
rhs: Some(ast::ConstItemRhs::Body(
|
rhs_kind: ast::ConstItemRhsKind::new_body(
|
||||||
cx.expr_struct(
|
cx.expr_struct(
|
||||||
sp,
|
sp,
|
||||||
test_path("TestDescAndFn"),
|
test_path("TestDescAndFn"),
|
||||||
|
|
@ -371,7 +371,7 @@ pub(crate) fn expand_test_or_bench(
|
||||||
field("testfn", test_fn), // }
|
field("testfn", test_fn), // }
|
||||||
],
|
],
|
||||||
), // }
|
), // }
|
||||||
)),
|
),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -345,7 +345,7 @@ where
|
||||||
let uneval = match constant.const_ {
|
let uneval = match constant.const_ {
|
||||||
Const::Ty(_, ct) => match ct.kind() {
|
Const::Ty(_, ct) => match ct.kind() {
|
||||||
ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None,
|
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,
|
ty::ConstKind::Unevaluated(_) => None,
|
||||||
// FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly
|
// 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.
|
// 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>,
|
typing_env: ty::TypingEnv<'tcx>,
|
||||||
) -> Result<R, ErrorHandled> {
|
) -> Result<R, ErrorHandled> {
|
||||||
let def = cid.instance.def.def_id();
|
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);
|
debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
|
||||||
|
|
||||||
let is_static = tcx.is_static(def);
|
let is_static = tcx.is_static(def);
|
||||||
|
|
|
||||||
|
|
@ -727,7 +727,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
span: Span,
|
span: Span,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
ty: Box<ast::Ty>,
|
ty: Box<ast::Ty>,
|
||||||
rhs: ast::ConstItemRhs,
|
rhs_kind: ast::ConstItemRhsKind,
|
||||||
) -> Box<ast::Item> {
|
) -> Box<ast::Item> {
|
||||||
let defaultness = ast::Defaultness::Final;
|
let defaultness = ast::Defaultness::Final;
|
||||||
self.item(
|
self.item(
|
||||||
|
|
@ -740,7 +740,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
// FIXME(generic_const_items): Pass the generics as a parameter.
|
// FIXME(generic_const_items): Pass the generics as a parameter.
|
||||||
generics: ast::Generics::default(),
|
generics: ast::Generics::default(),
|
||||||
ty,
|
ty,
|
||||||
rhs: Some(rhs),
|
rhs_kind,
|
||||||
define_opaque: None,
|
define_opaque: None,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
|
||||||
|
|
@ -888,13 +888,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
|
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
|
// The `#[loop_match]` and `#[const_continue]` attributes are part of the
|
||||||
// lang experiment for RFC 3720 tracked in:
|
// lang experiment for RFC 3720 tracked in:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -561,6 +561,8 @@ declare_features! (
|
||||||
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
(unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)),
|
||||||
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
/// Allows `#[marker]` on certain traits allowing overlapping implementations.
|
||||||
(unstable, marker_trait_attr, "1.30.0", Some(29864)),
|
(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).
|
/// Enables the generic const args MVP (only bare paths, not arbitrary computation).
|
||||||
(incomplete, min_generic_const_args, "1.84.0", Some(132980)),
|
(incomplete, min_generic_const_args, "1.84.0", Some(132980)),
|
||||||
/// A minimal, sound subset of specialization intended to be used by the
|
/// A minimal, sound subset of specialization intended to be used by the
|
||||||
|
|
|
||||||
|
|
@ -1292,9 +1292,6 @@ pub enum AttributeKind {
|
||||||
/// Represents `#[track_caller]`
|
/// Represents `#[track_caller]`
|
||||||
TrackCaller(Span),
|
TrackCaller(Span),
|
||||||
|
|
||||||
/// Represents `#[type_const]`.
|
|
||||||
TypeConst(Span),
|
|
||||||
|
|
||||||
/// Represents `#[type_length_limit]`
|
/// Represents `#[type_length_limit]`
|
||||||
TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
TypeLengthLimit { attr_span: Span, limit_span: Span, limit: Limit },
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,6 @@ impl AttributeKind {
|
||||||
TargetFeature { .. } => No,
|
TargetFeature { .. } => No,
|
||||||
ThreadLocal => No,
|
ThreadLocal => No,
|
||||||
TrackCaller(..) => Yes,
|
TrackCaller(..) => Yes,
|
||||||
TypeConst(..) => Yes,
|
|
||||||
TypeLengthLimit { .. } => No,
|
TypeLengthLimit { .. } => No,
|
||||||
UnstableFeatureBound(..) => No,
|
UnstableFeatureBound(..) => No,
|
||||||
Used { .. } => No,
|
Used { .. } => No,
|
||||||
|
|
|
||||||
|
|
@ -3199,7 +3199,7 @@ impl<'hir> TraitItem<'hir> {
|
||||||
|
|
||||||
expect_methods_self_kind! {
|
expect_methods_self_kind! {
|
||||||
expect_const, (&'hir Ty<'hir>, Option<ConstItemRhs<'hir>>),
|
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>),
|
expect_fn, (&FnSig<'hir>, &TraitFn<'hir>),
|
||||||
TraitItemKind::Fn(ty, trfn), (ty, trfn);
|
TraitItemKind::Fn(ty, trfn), (ty, trfn);
|
||||||
|
|
@ -3219,11 +3219,32 @@ pub enum TraitFn<'hir> {
|
||||||
Provided(BodyId),
|
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
|
/// Represents a trait method or associated constant or type
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub enum TraitItemKind<'hir> {
|
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).
|
/// 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.
|
/// An associated function with an optional body.
|
||||||
Fn(FnSig<'hir>, TraitFn<'hir>),
|
Fn(FnSig<'hir>, TraitFn<'hir>),
|
||||||
/// An associated type with (possibly empty) bounds and optional concrete
|
/// An associated type with (possibly empty) bounds and optional concrete
|
||||||
|
|
@ -4686,7 +4707,7 @@ impl<'hir> OwnerNode<'hir> {
|
||||||
| OwnerNode::TraitItem(TraitItem {
|
| OwnerNode::TraitItem(TraitItem {
|
||||||
kind:
|
kind:
|
||||||
TraitItemKind::Fn(_, TraitFn::Provided(body))
|
TraitItemKind::Fn(_, TraitFn::Provided(body))
|
||||||
| TraitItemKind::Const(_, Some(ConstItemRhs::Body(body))),
|
| TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _),
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| OwnerNode::ImplItem(ImplItem {
|
| OwnerNode::ImplItem(ImplItem {
|
||||||
|
|
@ -4913,7 +4934,7 @@ impl<'hir> Node<'hir> {
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
Node::TraitItem(it) => match it.kind {
|
Node::TraitItem(it) => match it.kind {
|
||||||
TraitItemKind::Const(ty, _) => Some(ty),
|
TraitItemKind::Const(ty, _, _) => Some(ty),
|
||||||
TraitItemKind::Type(_, ty) => ty,
|
TraitItemKind::Type(_, ty) => ty,
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
|
|
@ -4956,7 +4977,7 @@ impl<'hir> Node<'hir> {
|
||||||
| Node::TraitItem(TraitItem {
|
| Node::TraitItem(TraitItem {
|
||||||
owner_id,
|
owner_id,
|
||||||
kind:
|
kind:
|
||||||
TraitItemKind::Const(.., Some(ConstItemRhs::Body(body)))
|
TraitItemKind::Const(_, Some(ConstItemRhs::Body(body)), _)
|
||||||
| TraitItemKind::Fn(_, TraitFn::Provided(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_defaultness(&defaultness));
|
||||||
try_visit!(visitor.visit_id(hir_id));
|
try_visit!(visitor.visit_id(hir_id));
|
||||||
match *kind {
|
match *kind {
|
||||||
TraitItemKind::Const(ref ty, default) => {
|
TraitItemKind::Const(ref ty, default, _) => {
|
||||||
try_visit!(visitor.visit_ty_unambig(ty));
|
try_visit!(visitor.visit_ty_unambig(ty));
|
||||||
visit_opt!(visitor, visit_const_item_rhs, default);
|
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);
|
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)?;
|
wfcheck::check_type_const(wfcx, def_id, ty, true)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -2060,14 +2060,14 @@ fn compare_type_const<'tcx>(
|
||||||
.dcx()
|
.dcx()
|
||||||
.struct_span_err(
|
.struct_span_err(
|
||||||
tcx.def_span(impl_const_item.def_id),
|
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(
|
.with_span_note(
|
||||||
MultiSpan::from_spans(vec![
|
MultiSpan::from_spans(vec![
|
||||||
tcx.def_span(trait_const_item.def_id),
|
tcx.def_span(trait_const_item.def_id),
|
||||||
trait_type_const_span,
|
trait_type_const_span,
|
||||||
]),
|
]),
|
||||||
"trait declaration of const is marked with `#[type_const]`",
|
"trait declaration of const is marked as `type const`",
|
||||||
)
|
)
|
||||||
.emit());
|
.emit());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -955,7 +955,7 @@ pub(crate) fn check_associated_item(
|
||||||
wfcx.register_wf_obligation(span, loc, ty.into());
|
wfcx.register_wf_obligation(span, loc, ty.into());
|
||||||
|
|
||||||
let has_value = item.defaultness(tcx).has_value();
|
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)?;
|
check_type_const(wfcx, def_id, ty, has_value)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
const_param_default,
|
const_param_default,
|
||||||
anon_const_kind,
|
anon_const_kind,
|
||||||
const_of_item,
|
const_of_item,
|
||||||
|
is_rhs_type_const,
|
||||||
..*providers
|
..*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), .. })
|
let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. })
|
||||||
| Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. })
|
| Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. })
|
||||||
| Node::TraitItem(hir::TraitItem {
|
| Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), ..
|
kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _),
|
||||||
|
..
|
||||||
})) = grandparent_node
|
})) = grandparent_node
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1594,7 +1596,7 @@ fn const_of_item<'tcx>(
|
||||||
let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
|
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::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
|
||||||
hir::Node::TraitItem(hir::TraitItem {
|
hir::Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Const(.., ct), ..
|
kind: hir::TraitItemKind::Const(_, ct, _), ..
|
||||||
}) => ct.expect("no default value for trait assoc const"),
|
}) => ct.expect("no default value for trait assoc const"),
|
||||||
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
|
hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
|
||||||
_ => {
|
_ => {
|
||||||
|
|
@ -1624,3 +1626,22 @@ fn const_of_item<'tcx>(
|
||||||
ty::EarlyBinder::bind(ct)
|
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)
|
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);
|
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||||
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
Ty::new_fn_def(tcx, def_id.to_def_id(), args)
|
||||||
}
|
}
|
||||||
TraitItemKind::Const(ty, rhs) => rhs
|
TraitItemKind::Const(ty, rhs, _) => rhs
|
||||||
.and_then(|rhs| {
|
.and_then(|rhs| {
|
||||||
ty.is_suggestable_infer_ty().then(|| {
|
ty.is_suggestable_infer_ty().then(|| {
|
||||||
infer_placeholder_type(
|
infer_placeholder_type(
|
||||||
|
|
@ -420,9 +420,9 @@ fn infer_placeholder_type<'tcx>(
|
||||||
kind: &'static str,
|
kind: &'static str,
|
||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let tcx = cx.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
|
// 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()) {
|
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()) {
|
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()
|
tcx.type_of(trait_item_def_id).instantiate_identity()
|
||||||
|
|
@ -430,7 +430,7 @@ fn infer_placeholder_type<'tcx>(
|
||||||
Ty::new_error_with_message(
|
Ty::new_error_with_message(
|
||||||
tcx,
|
tcx,
|
||||||
ty_span,
|
ty_span,
|
||||||
"constant with #[type_const] requires an explicit type",
|
"constant with `type const` requires an explicit type",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -607,14 +607,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
if tcx.features().min_generic_const_args() {
|
if tcx.features().min_generic_const_args() {
|
||||||
let mut err = self.dcx().struct_span_err(
|
let mut err = self.dcx().struct_span_err(
|
||||||
constraint.span,
|
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());
|
return Err(err.emit());
|
||||||
} else {
|
} else {
|
||||||
let err = self.dcx().span_delayed_bug(
|
let err = self.dcx().span_delayed_bug(
|
||||||
constraint.span,
|
constraint.span,
|
||||||
"use of trait associated const without `#[type_const]`",
|
"use of trait associated const defined as `type const`",
|
||||||
);
|
);
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2849,19 +2849,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
if tcx.is_type_const(def_id) {
|
if tcx.is_type_const(def_id) {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let mut err = self
|
let mut err = self.dcx().struct_span_err(
|
||||||
.dcx()
|
span,
|
||||||
.struct_span_err(span, "use of `const` in the type system without `#[type_const]`");
|
"use of `const` in the type system not defined as `type const`",
|
||||||
|
);
|
||||||
if def_id.is_local() {
|
if def_id.is_local() {
|
||||||
let name = tcx.def_path_str(def_id);
|
let name = tcx.def_path_str(def_id);
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
tcx.def_span(def_id).shrink_to_lo(),
|
tcx.def_span(def_id).shrink_to_lo(),
|
||||||
format!("add `#[type_const]` attribute to `{name}`"),
|
format!("add `type` before `const` for `{name}`"),
|
||||||
format!("#[type_const]\n"),
|
format!("type "),
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
} else {
|
} 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())
|
Err(err.emit())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>(
|
||||||
},
|
},
|
||||||
hir::Node::TraitItem(item) => match item.kind {
|
hir::Node::TraitItem(item) => match item.kind {
|
||||||
hir::TraitItemKind::Type(_, ty) => ty.into_iter().collect(),
|
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),
|
ref item => bug!("Unexpected TraitItem {:?}", item),
|
||||||
},
|
},
|
||||||
hir::Node::Item(item) => match item.kind {
|
hir::Node::Item(item) => match item.kind {
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
||||||
}
|
}
|
||||||
DefKind::Const
|
DefKind::Const
|
||||||
if !tcx.generics_of(item_def_id).own_requires_monomorphization()
|
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
|
// FIXME(generic_const_items): Passing empty instead of identity args is fishy but
|
||||||
// seems to be fine for now. Revisit this!
|
// seems to be fine for now. Revisit this!
|
||||||
|
|
|
||||||
|
|
@ -937,7 +937,7 @@ impl<'a> State<'a> {
|
||||||
self.maybe_print_comment(ti.span.lo());
|
self.maybe_print_comment(ti.span.lo());
|
||||||
self.print_attrs(self.attrs(ti.hir_id()));
|
self.print_attrs(self.attrs(ti.hir_id()));
|
||||||
match ti.kind {
|
match ti.kind {
|
||||||
hir::TraitItemKind::Const(ty, default) => {
|
hir::TraitItemKind::Const(ty, default, _) => {
|
||||||
self.print_associated_const(ti.ident, ti.generics, ty, default);
|
self.print_associated_const(ti.ident, ti.generics, ty, default);
|
||||||
}
|
}
|
||||||
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_idents)) => {
|
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) {
|
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||||
use ast::ItemKind::*;
|
use ast::ItemKind::*;
|
||||||
|
|
||||||
let expr = if let Const(box ast::ConstItem { rhs: Some(rhs), .. }) = &item.kind {
|
let expr = if let Const(box ast::ConstItem { rhs_kind, .. }) = &item.kind {
|
||||||
rhs.expr()
|
if let Some(e) = rhs_kind.expr() { e } else { return }
|
||||||
} else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind {
|
} else if let Static(box ast::StaticItem { expr: Some(expr), .. }) = &item.kind {
|
||||||
expr
|
expr
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -418,6 +418,7 @@ provide! { tcx, def_id, other, cdata,
|
||||||
}
|
}
|
||||||
anon_const_kind => { table }
|
anon_const_kind => { table }
|
||||||
const_of_item => { table }
|
const_of_item => { table }
|
||||||
|
is_rhs_type_const => { table }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
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);
|
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);
|
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 {
|
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>>,
|
anon_const_kind: Table<DefIndex, LazyValue<ty::AnonConstKind>>,
|
||||||
const_of_item: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, ty::Const<'static>>>>,
|
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>>>>,
|
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)]
|
#[derive(TyEncodable, TyDecodable)]
|
||||||
|
|
|
||||||
|
|
@ -293,13 +293,13 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
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
|
/// 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
|
/// projection, this allows us to retrieve the typesystem-appropriate representation of the
|
||||||
/// const value.
|
/// 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>> {
|
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) }
|
desc { |tcx| "computing the type-level value for `{}`", tcx.def_path_str(def_id) }
|
||||||
cache_on_disk_if { def_id.is_local() }
|
cache_on_disk_if { def_id.is_local() }
|
||||||
|
|
@ -2764,6 +2764,12 @@ rustc_queries! {
|
||||||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||||
separate_provide_extern
|
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! }
|
rustc_with_all_queries! { define_callbacks! }
|
||||||
|
|
|
||||||
|
|
@ -845,7 +845,7 @@ impl DynCompatibilityViolation {
|
||||||
format!("it contains generic associated const `{name}`").into()
|
format!("it contains generic associated const `{name}`").into()
|
||||||
}
|
}
|
||||||
Self::AssocConst(name, AssocConstViolation::NonType, _) => {
|
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()
|
.into()
|
||||||
}
|
}
|
||||||
Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!(
|
Self::AssocConst(name, AssocConstViolation::TypeReferencesSelf, _) => format!(
|
||||||
|
|
@ -999,7 +999,7 @@ pub enum AssocConstViolation {
|
||||||
/// Has own generic parameters (GAC).
|
/// Has own generic parameters (GAC).
|
||||||
Generic,
|
Generic,
|
||||||
|
|
||||||
/// Isn't marked `#[type_const]`.
|
/// Isn't defined as `type const`.
|
||||||
NonType,
|
NonType,
|
||||||
|
|
||||||
/// Its type mentions the `Self` type parameter.
|
/// 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> {
|
pub fn type_const_span(self, def_id: DefId) -> Option<Span> {
|
||||||
matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst)
|
if !self.is_type_const(def_id) {
|
||||||
.then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp))
|
return None;
|
||||||
.flatten()
|
}
|
||||||
|
Some(self.def_span(def_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the given `def_id` is a const with the `#[type_const]` attribute.
|
/// Check if the given `def_id` is a `type const` (mgca)
|
||||||
pub fn is_type_const(self, def_id: DefId) -> bool {
|
pub fn is_type_const<I: Copy + IntoQueryParam<DefId>>(self, def_id: I) -> bool {
|
||||||
self.type_const_span(def_id).is_some()
|
// 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
|
/// Returns the movability of the coroutine of `def_id`, or panics
|
||||||
|
|
@ -2923,7 +2931,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let generics = self.generics_of(def_id);
|
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.
|
// weird arg setup (self + own args), but nested items *in* IATs (namely: opaques, i.e.
|
||||||
// ATPITs) do not.
|
// ATPITs) do not.
|
||||||
let is_inherent_assoc_ty = matches!(self.def_kind(def_id), DefKind::AssocTy)
|
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::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, _), span, .. })
|
||||||
| Node::TraitItem(hir::TraitItem {
|
| Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Const(ty, Some(_)),
|
kind: hir::TraitItemKind::Const(ty, Some(_), _),
|
||||||
span,
|
span,
|
||||||
..
|
..
|
||||||
}) => (*span, ty.span),
|
}) => (*span, ty.span),
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@ use rustc_ast::ast::*;
|
||||||
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
|
use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
|
||||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
||||||
use rustc_ast::util::case::Case;
|
use rustc_ast::util::case::Case;
|
||||||
use rustc_ast::{
|
use rustc_ast::{self as ast};
|
||||||
attr, {self as ast},
|
|
||||||
};
|
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err};
|
use rustc_errors::{Applicability, PResult, StashKey, inline_fluent, struct_span_code_err};
|
||||||
|
|
@ -286,13 +284,13 @@ impl<'a> Parser<'a> {
|
||||||
// CONST ITEM
|
// CONST ITEM
|
||||||
self.recover_const_mut(const_span);
|
self.recover_const_mut(const_span);
|
||||||
self.recover_missing_kw_before_item()?;
|
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 {
|
ItemKind::Const(Box::new(ConstItem {
|
||||||
defaultness: def_(),
|
defaultness: def_(),
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque: None,
|
define_opaque: None,
|
||||||
}))
|
}))
|
||||||
} else if let Some(kind) = self.is_reuse_item() {
|
} else if let Some(kind) = self.is_reuse_item() {
|
||||||
|
|
@ -303,8 +301,26 @@ impl<'a> Parser<'a> {
|
||||||
// MODULE ITEM
|
// MODULE ITEM
|
||||||
self.parse_item_mod(attrs)?
|
self.parse_item_mod(attrs)?
|
||||||
} else if self.eat_keyword_case(exp!(Type), case) {
|
} else if self.eat_keyword_case(exp!(Type), case) {
|
||||||
// TYPE ITEM
|
if let Const::Yes(const_span) = self.parse_constness(case) {
|
||||||
self.parse_type_alias(def_())?
|
// 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) {
|
} else if self.eat_keyword_case(exp!(Enum), case) {
|
||||||
// ENUM ITEM
|
// ENUM ITEM
|
||||||
self.parse_item_enum()?
|
self.parse_item_enum()?
|
||||||
|
|
@ -1113,13 +1129,12 @@ impl<'a> Parser<'a> {
|
||||||
define_opaque,
|
define_opaque,
|
||||||
}) => {
|
}) => {
|
||||||
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span });
|
||||||
let rhs = expr.map(ConstItemRhs::Body);
|
|
||||||
AssocItemKind::Const(Box::new(ConstItem {
|
AssocItemKind::Const(Box::new(ConstItem {
|
||||||
defaultness: Defaultness::Final,
|
defaultness: Defaultness::Final,
|
||||||
ident,
|
ident,
|
||||||
generics: Generics::default(),
|
generics: Generics::default(),
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind: ConstItemRhsKind::Body { rhs: expr },
|
||||||
define_opaque,
|
define_opaque,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
@ -1360,7 +1375,7 @@ impl<'a> Parser<'a> {
|
||||||
let kind = match ForeignItemKind::try_from(kind) {
|
let kind = match ForeignItemKind::try_from(kind) {
|
||||||
Ok(kind) => kind,
|
Ok(kind) => kind,
|
||||||
Err(kind) => match 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()))
|
let const_span = Some(span.with_hi(ident.span.lo()))
|
||||||
.filter(|span| span.can_be_used_for_suggestions());
|
.filter(|span| span.can_be_used_for_suggestions());
|
||||||
self.dcx().emit_err(errors::ExternItemCannotBeConst {
|
self.dcx().emit_err(errors::ExternItemCannotBeConst {
|
||||||
|
|
@ -1371,10 +1386,13 @@ impl<'a> Parser<'a> {
|
||||||
ident,
|
ident,
|
||||||
ty,
|
ty,
|
||||||
mutability: Mutability::Not,
|
mutability: Mutability::Not,
|
||||||
expr: rhs.map(|b| match b {
|
expr: match rhs_kind {
|
||||||
ConstItemRhs::TypeConst(anon_const) => anon_const.value,
|
ConstItemRhsKind::Body { rhs } => rhs,
|
||||||
ConstItemRhs::Body(expr) => expr,
|
ConstItemRhsKind::TypeConst { rhs: Some(anon) } => {
|
||||||
}),
|
Some(anon.value)
|
||||||
|
}
|
||||||
|
ConstItemRhsKind::TypeConst { rhs: None } => None,
|
||||||
|
},
|
||||||
safety: Safety::Default,
|
safety: Safety::Default,
|
||||||
define_opaque: None,
|
define_opaque: None,
|
||||||
}))
|
}))
|
||||||
|
|
@ -1516,13 +1534,16 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse a constant item with the prefix `"const"` already parsed.
|
/// 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
|
/// ```ebnf
|
||||||
/// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;
|
/// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_const_item(
|
fn parse_const_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
attrs: &[Attribute],
|
const_arg: bool,
|
||||||
) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<ast::ConstItemRhs>)> {
|
) -> PResult<'a, (Ident, Generics, Box<Ty>, ConstItemRhsKind)> {
|
||||||
let ident = self.parse_ident_or_underscore()?;
|
let ident = self.parse_ident_or_underscore()?;
|
||||||
|
|
||||||
let mut generics = self.parse_generics()?;
|
let mut generics = self.parse_generics()?;
|
||||||
|
|
@ -1549,16 +1570,15 @@ impl<'a> Parser<'a> {
|
||||||
let before_where_clause =
|
let before_where_clause =
|
||||||
if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
|
if self.may_recover() { self.parse_where_clause()? } else { WhereClause::default() };
|
||||||
|
|
||||||
let rhs = if self.eat(exp!(Eq)) {
|
let rhs = match (self.eat(exp!(Eq)), const_arg) {
|
||||||
if attr::contains_name(attrs, sym::type_const) {
|
(true, true) => ConstItemRhsKind::TypeConst {
|
||||||
let ct =
|
rhs: Some(
|
||||||
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?;
|
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?,
|
||||||
Some(ConstItemRhs::TypeConst(ct))
|
),
|
||||||
} else {
|
},
|
||||||
Some(ConstItemRhs::Body(self.parse_expr()?))
|
(true, false) => ConstItemRhsKind::Body { rhs: Some(self.parse_expr()?) },
|
||||||
}
|
(false, true) => ConstItemRhsKind::TypeConst { rhs: None },
|
||||||
} else {
|
(false, false) => ConstItemRhsKind::Body { rhs: None },
|
||||||
None
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let after_where_clause = self.parse_where_clause()?;
|
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
|
// 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.
|
// where-clause location on type aliases and associated types. See also #89122.
|
||||||
if before_where_clause.has_where_token
|
if before_where_clause.has_where_token
|
||||||
&& let Some(rhs) = &rhs
|
&& let Some(rhs_span) = rhs.span()
|
||||||
{
|
{
|
||||||
self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
|
self.dcx().emit_err(errors::WhereClauseBeforeConstBody {
|
||||||
span: before_where_clause.span,
|
span: before_where_clause.span,
|
||||||
name: ident.span,
|
name: ident.span,
|
||||||
body: rhs.span(),
|
body: rhs_span,
|
||||||
sugg: if !after_where_clause.has_where_token {
|
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 {
|
errors::WhereClauseBeforeConstBodySugg {
|
||||||
left: before_where_clause.span.shrink_to_lo(),
|
left: before_where_clause.span.shrink_to_lo(),
|
||||||
snippet: body_s,
|
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 {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
||||||
| AttributeKind::RustcVarianceOfOpaques
|
| AttributeKind::RustcVarianceOfOpaques
|
||||||
| AttributeKind::ShouldPanic { .. }
|
| AttributeKind::ShouldPanic { .. }
|
||||||
| AttributeKind::ThreadLocal
|
| AttributeKind::ThreadLocal
|
||||||
| AttributeKind::TypeConst{..}
|
|
||||||
| AttributeKind::TypeLengthLimit { .. }
|
| AttributeKind::TypeLengthLimit { .. }
|
||||||
| AttributeKind::UnstableFeatureBound(..)
|
| AttributeKind::UnstableFeatureBound(..)
|
||||||
| AttributeKind::Used { .. }
|
| AttributeKind::Used { .. }
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Node::TraitItem(trait_method) => match trait_method.kind {
|
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::Provided(_)) => true,
|
||||||
hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
|
hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_))
|
||||||
| hir::TraitItemKind::Type(..) => false,
|
| hir::TraitItemKind::Type(..) => false,
|
||||||
|
|
@ -209,7 +209,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
self.visit_nested_body(body);
|
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(_)) => {
|
hir::ItemKind::Const(_, _, _, init @ hir::ConstItemRhs::TypeConst(_)) => {
|
||||||
self.visit_const_item_rhs(init);
|
self.visit_const_item_rhs(init);
|
||||||
}
|
}
|
||||||
|
|
@ -258,11 +258,11 @@ impl<'tcx> ReachableContext<'tcx> {
|
||||||
}
|
}
|
||||||
Node::TraitItem(trait_method) => {
|
Node::TraitItem(trait_method) => {
|
||||||
match trait_method.kind {
|
match trait_method.kind {
|
||||||
hir::TraitItemKind::Const(_, None)
|
hir::TraitItemKind::Const(_, None, _)
|
||||||
| hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
|
| hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
|
||||||
// Keep going, nothing to get exported
|
// 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)) => {
|
hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => {
|
||||||
self.visit_nested_body(body_id);
|
self.visit_nested_body(body_id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2847,11 +2847,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
defaultness: _,
|
defaultness: _,
|
||||||
}) => {
|
}) => {
|
||||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::Item(
|
RibKind::Item(
|
||||||
|
|
@ -2871,7 +2870,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::Elided(LifetimeRes::Static),
|
LifetimeRibKind::Elided(LifetimeRes::Static),
|
||||||
|this| {
|
|this| {
|
||||||
if is_type_const
|
if rhs_kind.is_type_const()
|
||||||
&& !this.r.tcx.features().generic_const_parameter_types()
|
&& !this.r.tcx.features().generic_const_parameter_types()
|
||||||
{
|
{
|
||||||
this.with_rib(TypeNS, RibKind::ConstParamTy, |this| {
|
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(
|
||||||
this.resolve_const_item_rhs(
|
rhs_kind,
|
||||||
rhs,
|
Some((*ident, ConstantItemKind::Const)),
|
||||||
Some((*ident, ConstantItemKind::Const)),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.resolve_define_opaques(define_opaque);
|
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 {
|
AssocItemKind::Const(box ast::ConstItem {
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::AssocItem,
|
RibKind::AssocItem,
|
||||||
|
|
@ -3261,7 +3257,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
},
|
},
|
||||||
|this| {
|
|this| {
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
if is_type_const
|
if rhs_kind.is_type_const()
|
||||||
&& !this.r.tcx.features().generic_const_parameter_types()
|
&& !this.r.tcx.features().generic_const_parameter_types()
|
||||||
{
|
{
|
||||||
this.with_rib(TypeNS, RibKind::ConstParamTy, |this| {
|
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
|
// Only impose the restrictions of `ConstRibKind` for an
|
||||||
// actual constant expression in a provided default.
|
// actual constant expression in a provided default.
|
||||||
if let Some(rhs) = rhs {
|
//
|
||||||
// We allow arbitrary const expressions inside of associated consts,
|
// We allow arbitrary const expressions inside of associated consts,
|
||||||
// even if they are potentially not const evaluatable.
|
// even if they are potentially not const evaluatable.
|
||||||
//
|
//
|
||||||
// Type parameters can already be used and as associated consts are
|
// Type parameters can already be used and as associated consts are
|
||||||
// not used as part of the type system, this is far less surprising.
|
// not used as part of the type system, this is far less surprising.
|
||||||
this.resolve_const_item_rhs(rhs, None);
|
this.resolve_const_item_rhs(rhs_kind, None);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -3463,12 +3458,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
ident,
|
ident,
|
||||||
generics,
|
generics,
|
||||||
ty,
|
ty,
|
||||||
rhs,
|
rhs_kind,
|
||||||
define_opaque,
|
define_opaque,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
debug!("resolve_implementation AssocItemKind::Const");
|
debug!("resolve_implementation AssocItemKind::Const");
|
||||||
let is_type_const = attr::contains_name(&item.attrs, sym::type_const);
|
|
||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::AssocItem,
|
RibKind::AssocItem,
|
||||||
|
|
@ -3505,7 +3499,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
if is_type_const
|
if rhs_kind.is_type_const()
|
||||||
&& !this
|
&& !this
|
||||||
.r
|
.r
|
||||||
.tcx
|
.tcx
|
||||||
|
|
@ -3527,14 +3521,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
this.visit_ty(ty);
|
this.visit_ty(ty);
|
||||||
}
|
}
|
||||||
if let Some(rhs) = rhs {
|
// We allow arbitrary const expressions inside of associated consts,
|
||||||
// We allow arbitrary const expressions inside of associated consts,
|
// even if they are potentially not const evaluatable.
|
||||||
// even if they are potentially not const evaluatable.
|
//
|
||||||
//
|
// Type parameters can already be used and as associated consts are
|
||||||
// Type parameters can already be used and as associated consts are
|
// not used as part of the type system, this is far less surprising.
|
||||||
// not used as part of the type system, this is far less surprising.
|
this.resolve_const_item_rhs(rhs_kind, None);
|
||||||
this.resolve_const_item_rhs(rhs, None);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -3756,18 +3748,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
||||||
|
|
||||||
fn resolve_const_item_rhs(
|
fn resolve_const_item_rhs(
|
||||||
&mut self,
|
&mut self,
|
||||||
rhs: &'ast ConstItemRhs,
|
rhs_kind: &'ast ConstItemRhsKind,
|
||||||
item: Option<(Ident, ConstantItemKind)>,
|
item: Option<(Ident, ConstantItemKind)>,
|
||||||
) {
|
) {
|
||||||
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs {
|
self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| match rhs_kind {
|
||||||
ConstItemRhs::TypeConst(anon_const) => {
|
ConstItemRhsKind::TypeConst { rhs: Some(anon_const) } => {
|
||||||
this.resolve_anon_const(anon_const, AnonConstKind::ConstArg(IsRepeatExpr::No));
|
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.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
|
||||||
this.visit_expr(expr)
|
this.visit_expr(expr)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
_ => (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1453,6 +1453,7 @@ symbols! {
|
||||||
meta,
|
meta,
|
||||||
meta_sized,
|
meta_sized,
|
||||||
metadata_type,
|
metadata_type,
|
||||||
|
mgca_type_const_syntax,
|
||||||
min_const_fn,
|
min_const_fn,
|
||||||
min_const_generics,
|
min_const_generics,
|
||||||
min_const_unsafe_fn,
|
min_const_unsafe_fn,
|
||||||
|
|
@ -2339,7 +2340,6 @@ symbols! {
|
||||||
type_ascribe,
|
type_ascribe,
|
||||||
type_ascription,
|
type_ascription,
|
||||||
type_changing_struct_update,
|
type_changing_struct_update,
|
||||||
type_const,
|
|
||||||
type_id,
|
type_id,
|
||||||
type_id_eq,
|
type_id_eq,
|
||||||
type_info,
|
type_info,
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
||||||
// been emitted earlier in compilation.
|
// been emitted earlier in compilation.
|
||||||
//
|
//
|
||||||
// That's because we can only end up with an Unevaluated ty::Const for a const item
|
// 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.
|
// feature gate causes a parse error.
|
||||||
let ct = match tcx.def_kind(uv.def) {
|
let ct = match tcx.def_kind(uv.def) {
|
||||||
DefKind::AssocConst => match tcx.def_kind(tcx.parent(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();
|
let local_did = trait_item.owner_id.to_def_id();
|
||||||
cx.with_param_env(local_did, |cx| {
|
cx.with_param_env(local_did, |cx| {
|
||||||
let inner = match trait_item.kind {
|
let inner = match trait_item.kind {
|
||||||
hir::TraitItemKind::Const(ty, Some(default)) => {
|
hir::TraitItemKind::Const(ty, Some(default), _) => {
|
||||||
ProvidedAssocConstItem(Box::new(Constant {
|
ProvidedAssocConstItem(Box::new(Constant {
|
||||||
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
|
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
|
||||||
kind: clean_const_item_rhs(default, local_did),
|
kind: clean_const_item_rhs(default, local_did),
|
||||||
type_: clean_ty(ty, cx),
|
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));
|
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
|
||||||
RequiredAssocConstItem(generics, Box::new(clean_ty(ty, 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<'_>) {
|
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()
|
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
|
||||||
&& match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) {
|
&& match self.is_ty_freeze(cx.tcx, cx.typing_env(), ty) {
|
||||||
IsFreeze::No => true,
|
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)) {
|
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::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,
|
_ => return None,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -514,7 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
|
||||||
};
|
};
|
||||||
|
|
||||||
match item.kind {
|
match item.kind {
|
||||||
TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
|
TraitItemKind::Const(ty, _, _) | TraitItemKind::Type(_, Some(ty)) => {
|
||||||
self.check_ty(cx, ty, context);
|
self.check_ty(cx, ty, context);
|
||||||
},
|
},
|
||||||
TraitItemKind::Fn(ref sig, trait_method) => {
|
TraitItemKind::Fn(ref sig, trait_method) => {
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
ident: li,
|
ident: li,
|
||||||
generics: lg,
|
generics: lg,
|
||||||
ty: lt,
|
ty: lt,
|
||||||
rhs: lb,
|
rhs_kind: lb,
|
||||||
define_opaque: _,
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Const(box ConstItem {
|
Const(box ConstItem {
|
||||||
|
|
@ -363,7 +363,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
ident: ri,
|
ident: ri,
|
||||||
generics: rg,
|
generics: rg,
|
||||||
ty: rt,
|
ty: rt,
|
||||||
rhs: rb,
|
rhs_kind: rb,
|
||||||
define_opaque: _,
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -371,7 +371,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
|
||||||
&& eq_id(*li, *ri)
|
&& eq_id(*li, *ri)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& eq_ty(lt, rt)
|
&& 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 {
|
Fn(box ast::Fn {
|
||||||
|
|
@ -615,7 +615,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
ident: li,
|
ident: li,
|
||||||
generics: lg,
|
generics: lg,
|
||||||
ty: lt,
|
ty: lt,
|
||||||
rhs: lb,
|
rhs_kind: lb,
|
||||||
define_opaque: _,
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
Const(box ConstItem {
|
Const(box ConstItem {
|
||||||
|
|
@ -623,7 +623,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
ident: ri,
|
ident: ri,
|
||||||
generics: rg,
|
generics: rg,
|
||||||
ty: rt,
|
ty: rt,
|
||||||
rhs: rb,
|
rhs_kind: rb,
|
||||||
define_opaque: _,
|
define_opaque: _,
|
||||||
}),
|
}),
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -631,7 +631,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
|
||||||
&& eq_id(*li, *ri)
|
&& eq_id(*li, *ri)
|
||||||
&& eq_generics(lg, rg)
|
&& eq_generics(lg, rg)
|
||||||
&& eq_ty(lt, rt)
|
&& 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 {
|
Fn(box ast::Fn {
|
||||||
|
|
@ -791,12 +791,18 @@ pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool {
|
||||||
eq_expr(&l.value, &r.value)
|
eq_expr(&l.value, &r.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq_const_item_rhs(l: &ConstItemRhs, r: &ConstItemRhs) -> bool {
|
pub fn eq_const_item_rhs(l: &ConstItemRhsKind, r: &ConstItemRhsKind) -> bool {
|
||||||
use ConstItemRhs::*;
|
use ConstItemRhsKind::*;
|
||||||
match (l, r) {
|
match (l, r) {
|
||||||
(TypeConst(l), TypeConst(r)) => eq_anon_const(l, r),
|
(TypeConst { rhs: Some(l) }, TypeConst { rhs: Some(r) }) => eq_anon_const(l, r),
|
||||||
(Body(l), Body(r)) => eq_expr(l, r),
|
(TypeConst { rhs: None }, TypeConst { rhs: None }) => true,
|
||||||
(TypeConst(..), Body(..)) | (Body(..), TypeConst(..)) => false,
|
(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)]
|
#![feature(min_generic_const_args)]
|
||||||
|
|
||||||
trait AssocConstTrait {
|
trait AssocConstTrait {
|
||||||
#[type_const]
|
|
||||||
const ASSOC: usize;
|
type const ASSOC: usize;
|
||||||
}
|
}
|
||||||
fn assoc_const_args<T>()
|
fn assoc_const_args<T>()
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
#![feature(min_generic_const_args)]
|
#![feature(min_generic_const_args)]
|
||||||
|
|
||||||
trait AssocConstTrait {
|
trait AssocConstTrait {
|
||||||
#[type_const]
|
|
||||||
const ASSOC: usize;
|
type const ASSOC: usize;
|
||||||
}
|
}
|
||||||
fn assoc_const_args<T>()
|
fn assoc_const_args<T>()
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -2028,12 +2028,16 @@ impl<'a> StaticParts<'a> {
|
||||||
),
|
),
|
||||||
ast::ItemKind::Const(c) => (
|
ast::ItemKind::Const(c) => (
|
||||||
Some(c.defaultness),
|
Some(c.defaultness),
|
||||||
"const",
|
if c.rhs_kind.is_type_const() {
|
||||||
|
"type const"
|
||||||
|
} else {
|
||||||
|
"const"
|
||||||
|
},
|
||||||
ast::Safety::Default,
|
ast::Safety::Default,
|
||||||
c.ident,
|
c.ident,
|
||||||
&c.ty,
|
&c.ty,
|
||||||
ast::Mutability::Not,
|
ast::Mutability::Not,
|
||||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
c.rhs_kind.expr(),
|
||||||
Some(&c.generics),
|
Some(&c.generics),
|
||||||
),
|
),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
@ -2053,17 +2057,25 @@ impl<'a> StaticParts<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
|
pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self {
|
||||||
let (defaultness, ty, expr_opt, generics) = match &ti.kind {
|
let (defaultness, ty, expr_opt, generics, prefix) = match &ti.kind {
|
||||||
ast::AssocItemKind::Const(c) => (
|
ast::AssocItemKind::Const(c) => {
|
||||||
c.defaultness,
|
let prefix = if c.rhs_kind.is_type_const() {
|
||||||
&c.ty,
|
"type const"
|
||||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
} else {
|
||||||
Some(&c.generics),
|
"const"
|
||||||
),
|
};
|
||||||
|
(
|
||||||
|
c.defaultness,
|
||||||
|
&c.ty,
|
||||||
|
c.rhs_kind.expr(),
|
||||||
|
Some(&c.generics),
|
||||||
|
prefix,
|
||||||
|
)
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
StaticParts {
|
StaticParts {
|
||||||
prefix: "const",
|
prefix,
|
||||||
safety: ast::Safety::Default,
|
safety: ast::Safety::Default,
|
||||||
vis: &ti.vis,
|
vis: &ti.vis,
|
||||||
ident,
|
ident,
|
||||||
|
|
@ -2077,17 +2089,25 @@ impl<'a> StaticParts<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
|
pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self {
|
||||||
let (defaultness, ty, expr_opt, generics) = match &ii.kind {
|
let (defaultness, ty, expr_opt, generics, prefix) = match &ii.kind {
|
||||||
ast::AssocItemKind::Const(c) => (
|
ast::AssocItemKind::Const(c) => {
|
||||||
c.defaultness,
|
let prefix = if c.rhs_kind.is_type_const() {
|
||||||
&c.ty,
|
"type const"
|
||||||
c.rhs.as_ref().map(|rhs| rhs.expr()),
|
} else {
|
||||||
Some(&c.generics),
|
"const"
|
||||||
),
|
};
|
||||||
|
(
|
||||||
|
c.defaultness,
|
||||||
|
&c.ty,
|
||||||
|
c.rhs_kind.expr(),
|
||||||
|
Some(&c.generics),
|
||||||
|
prefix,
|
||||||
|
)
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
StaticParts {
|
StaticParts {
|
||||||
prefix: "const",
|
prefix,
|
||||||
safety: ast::Safety::Default,
|
safety: ast::Safety::Default,
|
||||||
vis: &ii.vis,
|
vis: &ii.vis,
|
||||||
ident,
|
ident,
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ struct Qux<'a> {
|
||||||
x: &'a (),
|
x: &'a (),
|
||||||
}
|
}
|
||||||
impl<'a> Qux<'a> {
|
impl<'a> Qux<'a> {
|
||||||
#[type_const]
|
type const LEN: usize = 4;
|
||||||
const LEN: usize = 4;
|
|
||||||
fn foo(_: [u8; Qux::LEN]) {}
|
fn foo(_: [u8; Qux::LEN]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,10 @@
|
||||||
#![expect(unused_variables, incomplete_features)]
|
#![expect(unused_variables, incomplete_features)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
impl Trait for () {
|
impl Trait for () {
|
||||||
#[type_const]
|
type const N: usize = 101;
|
||||||
const N: usize = 101;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ pub enum ParseMode {
|
||||||
Raw,
|
Raw,
|
||||||
}
|
}
|
||||||
pub trait Parse {
|
pub trait Parse {
|
||||||
#[type_const]
|
type const PARSE_MODE: ParseMode;
|
||||||
const PARSE_MODE: ParseMode;
|
|
||||||
}
|
}
|
||||||
pub trait RenderRaw {}
|
pub trait RenderRaw {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,5 @@
|
||||||
pub fn accept(_: impl Trait<K = 0>) {}
|
pub fn accept(_: impl Trait<K = 0>) {}
|
||||||
|
|
||||||
pub trait Trait {
|
pub trait Trait {
|
||||||
#[type_const]
|
type const K: i32;
|
||||||
const K: i32;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ trait T {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait S {
|
trait S {
|
||||||
#[type_const]
|
type const C: i32;
|
||||||
const C: i32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
pub trait Trait {
|
pub trait Trait {
|
||||||
#[type_const]
|
type const ASSOC: usize;
|
||||||
const ASSOC: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn foo<
|
pub fn foo<
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@
|
||||||
struct OnDiskDirEntry<'a>(&'a ());
|
struct OnDiskDirEntry<'a>(&'a ());
|
||||||
|
|
||||||
impl<'a> OnDiskDirEntry<'a> {
|
impl<'a> OnDiskDirEntry<'a> {
|
||||||
#[type_const]
|
type const LFN_FRAGMENT_LEN: i64 = 2;
|
||||||
const LFN_FRAGMENT_LEN: i64 = 2;
|
|
||||||
|
|
||||||
fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
|
fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
|
||||||
//~^ ERROR the constant `2` is not of type `usize`
|
//~^ 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
|
= note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information
|
||||||
|
|
||||||
error: the constant `2` is not of type `usize`
|
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] {
|
LL | fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64`
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@
|
||||||
// Test case from #138226: generic impl with multiple type parameters
|
// Test case from #138226: generic impl with multiple type parameters
|
||||||
struct Foo<A, B>(A, B);
|
struct Foo<A, B>(A, B);
|
||||||
impl<A, B> Foo<A, B> {
|
impl<A, B> Foo<A, B> {
|
||||||
#[type_const]
|
type const LEN: usize = 4;
|
||||||
const LEN: usize = 4;
|
|
||||||
|
|
||||||
fn foo() {
|
fn foo() {
|
||||||
let _ = [5; Self::LEN];
|
let _ = [5; Self::LEN];
|
||||||
|
|
@ -19,8 +18,7 @@ impl<A, B> Foo<A, B> {
|
||||||
// Test case from #138226: generic impl with const parameter
|
// Test case from #138226: generic impl with const parameter
|
||||||
struct Bar<const N: usize>;
|
struct Bar<const N: usize>;
|
||||||
impl<const N: usize> Bar<N> {
|
impl<const N: usize> Bar<N> {
|
||||||
#[type_const]
|
type const LEN: usize = 4;
|
||||||
const LEN: usize = 4;
|
|
||||||
|
|
||||||
fn bar() {
|
fn bar() {
|
||||||
let _ = [0; Self::LEN];
|
let _ = [0; Self::LEN];
|
||||||
|
|
@ -30,8 +28,7 @@ impl<const N: usize> Bar<N> {
|
||||||
// Test case from #150960: non-generic impl with const block
|
// Test case from #150960: non-generic impl with const block
|
||||||
struct Baz;
|
struct Baz;
|
||||||
impl Baz {
|
impl Baz {
|
||||||
#[type_const]
|
type const LEN: usize = 4;
|
||||||
const LEN: usize = 4;
|
|
||||||
|
|
||||||
fn baz() {
|
fn baz() {
|
||||||
let _ = [0; { Self::LEN }];
|
let _ = [0; { Self::LEN }];
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,7 @@ fn mismatch_2() -> impl Iterator<Item: Copy, Item: Send> {
|
||||||
trait Trait {
|
trait Trait {
|
||||||
type Gat<T>;
|
type Gat<T>;
|
||||||
|
|
||||||
#[type_const]
|
type const ASSOC: i32;
|
||||||
const ASSOC: i32;
|
|
||||||
|
|
||||||
fn foo() -> impl Sized;
|
fn foo() -> impl Sized;
|
||||||
}
|
}
|
||||||
|
|
@ -59,8 +58,7 @@ trait Trait {
|
||||||
impl Trait for () {
|
impl Trait for () {
|
||||||
type Gat<T> = ();
|
type Gat<T> = ();
|
||||||
|
|
||||||
#[type_const]
|
type const ASSOC: i32 = 3;
|
||||||
const ASSOC: i32 = 3;
|
|
||||||
|
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
}
|
}
|
||||||
|
|
@ -68,8 +66,7 @@ impl Trait for () {
|
||||||
impl Trait for u32 {
|
impl Trait for u32 {
|
||||||
type Gat<T> = ();
|
type Gat<T> = ();
|
||||||
|
|
||||||
#[type_const]
|
type const ASSOC: i32 = 4;
|
||||||
const ASSOC: i32 = 4;
|
|
||||||
|
|
||||||
fn foo() -> u32 {
|
fn foo() -> u32 {
|
||||||
42
|
42
|
||||||
|
|
@ -89,8 +86,7 @@ type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||||
//~| ERROR conflicting associated type bindings
|
//~| ERROR conflicting associated type bindings
|
||||||
|
|
||||||
trait Trait2 {
|
trait Trait2 {
|
||||||
#[type_const]
|
type const ASSOC: u32;
|
||||||
const ASSOC: u32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
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
|
| ----------------------- 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`
|
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> {
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `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
|
| ------------------ 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`
|
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> {
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||||
|
|
|
|
||||||
note: required by a bound in `Trait3::foo::{anon_assoc#0}`
|
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>;
|
LL | fn foo() -> impl Iterator<Item = i32, Item = u32>;
|
||||||
| ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}`
|
| ^^^^^^^^^^ 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
|
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>;
|
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||||
| ---------- ^^^^^^^^^^ re-bound here
|
| ---------- ^^^^^^^^^^ re-bound here
|
||||||
|
|
@ -129,7 +129,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||||
| `Item` bound here first
|
| `Item` bound here first
|
||||||
|
|
||||||
error: conflicting associated type bindings for `Item`
|
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>;
|
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
|
| `Item` is specified to be `i32` here
|
||||||
|
|
||||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
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>;
|
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||||
|
|
@ -146,7 +146,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||||
| `ASSOC` bound here first
|
| `ASSOC` bound here first
|
||||||
|
|
||||||
error: conflicting associated constant bindings for `ASSOC`
|
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>;
|
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
|
| `ASSOC` is specified to be `3` here
|
||||||
|
|
||||||
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
|
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>;
|
LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
||||||
| ---------- ^^^^^^^^^^ re-bound here
|
| ---------- ^^^^^^^^^^ re-bound here
|
||||||
|
|
@ -163,7 +163,7 @@ LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
||||||
| `Item` bound here first
|
| `Item` bound here first
|
||||||
|
|
||||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
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>;
|
LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
||||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||||
|
|
@ -171,7 +171,7 @@ LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
||||||
| `ASSOC` bound here first
|
| `ASSOC` bound here first
|
||||||
|
|
||||||
error[E0271]: expected `Empty<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
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>());
|
LL | uncallable(iter::empty::<u32>());
|
||||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||||
|
|
@ -179,13 +179,13 @@ LL | uncallable(iter::empty::<u32>());
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
note: required by a bound in `uncallable`
|
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>) {}
|
LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
||||||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||||
|
|
||||||
error[E0271]: expected `Empty<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
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>());
|
LL | uncallable(iter::empty::<i32>());
|
||||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
|
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
|
||||||
|
|
@ -193,13 +193,13 @@ LL | uncallable(iter::empty::<i32>());
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
note: required by a bound in `uncallable`
|
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>) {}
|
LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
||||||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
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(());
|
LL | uncallable_const(());
|
||||||
| ---------------- ^^ expected `4`, found `3`
|
| ---------------- ^^ expected `4`, found `3`
|
||||||
|
|
@ -209,13 +209,13 @@ LL | uncallable_const(());
|
||||||
= note: expected constant `4`
|
= note: expected constant `4`
|
||||||
found constant `3`
|
found constant `3`
|
||||||
note: required by a bound in `uncallable_const`
|
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>) {}
|
LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
||||||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
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);
|
LL | uncallable_const(4u32);
|
||||||
| ---------------- ^^^^ expected `3`, found `4`
|
| ---------------- ^^^^ expected `3`, found `4`
|
||||||
|
|
@ -225,13 +225,13 @@ LL | uncallable_const(4u32);
|
||||||
= note: expected constant `3`
|
= note: expected constant `3`
|
||||||
found constant `4`
|
found constant `4`
|
||||||
note: required by a bound in `uncallable_const`
|
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>) {}
|
LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
||||||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
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(());
|
LL | uncallable_rtn(());
|
||||||
| -------------- ^^ expected `4`, found `3`
|
| -------------- ^^ expected `4`, found `3`
|
||||||
|
|
@ -241,7 +241,7 @@ LL | uncallable_rtn(());
|
||||||
= note: expected constant `4`
|
= note: expected constant `4`
|
||||||
found constant `3`
|
found constant `3`
|
||||||
note: required by a bound in `uncallable_rtn`
|
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(
|
LL | fn uncallable_rtn(
|
||||||
| -------------- required by a bound in this function
|
| -------------- 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`
|
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
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);
|
LL | uncallable_rtn(17u32);
|
||||||
| -------------- ^^^^^ expected `3`, found `4`
|
| -------------- ^^^^^ expected `3`, found `4`
|
||||||
|
|
@ -259,7 +259,7 @@ LL | uncallable_rtn(17u32);
|
||||||
= note: expected constant `3`
|
= note: expected constant `3`
|
||||||
found constant `4`
|
found constant `4`
|
||||||
note: required by a bound in `uncallable_rtn`
|
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(
|
LL | fn uncallable_rtn(
|
||||||
| -------------- required by a bound in this function
|
| -------------- required by a bound in this function
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,7 @@ trait Tra3 {
|
||||||
trait Trait {
|
trait Trait {
|
||||||
type Gat<T>;
|
type Gat<T>;
|
||||||
|
|
||||||
#[type_const]
|
type const ASSOC: i32;
|
||||||
const ASSOC: i32;
|
|
||||||
|
|
||||||
fn foo() -> impl Sized;
|
fn foo() -> impl Sized;
|
||||||
}
|
}
|
||||||
|
|
@ -198,8 +197,7 @@ trait Trait {
|
||||||
impl Trait for () {
|
impl Trait for () {
|
||||||
type Gat<T> = ();
|
type Gat<T> = ();
|
||||||
|
|
||||||
#[type_const]
|
type const ASSOC: i32 = 3;
|
||||||
const ASSOC: i32 = 3;
|
|
||||||
|
|
||||||
fn foo() {}
|
fn foo() {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
struct S<const N: usize>;
|
struct S<const N: usize>;
|
||||||
impl<const N: usize> S<N> {
|
impl<const N: usize> S<N> {
|
||||||
#[type_const]
|
type const LEN: usize = 1;
|
||||||
//~^ ERROR: the `#[type_const]` attribute is an experimental feature
|
//~^ ERROR: associated `type const` are unstable [E0658]
|
||||||
const LEN: usize = 1;
|
//~| ERROR: `type const` syntax is experimental [E0658]
|
||||||
fn arr() {
|
fn arr() {
|
||||||
[8; Self::LEN]
|
[8; Self::LEN]
|
||||||
//~^ WARN: cannot use constants which depend on generic parameters in types
|
//~^ 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
|
--> $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
|
= 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
|
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||||
|
|
@ -36,7 +46,7 @@ LL | fn arr() {
|
||||||
LL | [8; Self::LEN]
|
LL | [8; Self::LEN]
|
||||||
| ^^^^^^^^^^^^^^ expected `()`, found `[{integer}; 1]`
|
| ^^^^^^^^^^^^^^ 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.
|
Some errors have detailed explanations: E0308, E0658.
|
||||||
For more information about an error, try `rustc --explain E0308`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,6 @@ struct Test;
|
||||||
#[diagnostic::on_unimplemented = 1]
|
#[diagnostic::on_unimplemented = 1]
|
||||||
//~^ WARN malformed
|
//~^ WARN malformed
|
||||||
trait Hey {
|
trait Hey {
|
||||||
#[type_const = 1]
|
|
||||||
//~^ ERROR malformed
|
|
||||||
const HEY: usize = 5;
|
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>
|
= 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`
|
error[E0463]: can't find crate for `wloop`
|
||||||
--> $DIR/malformed-attrs.rs:217:1
|
--> $DIR/malformed-attrs.rs:215:1
|
||||||
|
|
|
|
||||||
LL | extern crate wloop;
|
LL | extern crate wloop;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ can't find crate
|
| ^^^^^^^^^^^^^^^^^^^ can't find crate
|
||||||
|
|
||||||
error: malformed `allow` attribute input
|
error: malformed `allow` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:183:1
|
--> $DIR/malformed-attrs.rs:181:1
|
||||||
|
|
|
|
||||||
LL | #[allow]
|
LL | #[allow]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
@ -43,7 +43,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")]
|
||||||
| +++++++++++++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: malformed `expect` attribute input
|
error: malformed `expect` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:185:1
|
--> $DIR/malformed-attrs.rs:183:1
|
||||||
|
|
|
|
||||||
LL | #[expect]
|
LL | #[expect]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
@ -59,7 +59,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")]
|
||||||
| +++++++++++++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: malformed `warn` attribute input
|
error: malformed `warn` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:187:1
|
--> $DIR/malformed-attrs.rs:185:1
|
||||||
|
|
|
|
||||||
LL | #[warn]
|
LL | #[warn]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
@ -75,7 +75,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")]
|
||||||
| +++++++++++++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: malformed `deny` attribute input
|
error: malformed `deny` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:189:1
|
--> $DIR/malformed-attrs.rs:187:1
|
||||||
|
|
|
|
||||||
LL | #[deny]
|
LL | #[deny]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
@ -91,7 +91,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")]
|
||||||
| +++++++++++++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: malformed `forbid` attribute input
|
error: malformed `forbid` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:191:1
|
--> $DIR/malformed-attrs.rs:189:1
|
||||||
|
|
|
|
||||||
LL | #[forbid]
|
LL | #[forbid]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
@ -125,7 +125,7 @@ LL | #[proc_macro_derive]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
|
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]
|
LL | #[allow_internal_unsafe = 1]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -541,7 +541,7 @@ LL | #[cfi_encoding = ""]
|
||||||
| help: must be of the form: `#[cfi_encoding = "encoding"]`
|
| help: must be of the form: `#[cfi_encoding = "encoding"]`
|
||||||
|
|
||||||
error[E0565]: malformed `marker` attribute input
|
error[E0565]: malformed `marker` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:160:1
|
--> $DIR/malformed-attrs.rs:158:1
|
||||||
|
|
|
|
||||||
LL | #[marker = 3]
|
LL | #[marker = 3]
|
||||||
| ^^^^^^^^^---^
|
| ^^^^^^^^^---^
|
||||||
|
|
@ -550,7 +550,7 @@ LL | #[marker = 3]
|
||||||
| help: must be of the form: `#[marker]`
|
| help: must be of the form: `#[marker]`
|
||||||
|
|
||||||
error[E0565]: malformed `fundamental` attribute input
|
error[E0565]: malformed `fundamental` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:162:1
|
--> $DIR/malformed-attrs.rs:160:1
|
||||||
|
|
|
|
||||||
LL | #[fundamental()]
|
LL | #[fundamental()]
|
||||||
| ^^^^^^^^^^^^^--^
|
| ^^^^^^^^^^^^^--^
|
||||||
|
|
@ -559,7 +559,7 @@ LL | #[fundamental()]
|
||||||
| help: must be of the form: `#[fundamental]`
|
| help: must be of the form: `#[fundamental]`
|
||||||
|
|
||||||
error[E0565]: malformed `ffi_pure` attribute input
|
error[E0565]: malformed `ffi_pure` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:170:5
|
--> $DIR/malformed-attrs.rs:168:5
|
||||||
|
|
|
|
||||||
LL | #[unsafe(ffi_pure = 1)]
|
LL | #[unsafe(ffi_pure = 1)]
|
||||||
| ^^^^^^^^^^^^^^^^^^---^^
|
| ^^^^^^^^^^^^^^^^^^---^^
|
||||||
|
|
@ -568,7 +568,7 @@ LL | #[unsafe(ffi_pure = 1)]
|
||||||
| help: must be of the form: `#[ffi_pure]`
|
| help: must be of the form: `#[ffi_pure]`
|
||||||
|
|
||||||
error[E0539]: malformed `link_ordinal` attribute input
|
error[E0539]: malformed `link_ordinal` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:172:5
|
--> $DIR/malformed-attrs.rs:170:5
|
||||||
|
|
|
|
||||||
LL | #[link_ordinal]
|
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>
|
= 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
|
error[E0565]: malformed `ffi_const` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:176:5
|
--> $DIR/malformed-attrs.rs:174:5
|
||||||
|
|
|
|
||||||
LL | #[unsafe(ffi_const = 1)]
|
LL | #[unsafe(ffi_const = 1)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^---^^
|
| ^^^^^^^^^^^^^^^^^^^---^^
|
||||||
|
|
@ -588,13 +588,13 @@ LL | #[unsafe(ffi_const = 1)]
|
||||||
| help: must be of the form: `#[ffi_const]`
|
| help: must be of the form: `#[ffi_const]`
|
||||||
|
|
||||||
error[E0539]: malformed `linkage` attribute input
|
error[E0539]: malformed `linkage` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:178:5
|
--> $DIR/malformed-attrs.rs:176:5
|
||||||
|
|
|
|
||||||
LL | #[linkage]
|
LL | #[linkage]
|
||||||
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
|
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
|
||||||
|
|
||||||
error[E0539]: malformed `debugger_visualizer` attribute input
|
error[E0539]: malformed `debugger_visualizer` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:193:1
|
--> $DIR/malformed-attrs.rs:191:1
|
||||||
|
|
|
|
||||||
LL | #[debugger_visualizer]
|
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>
|
= 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
|
error[E0565]: malformed `automatically_derived` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:195:1
|
--> $DIR/malformed-attrs.rs:193:1
|
||||||
|
|
|
|
||||||
LL | #[automatically_derived = 18]
|
LL | #[automatically_derived = 18]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^----^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^----^
|
||||||
|
|
@ -614,7 +614,7 @@ LL | #[automatically_derived = 18]
|
||||||
| help: must be of the form: `#[automatically_derived]`
|
| help: must be of the form: `#[automatically_derived]`
|
||||||
|
|
||||||
error[E0565]: malformed `non_exhaustive` attribute input
|
error[E0565]: malformed `non_exhaustive` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:203:1
|
--> $DIR/malformed-attrs.rs:201:1
|
||||||
|
|
|
|
||||||
LL | #[non_exhaustive = 1]
|
LL | #[non_exhaustive = 1]
|
||||||
| ^^^^^^^^^^^^^^^^^---^
|
| ^^^^^^^^^^^^^^^^^---^
|
||||||
|
|
@ -623,7 +623,7 @@ LL | #[non_exhaustive = 1]
|
||||||
| help: must be of the form: `#[non_exhaustive]`
|
| help: must be of the form: `#[non_exhaustive]`
|
||||||
|
|
||||||
error[E0565]: malformed `thread_local` attribute input
|
error[E0565]: malformed `thread_local` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:209:1
|
--> $DIR/malformed-attrs.rs:207:1
|
||||||
|
|
|
|
||||||
LL | #[thread_local()]
|
LL | #[thread_local()]
|
||||||
| ^^^^^^^^^^^^^^--^
|
| ^^^^^^^^^^^^^^--^
|
||||||
|
|
@ -632,7 +632,7 @@ LL | #[thread_local()]
|
||||||
| help: must be of the form: `#[thread_local]`
|
| help: must be of the form: `#[thread_local]`
|
||||||
|
|
||||||
error[E0565]: malformed `no_link` attribute input
|
error[E0565]: malformed `no_link` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:213:1
|
--> $DIR/malformed-attrs.rs:211:1
|
||||||
|
|
|
|
||||||
LL | #[no_link()]
|
LL | #[no_link()]
|
||||||
| ^^^^^^^^^--^
|
| ^^^^^^^^^--^
|
||||||
|
|
@ -641,7 +641,7 @@ LL | #[no_link()]
|
||||||
| help: must be of the form: `#[no_link]`
|
| help: must be of the form: `#[no_link]`
|
||||||
|
|
||||||
error[E0539]: malformed `macro_use` attribute input
|
error[E0539]: malformed `macro_use` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:215:1
|
--> $DIR/malformed-attrs.rs:213:1
|
||||||
|
|
|
|
||||||
LL | #[macro_use = 1]
|
LL | #[macro_use = 1]
|
||||||
| ^^^^^^^^^^^^---^
|
| ^^^^^^^^^^^^---^
|
||||||
|
|
@ -659,7 +659,7 @@ LL + #[macro_use]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0539]: malformed `macro_export` attribute input
|
error[E0539]: malformed `macro_export` attribute input
|
||||||
--> $DIR/malformed-attrs.rs:220:1
|
--> $DIR/malformed-attrs.rs:218:1
|
||||||
|
|
|
|
||||||
LL | #[macro_export = 18]
|
LL | #[macro_export = 18]
|
||||||
| ^^^^^^^^^^^^^^^----^
|
| ^^^^^^^^^^^^^^^----^
|
||||||
|
|
@ -676,7 +676,7 @@ LL + #[macro_export]
|
||||||
|
|
|
|
||||||
|
|
||||||
error[E0565]: malformed `allow_internal_unsafe` attribute input
|
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]
|
LL | #[allow_internal_unsafe = 1]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^---^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^---^
|
||||||
|
|
@ -684,15 +684,6 @@ LL | #[allow_internal_unsafe = 1]
|
||||||
| | didn't expect any arguments here
|
| | didn't expect any arguments here
|
||||||
| help: must be of the form: `#[allow_internal_unsafe]`
|
| 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`
|
error: attribute should be applied to `const fn`
|
||||||
--> $DIR/malformed-attrs.rs:32:1
|
--> $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
|
= help: `#[no_implicit_prelude]` can be applied to crates and modules
|
||||||
|
|
||||||
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
|
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()]
|
LL | #[diagnostic::do_not_recommend()]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: `#[automatically_derived]` attribute cannot be used on modules
|
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]
|
LL | #[automatically_derived = 18]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
@ -835,7 +826,7 @@ LL | #[automatically_derived = 18]
|
||||||
= help: `#[automatically_derived]` can only be applied to trait impl blocks
|
= help: `#[automatically_derived]` can only be applied to trait impl blocks
|
||||||
|
|
||||||
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
|
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]
|
LL | #[ignore = 1]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
@ -854,7 +845,7 @@ LL | #[coroutine = 63] || {}
|
||||||
= note: expected unit type `()`
|
= note: expected unit type `()`
|
||||||
found coroutine `{coroutine@$DIR/malformed-attrs.rs:116:23: 116:25}`
|
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.
|
Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805.
|
||||||
For more information about an error, try `rustc --explain E0308`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
@ -882,7 +873,7 @@ LL | #[ignore()]
|
||||||
|
|
||||||
Future breakage diagnostic:
|
Future breakage diagnostic:
|
||||||
error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
|
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]
|
LL | #[ignore = 1]
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
trait Trait0: Parent0<i32> + Parent0<u32> {}
|
trait Trait0: Parent0<i32> + Parent0<u32> {}
|
||||||
trait Parent0<T> {
|
trait Parent0<T> {
|
||||||
#[type_const]
|
type const K: ();
|
||||||
const K: ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take0(_: impl Trait0<K = const { }>) {}
|
fn take0(_: impl Trait0<K = const { }>) {}
|
||||||
|
|
@ -15,12 +14,10 @@ fn take0(_: impl Trait0<K = const { }>) {}
|
||||||
|
|
||||||
trait Trait1: Parent1 + Parent2 {}
|
trait Trait1: Parent1 + Parent2 {}
|
||||||
trait Parent1 {
|
trait Parent1 {
|
||||||
#[type_const]
|
type const C: i32;
|
||||||
const C: i32;
|
|
||||||
}
|
}
|
||||||
trait Parent2 {
|
trait Parent2 {
|
||||||
#[type_const]
|
type const C: &'static str;
|
||||||
const C: &'static str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take1(_: impl Trait1<C = "?">) {}
|
fn take1(_: impl Trait1<C = "?">) {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0222]: ambiguous associated constant `K` in bounds of `Trait0`
|
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<u32>`
|
||||||
| ambiguous `K` from `Parent0<i32>`
|
| ambiguous `K` from `Parent0<i32>`
|
||||||
|
|
@ -17,13 +17,13 @@ LL | fn take0(_: impl Trait0<K = const { }>) {}
|
||||||
T: Parent0<i32>::K = const { }
|
T: Parent0<i32>::K = const { }
|
||||||
|
|
||||||
error[E0222]: ambiguous associated constant `C` in bounds of `Trait1`
|
error[E0222]: ambiguous associated constant `C` in bounds of `Trait1`
|
||||||
--> $DIR/ambiguity.rs:26:25
|
--> $DIR/ambiguity.rs:23:25
|
||||||
|
|
|
|
||||||
LL | const C: i32;
|
LL | type const C: i32;
|
||||||
| ------------ ambiguous `C` from `Parent1`
|
| ----------------- ambiguous `C` from `Parent1`
|
||||||
...
|
...
|
||||||
LL | const C: &'static str;
|
LL | type const C: &'static str;
|
||||||
| --------------------- ambiguous `C` from `Parent2`
|
| -------------------------- ambiguous `C` from `Parent2`
|
||||||
...
|
...
|
||||||
LL | fn take1(_: impl Trait1<C = "?">) {}
|
LL | fn take1(_: impl Trait1<C = "?">) {}
|
||||||
| ^^^^^^^ ambiguous associated constant `C`
|
| ^^^^^^^ ambiguous associated constant `C`
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,13 @@
|
||||||
#![allow(unused, incomplete_features)]
|
#![allow(unused, incomplete_features)]
|
||||||
|
|
||||||
pub trait Foo {
|
pub trait Foo {
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Bar;
|
pub struct Bar;
|
||||||
|
|
||||||
impl Foo for Bar {
|
impl Foo for Bar {
|
||||||
#[type_const]
|
type const N: usize = 3;
|
||||||
const N: usize = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST: usize = 3;
|
const TEST: usize = 3;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@
|
||||||
use std::marker::ConstParamTy_;
|
use std::marker::ConstParamTy_;
|
||||||
|
|
||||||
trait Trait<T: ConstParamTy_> {
|
trait Trait<T: ConstParamTy_> {
|
||||||
#[type_const]
|
type const K: T;
|
||||||
const K: T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take(
|
fn take(
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
error: higher-ranked subtype error
|
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 { () }
|
LL | K = const { () }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
||||||
error: higher-ranked subtype error
|
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 { () }
|
LL | K = const { () }
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@
|
||||||
use std::marker::ConstParamTy_;
|
use std::marker::ConstParamTy_;
|
||||||
|
|
||||||
trait Trait<T: ConstParamTy_> {
|
trait Trait<T: ConstParamTy_> {
|
||||||
#[type_const]
|
type const K: T;
|
||||||
const K: T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take(
|
fn take(
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,11 @@ trait Trait: SuperTrait {
|
||||||
type N;
|
type N;
|
||||||
type Q;
|
type Q;
|
||||||
|
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SuperTrait {
|
trait SuperTrait {
|
||||||
#[type_const]
|
type const Q: &'static str;
|
||||||
const Q: &'static str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take0(_: impl Trait<N = 0, N = ()>) {}
|
fn take0(_: impl Trait<N = 0, N = ()>) {}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,10 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
pub trait IsVoid {
|
pub trait IsVoid {
|
||||||
#[type_const]
|
type const IS_VOID: bool;
|
||||||
const IS_VOID: bool;
|
|
||||||
}
|
}
|
||||||
impl IsVoid for () {
|
impl IsVoid for () {
|
||||||
#[type_const]
|
type const IS_VOID: bool = true;
|
||||||
const IS_VOID: bool = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Maybe {}
|
pub trait Maybe {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0119]: conflicting implementations of trait `Maybe` for type `()`
|
error[E0119]: conflicting implementations of trait `Maybe` for type `()`
|
||||||
--> $DIR/coherence.rs:15:1
|
--> $DIR/coherence.rs:13:1
|
||||||
|
|
|
|
||||||
LL | impl Maybe for () {}
|
LL | impl Maybe for () {}
|
||||||
| ----------------- first implementation here
|
| ----------------- first implementation here
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
trait TraitWAssocConst {
|
trait TraitWAssocConst {
|
||||||
#[type_const]
|
type const A: usize;
|
||||||
const A: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn foo<T: TraitWAssocConst<A = 1>>() {}
|
fn foo<T: TraitWAssocConst<A = 1>>() {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
|
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>();
|
LL | foo::<T>();
|
||||||
| ^ expected `1`, found `0`
|
| ^ expected `1`, found `0`
|
||||||
|
|
@ -7,7 +7,7 @@ LL | foo::<T>();
|
||||||
= note: expected constant `1`
|
= note: expected constant `1`
|
||||||
found constant `0`
|
found constant `0`
|
||||||
note: required by a bound in `foo`
|
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>>() {}
|
LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
|
||||||
| ^^^^^ required by this bound in `foo`
|
| ^^^^^ required by this bound in `foo`
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
pub trait TraitA<T> {
|
pub trait TraitA<T> {
|
||||||
#[type_const]
|
type const K: u8 = 0;
|
||||||
const K: u8 = 0;
|
|
||||||
}
|
}
|
||||||
pub trait TraitB<T> {}
|
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
|
// 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
|
// 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.
|
// bounded by `PartialEq<Self>` and supertrait bounds cannot mention `Self` like this.
|
||||||
#[type_const]
|
type const K: Self where Self: std::marker::ConstParamTy_;
|
||||||
const K: Self where Self: std::marker::ConstParamTy_;
|
|
||||||
//~^ NOTE it contains associated const `K` whose type references the `Self` type
|
//~^ 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)
|
// 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.
|
// since the trait is not the principal trait or a supertrait thereof.
|
||||||
#[type_const]
|
type const Q: <Self as SomeOtherTrait>::Output;
|
||||||
const Q: <Self as SomeOtherTrait>::Output;
|
|
||||||
//~^ NOTE it contains associated const `Q` whose type references the `Self` type
|
//~^ 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
|
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;
|
LL | let _: dyn Trait;
|
||||||
| ^^^^^ `Trait` is not dyn compatible
|
| ^^^^^ `Trait` is not dyn compatible
|
||||||
|
|
|
|
||||||
note: for a trait to be dyn compatible it needs to allow building a vtable
|
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>
|
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 {
|
LL | trait Trait {
|
||||||
| ----- this trait is not dyn compatible...
|
| ----- this trait is not dyn compatible...
|
||||||
...
|
...
|
||||||
LL | const K: Self where Self: std::marker::ConstParamTy_;
|
LL | type const K: Self where Self: std::marker::ConstParamTy_;
|
||||||
| ^ ...because it contains associated const `K` whose type references the `Self` type
|
| ^ ...because it contains associated const `K` whose type references the `Self` type
|
||||||
...
|
...
|
||||||
LL | const Q: <Self as SomeOtherTrait>::Output;
|
LL | type const Q: <Self as SomeOtherTrait>::Output;
|
||||||
| ^ ...because it contains associated const `Q` whose type references the `Self` type
|
| ^ ...because it contains associated const `Q` whose type references the `Self` type
|
||||||
= help: consider moving `K` to another trait
|
= help: consider moving `K` to another trait
|
||||||
= help: consider moving `Q` to another trait
|
= help: consider moving `Q` to another trait
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,20 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
trait Trait: SuperTrait<C = 3> {
|
trait Trait: SuperTrait<C = 3> {
|
||||||
#[type_const]
|
type const K: usize;
|
||||||
const K: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait SuperTrait {
|
trait SuperTrait {
|
||||||
#[type_const]
|
type const Q: usize;
|
||||||
const Q: usize;
|
type const C: usize;
|
||||||
#[type_const]
|
|
||||||
const C: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bound {
|
trait Bound {
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bound for () {
|
impl Bound for () {
|
||||||
#[type_const]
|
type const N: usize = 10;
|
||||||
const N: usize = 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,11 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for () {
|
impl Trait for () {
|
||||||
#[type_const]
|
type const N: usize = 1;
|
||||||
const N: usize = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0271]: type mismatch resolving `<() as Trait>::N == 0`
|
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> = &();
|
LL | let _: &dyn Trait<N = 0> = &();
|
||||||
| ^^^ expected `0`, found `1`
|
| ^^^ expected `0`, found `1`
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,11 @@
|
||||||
trait X<const N: usize = { <Self as Y>::N }> {}
|
trait X<const N: usize = { <Self as Y>::N }> {}
|
||||||
|
|
||||||
trait Y {
|
trait Y {
|
||||||
#[type_const]
|
type const N: usize;
|
||||||
const N: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized> Y for T {
|
impl<T: ?Sized> Y for T {
|
||||||
#[type_const]
|
type const N: usize = 1;
|
||||||
const N: usize = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0393]: the const parameter `N` must be explicitly specified
|
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 }> {}
|
LL | trait X<const N: usize = { <Self as Y>::N }> {}
|
||||||
| -------------------------------------------- const parameter `N` must be specified for this
|
| -------------------------------------------- const parameter `N` must be specified for this
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
#[type_const]
|
type const Y: i32;
|
||||||
const Y: i32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Hold<T: ?Sized>(T);
|
struct Hold<T: ?Sized>(T);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
error: associated constant binding in trait object type mentions `Self`
|
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> }>;
|
LL | trait Bound = Trait<Y = { Hold::<Self> }>;
|
||||||
| -------------------- this binding mentions `Self`
|
| -------------------- this binding mentions `Self`
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,11 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
trait X: Y<K = { Self::Q }> {
|
trait X: Y<K = { Self::Q }> {
|
||||||
#[type_const]
|
type const Q: usize;
|
||||||
const Q: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Y {
|
trait Y {
|
||||||
#[type_const]
|
type const K: usize;
|
||||||
const K: usize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
error[E0191]: the value of the associated constant `K` in `Y` must be specified
|
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;
|
LL | type const K: usize;
|
||||||
| -------------- `K` defined here
|
| ------------------- `K` defined here
|
||||||
...
|
...
|
||||||
LL | let _: dyn X<Q = 10>;
|
LL | let _: dyn X<Q = 10>;
|
||||||
| ^^^^^^^^^ help: specify the associated constant: `X<Q = 10, K = /* CONST */>`
|
| ^^^^^^^^^ help: specify the associated constant: `X<Q = 10, K = /* CONST */>`
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
const K: usize;
|
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() {
|
fn main() {
|
||||||
|
|
@ -16,5 +16,5 @@ fn main() {
|
||||||
// Check that specifying the non-type assoc const doesn't "magically make it work".
|
// Check that specifying the non-type assoc const doesn't "magically make it work".
|
||||||
let _: dyn Trait<K = 0>;
|
let _: dyn Trait<K = 0>;
|
||||||
//~^ ERROR the trait `Trait` is not dyn compatible
|
//~^ 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 {
|
LL | trait Trait {
|
||||||
| ----- this trait is not dyn compatible...
|
| ----- this trait is not dyn compatible...
|
||||||
LL | const K: usize;
|
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
|
= 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
|
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:22
|
||||||
|
|
|
|
||||||
LL | let _: dyn Trait<K = 0>;
|
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
|
error[E0038]: the trait `Trait` is not dyn compatible
|
||||||
--> $DIR/dyn-compat-non-type-assoc-const.rs:17:16
|
--> $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 {
|
LL | trait Trait {
|
||||||
| ----- this trait is not dyn compatible...
|
| ----- this trait is not dyn compatible...
|
||||||
LL | const K: usize;
|
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
|
= help: consider moving `K` to another trait
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,11 @@
|
||||||
#![expect(incomplete_features)]
|
#![expect(incomplete_features)]
|
||||||
|
|
||||||
trait Trait {
|
trait Trait {
|
||||||
#[type_const]
|
type const N: i32 where Self: Bound;
|
||||||
const N: i32 where Self: Bound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for () {
|
impl Trait for () {
|
||||||
#[type_const]
|
type const N: i32 = 0;
|
||||||
const N: i32 = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Bound {}
|
trait Bound {}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
error[E0277]: the trait bound `(): Bound` is not satisfied
|
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> = &();
|
LL | let _: &dyn Trait<N = 0> = &();
|
||||||
| ^^^ the trait `Bound` is not implemented for `()`
|
| ^^^ the trait `Bound` is not implemented for `()`
|
||||||
|
|
|
|
||||||
help: this trait has no implementations, consider adding one
|
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 {}
|
LL | trait Bound {}
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
note: required by a bound in `Trait::N`
|
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;
|
LL | type const N: i32 where Self: Bound;
|
||||||
| ^^^^^ required by this bound in `Trait::N`
|
| ^^^^^ required by this bound in `Trait::N`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,12 @@
|
||||||
|
|
||||||
trait A {
|
trait A {
|
||||||
type Ty: std::marker::ConstParamTy_;
|
type Ty: std::marker::ConstParamTy_;
|
||||||
#[type_const]
|
type const CT: Self::Ty;
|
||||||
const CT: Self::Ty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl A for () {
|
impl A for () {
|
||||||
type Ty = i32;
|
type Ty = i32;
|
||||||
#[type_const]
|
type const CT: i32 = 0;
|
||||||
const CT: i32 = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
error[E0277]: the trait bound `FreshTy(0): A` is not satisfied
|
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>;
|
LL | let _: dyn A<Ty = i32, CT = 0>;
|
||||||
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
||||||
|
|
|
|
||||||
help: the trait `A` is implemented for `()`
|
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 () {
|
LL | impl A for () {
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `FreshTy(0): A` is not satisfied
|
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> = &();
|
LL | let _: &dyn A<Ty = i32, CT = 0> = &();
|
||||||
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
| ^ the trait `A` is not implemented for `FreshTy(0)`
|
||||||
|
|
|
|
||||||
help: the trait `A` is implemented for `()`
|
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 () {
|
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