Syntactically distinguish anon const const args
This commit is contained in:
parent
2a3a62d26e
commit
acc3a0e2da
48 changed files with 779 additions and 252 deletions
|
|
@ -141,16 +141,11 @@ impl Path {
|
|||
/// Check if this path is potentially a trivial const arg, i.e., one that can _potentially_
|
||||
/// be represented without an anon const in the HIR.
|
||||
///
|
||||
/// If `allow_mgca_arg` is true (as should be the case in most situations when
|
||||
/// `#![feature(min_generic_const_args)]` is enabled), then this always returns true
|
||||
/// because all paths are valid.
|
||||
///
|
||||
/// Otherwise, it returns true iff the path has exactly one segment, and it has no generic args
|
||||
/// Returns true iff the path has exactly one segment, and it has no generic args
|
||||
/// (i.e., it is _potentially_ a const parameter).
|
||||
#[tracing::instrument(level = "debug", ret)]
|
||||
pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
|
||||
allow_mgca_arg
|
||||
|| self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
|
||||
pub fn is_potential_trivial_const_arg(&self) -> bool {
|
||||
self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1385,6 +1380,15 @@ pub enum UnsafeSource {
|
|||
UserProvided,
|
||||
}
|
||||
|
||||
/// Track whether under `feature(min_generic_const_args)` this anon const
|
||||
/// was explicitly disambiguated as an anon const or not through the use of
|
||||
/// `const { ... }` syntax.
|
||||
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, Walkable)]
|
||||
pub enum MgcaDisambiguation {
|
||||
AnonConst,
|
||||
Direct,
|
||||
}
|
||||
|
||||
/// A constant (expression) that's not an item or associated item,
|
||||
/// but needs its own `DefId` for type-checking, const-eval, etc.
|
||||
/// These are usually found nested inside types (e.g., array lengths)
|
||||
|
|
@ -1394,6 +1398,7 @@ pub enum UnsafeSource {
|
|||
pub struct AnonConst {
|
||||
pub id: NodeId,
|
||||
pub value: Box<Expr>,
|
||||
pub mgca_disambiguation: MgcaDisambiguation,
|
||||
}
|
||||
|
||||
/// An expression.
|
||||
|
|
@ -1412,26 +1417,20 @@ impl Expr {
|
|||
///
|
||||
/// This will unwrap at most one block level (curly braces). After that, if the expression
|
||||
/// is a path, it mostly dispatches to [`Path::is_potential_trivial_const_arg`].
|
||||
/// See there for more info about `allow_mgca_arg`.
|
||||
///
|
||||
/// The only additional thing to note is that when `allow_mgca_arg` is false, this function
|
||||
/// will only allow paths with no qself, before dispatching to the `Path` function of
|
||||
/// the same name.
|
||||
/// This function will only allow paths with no qself, before dispatching to the `Path`
|
||||
/// function of the same name.
|
||||
///
|
||||
/// Does not ensure that the path resolves to a const param/item, the caller should check this.
|
||||
/// This also does not consider macros, so it's only correct after macro-expansion.
|
||||
pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
|
||||
pub fn is_potential_trivial_const_arg(&self) -> bool {
|
||||
let this = self.maybe_unwrap_block();
|
||||
if allow_mgca_arg {
|
||||
matches!(this.kind, ExprKind::Path(..))
|
||||
if let ExprKind::Path(None, path) = &this.kind
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
{
|
||||
true
|
||||
} else {
|
||||
if let ExprKind::Path(None, path) = &this.kind
|
||||
&& path.is_potential_trivial_const_arg(allow_mgca_arg)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -415,6 +415,7 @@ macro_rules! common_visitor_and_walkers {
|
|||
UnsafeBinderCastKind,
|
||||
BinOpKind,
|
||||
BlockCheckMode,
|
||||
MgcaDisambiguation,
|
||||
BorrowKind,
|
||||
BoundAsyncness,
|
||||
BoundConstness,
|
||||
|
|
|
|||
|
|
@ -489,7 +489,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
arg
|
||||
};
|
||||
|
||||
let anon_const = AnonConst { id: node_id, value: const_value };
|
||||
let anon_const = AnonConst {
|
||||
id: node_id,
|
||||
value: const_value,
|
||||
mgca_disambiguation: MgcaDisambiguation::AnonConst,
|
||||
};
|
||||
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
|
||||
} else {
|
||||
real_args.push(arg);
|
||||
|
|
|
|||
|
|
@ -1219,7 +1219,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
.and_then(|partial_res| partial_res.full_res())
|
||||
{
|
||||
if !res.matches_ns(Namespace::TypeNS)
|
||||
&& path.is_potential_trivial_const_arg(false)
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
{
|
||||
debug!(
|
||||
"lower_generic_arg: Lowering type argument as const argument: {:?}",
|
||||
|
|
@ -2287,11 +2287,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
) -> &'hir hir::ConstArg<'hir> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let ct_kind = if path
|
||||
.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
|
||||
&& (tcx.features().min_generic_const_args()
|
||||
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
|
||||
{
|
||||
let is_trivial_path = path.is_potential_trivial_const_arg()
|
||||
&& matches!(res, Res::Def(DefKind::ConstParam, _));
|
||||
let ct_kind = if is_trivial_path || tcx.features().min_generic_const_args() {
|
||||
let qpath = self.lower_qpath(
|
||||
ty_id,
|
||||
&None,
|
||||
|
|
@ -2370,6 +2368,53 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
fn lower_expr_to_const_arg_direct(&mut self, expr: &Expr) -> hir::ConstArg<'hir> {
|
||||
let overly_complex_const = |this: &mut Self| {
|
||||
let e = this.dcx().struct_span_err(
|
||||
expr.span,
|
||||
"complex const arguments must be placed inside of a `const` block",
|
||||
);
|
||||
|
||||
ConstArg { hir_id: this.next_id(), kind: hir::ConstArgKind::Error(expr.span, e.emit()) }
|
||||
};
|
||||
|
||||
match &expr.kind {
|
||||
ExprKind::Path(qself, path) => {
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
qself,
|
||||
path,
|
||||
ParamMode::Explicit,
|
||||
AllowReturnTypeNotation::No,
|
||||
// FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
||||
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Path(qpath) }
|
||||
}
|
||||
ExprKind::Underscore => ConstArg {
|
||||
hir_id: self.lower_node_id(expr.id),
|
||||
kind: hir::ConstArgKind::Infer(expr.span, ()),
|
||||
},
|
||||
ExprKind::Block(block, _) => {
|
||||
if let [stmt] = block.stmts.as_slice()
|
||||
&& let StmtKind::Expr(expr) = &stmt.kind
|
||||
&& matches!(
|
||||
expr.kind,
|
||||
ExprKind::Block(..) | ExprKind::Path(..) | ExprKind::Struct(..)
|
||||
)
|
||||
{
|
||||
return self.lower_expr_to_const_arg_direct(expr);
|
||||
}
|
||||
|
||||
overly_complex_const(self)
|
||||
}
|
||||
_ => overly_complex_const(self),
|
||||
}
|
||||
}
|
||||
|
||||
/// See [`hir::ConstArg`] for when to use this function vs
|
||||
/// [`Self::lower_anon_const_to_anon_const`].
|
||||
fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> &'hir hir::ConstArg<'hir> {
|
||||
|
|
@ -2379,6 +2424,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
#[instrument(level = "debug", skip(self))]
|
||||
fn lower_anon_const_to_const_arg_direct(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
// We cannot change parsing depending on feature gates available,
|
||||
// we can only require feature gates to be active as a delayed check.
|
||||
// Thus we just parse anon consts generally and make the real decision
|
||||
// making in ast lowering.
|
||||
// FIXME(min_generic_const_args): revisit once stable
|
||||
if tcx.features().min_generic_const_args() {
|
||||
return match anon.mgca_disambiguation {
|
||||
MgcaDisambiguation::AnonConst => {
|
||||
let lowered_anon = self.lower_anon_const_to_anon_const(anon);
|
||||
ConstArg { hir_id: self.next_id(), kind: hir::ConstArgKind::Anon(lowered_anon) }
|
||||
}
|
||||
MgcaDisambiguation::Direct => self.lower_expr_to_const_arg_direct(&anon.value),
|
||||
};
|
||||
}
|
||||
|
||||
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
|
||||
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
|
||||
let expr = if let ExprKind::Block(block, _) = &anon.value.kind
|
||||
|
|
@ -2390,12 +2451,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
} else {
|
||||
&anon.value
|
||||
};
|
||||
|
||||
let maybe_res =
|
||||
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
|
||||
if let ExprKind::Path(qself, path) = &expr.kind
|
||||
&& path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
|
||||
&& (tcx.features().min_generic_const_args()
|
||||
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
&& matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _)))
|
||||
{
|
||||
let qpath = self.lower_qpath(
|
||||
expr.id,
|
||||
|
|
@ -2403,7 +2464,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
path,
|
||||
ParamMode::Explicit,
|
||||
AllowReturnTypeNotation::No,
|
||||
// FIXME(mgca): update for `fn foo() -> Bar<FOO<impl Trait>>` support
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -517,6 +517,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
gate_all!(fn_delegation, "functions delegation is not yet fully implemented");
|
||||
gate_all!(postfix_match, "postfix match is experimental");
|
||||
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
|
||||
gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental");
|
||||
gate_all!(global_registration, "global registration is experimental");
|
||||
gate_all!(return_type_notation, "return type notation is experimental");
|
||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ mod llvm_enzyme {
|
|||
use rustc_ast::{
|
||||
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemKind, BindingMode,
|
||||
FnRetTy, FnSig, GenericArg, GenericArgs, GenericParamKind, Generics, ItemKind,
|
||||
MetaItemInner, PatKind, Path, PathSegment, TyKind, Visibility,
|
||||
MetaItemInner, MgcaDisambiguation, PatKind, Path, PathSegment, TyKind, Visibility,
|
||||
};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
|
|
@ -558,7 +558,11 @@ mod llvm_enzyme {
|
|||
}
|
||||
GenericParamKind::Const { .. } => {
|
||||
let expr = ecx.expr_path(ast::Path::from_ident(p.ident));
|
||||
let anon_const = AnonConst { id: ast::DUMMY_NODE_ID, value: expr };
|
||||
let anon_const = AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value: expr,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
};
|
||||
Some(AngleBracketedArg::Arg(GenericArg::Const(anon_const)))
|
||||
}
|
||||
GenericParamKind::Lifetime { .. } => None,
|
||||
|
|
@ -813,6 +817,7 @@ mod llvm_enzyme {
|
|||
let anon_const = rustc_ast::AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value: ecx.expr_usize(span, 1 + x.width as usize),
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
};
|
||||
TyKind::Array(ty.clone(), anon_const)
|
||||
};
|
||||
|
|
@ -827,6 +832,7 @@ mod llvm_enzyme {
|
|||
let anon_const = rustc_ast::AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value: ecx.expr_usize(span, x.width as usize),
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
};
|
||||
let kind = TyKind::Array(ty.clone(), anon_const);
|
||||
let ty =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
|
||||
use rustc_ast::{AnonConst, DUMMY_NODE_ID, MgcaDisambiguation, Ty, TyPat, TyPatKind, ast, token};
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
|
||||
use rustc_parse::exp;
|
||||
|
|
@ -60,8 +60,20 @@ fn ty_pat(kind: TyPatKind, span: Span) -> TyPat {
|
|||
fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> TyPat {
|
||||
let kind = match pat.kind {
|
||||
ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
|
||||
start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
end.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
|
||||
start.map(|value| {
|
||||
Box::new(AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
})
|
||||
}),
|
||||
end.map(|value| {
|
||||
Box::new(AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
})
|
||||
}),
|
||||
include_end,
|
||||
),
|
||||
ast::PatKind::Or(variants) => {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use rustc_ast::token::Delimiter;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::util::literal;
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind,
|
||||
UnOp, attr, token, tokenstream,
|
||||
self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind,
|
||||
MgcaDisambiguation, PatKind, UnOp, attr, token, tokenstream,
|
||||
};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
|
|
@ -101,6 +101,7 @@ impl<'a> ExtCtxt<'a> {
|
|||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
}),
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_ast::{self as ast, AsmMacro};
|
||||
use rustc_ast::{self as ast, AsmMacro, MgcaDisambiguation};
|
||||
use rustc_span::{Span, Symbol, kw};
|
||||
|
||||
use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos};
|
||||
|
|
@ -149,7 +149,7 @@ fn parse_asm_operand<'a>(
|
|||
let block = p.parse_block()?;
|
||||
ast::InlineAsmOperand::Label { block }
|
||||
} else if p.eat_keyword(exp!(Const)) {
|
||||
let anon_const = p.parse_expr_anon_const()?;
|
||||
let anon_const = p.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
|
||||
ast::InlineAsmOperand::Const { anon_const }
|
||||
} else if p.eat_keyword(exp!(Sym)) {
|
||||
let expr = p.parse_expr()?;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
|
|||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_ast::{
|
||||
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
|
||||
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat,
|
||||
PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
|
||||
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind,
|
||||
MgcaDisambiguation, Param, Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
@ -31,16 +31,15 @@ use crate::errors::{
|
|||
AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AttributeOnParamType,
|
||||
AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi,
|
||||
ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
|
||||
ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything,
|
||||
DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
|
||||
GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg,
|
||||
HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait,
|
||||
IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, PatternMethodParamWithoutBody,
|
||||
QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
|
||||
StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma,
|
||||
TernaryOperator, TernaryOperatorSuggestion, UnexpectedConstInGenericParam,
|
||||
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
|
||||
UseEqInstead, WrapType,
|
||||
DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound,
|
||||
ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets,
|
||||
GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition,
|
||||
InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse,
|
||||
PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst,
|
||||
StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt,
|
||||
SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion,
|
||||
UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
|
||||
UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType,
|
||||
};
|
||||
use crate::parser::FnContext;
|
||||
use crate::parser::attr::InnerAttrPolicy;
|
||||
|
|
@ -2558,36 +2557,6 @@ impl<'a> Parser<'a> {
|
|||
Ok(false) // Don't continue.
|
||||
}
|
||||
|
||||
/// Attempt to parse a generic const argument that has not been enclosed in braces.
|
||||
/// There are a limited number of expressions that are permitted without being encoded
|
||||
/// in braces:
|
||||
/// - Literals.
|
||||
/// - Single-segment paths (i.e. standalone generic const parameters).
|
||||
/// All other expressions that can be parsed will emit an error suggesting the expression be
|
||||
/// wrapped in braces.
|
||||
pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, Box<Expr>> {
|
||||
let start = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let (expr, _) =
|
||||
self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| {
|
||||
err.span_label(
|
||||
start.shrink_to_lo(),
|
||||
"while parsing a const generic argument starting here",
|
||||
);
|
||||
err
|
||||
})?;
|
||||
if !self.expr_is_valid_const_arg(&expr) {
|
||||
self.dcx().emit_err(ConstGenericWithoutBraces {
|
||||
span: expr.span,
|
||||
sugg: ConstGenericWithoutBracesSugg {
|
||||
left: expr.span.shrink_to_lo(),
|
||||
right: expr.span.shrink_to_hi(),
|
||||
},
|
||||
});
|
||||
}
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
|
||||
let snapshot = self.create_snapshot_for_diagnostic();
|
||||
let param = match self.parse_const_param(AttrVec::new()) {
|
||||
|
|
@ -2623,7 +2592,11 @@ impl<'a> Parser<'a> {
|
|||
self.dcx().emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg });
|
||||
|
||||
let value = self.mk_expr_err(param.span(), guar);
|
||||
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
|
||||
Some(GenericArg::Const(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
}))
|
||||
}
|
||||
|
||||
pub(super) fn recover_const_param_declaration(
|
||||
|
|
@ -2707,7 +2680,11 @@ impl<'a> Parser<'a> {
|
|||
);
|
||||
let guar = err.emit();
|
||||
let value = self.mk_expr_err(start.to(expr.span), guar);
|
||||
return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }));
|
||||
return Ok(GenericArg::Const(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
}));
|
||||
} else if snapshot.token == token::Colon
|
||||
&& expr.span.lo() == snapshot.token.span.hi()
|
||||
&& matches!(expr.kind, ExprKind::Path(..))
|
||||
|
|
@ -2776,7 +2753,11 @@ impl<'a> Parser<'a> {
|
|||
);
|
||||
let guar = err.emit();
|
||||
let value = self.mk_expr_err(span, guar);
|
||||
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||
GenericArg::Const(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
})
|
||||
}
|
||||
|
||||
/// Some special error handling for the "top-level" patterns in a match arm,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use rustc_ast::visit::{Visitor, walk_expr};
|
|||
use rustc_ast::{
|
||||
self as ast, AnonConst, Arm, AssignOp, AssignOpKind, AttrStyle, AttrVec, BinOp, BinOpKind,
|
||||
BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl,
|
||||
FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind,
|
||||
UnOp, UnsafeBinderCastKind, YieldKind,
|
||||
FnRetTy, Label, MacCall, MetaItemLit, MgcaDisambiguation, Movability, Param, RangeLimits,
|
||||
StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, YieldKind,
|
||||
};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
|
||||
|
|
@ -85,8 +85,15 @@ impl<'a> Parser<'a> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn parse_expr_anon_const(&mut self) -> PResult<'a, AnonConst> {
|
||||
self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
|
||||
pub fn parse_expr_anon_const(
|
||||
&mut self,
|
||||
mgca_disambiguation: impl FnOnce(&Self, &Expr) -> MgcaDisambiguation,
|
||||
) -> PResult<'a, AnonConst> {
|
||||
self.parse_expr().map(|value| AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
mgca_disambiguation: mgca_disambiguation(self, &value),
|
||||
value,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_expr_catch_underscore(
|
||||
|
|
@ -1615,7 +1622,18 @@ impl<'a> Parser<'a> {
|
|||
let first_expr = self.parse_expr()?;
|
||||
if self.eat(exp!(Semi)) {
|
||||
// Repeating array syntax: `[ 0; 512 ]`
|
||||
let count = self.parse_expr_anon_const()?;
|
||||
let count = if self.token.is_keyword(kw::Const)
|
||||
&& self.look_ahead(1, |t| *t == token::OpenBrace)
|
||||
{
|
||||
// While we could just disambiguate `Direct` from `AnonConst` by
|
||||
// treating all const block exprs as `AnonConst`, that would
|
||||
// complicate the DefCollector and likely all other visitors.
|
||||
// So we strip the const blockiness and just store it as a block
|
||||
// in the AST with the extra disambiguator on the AnonConst
|
||||
self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?
|
||||
} else {
|
||||
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
|
||||
};
|
||||
self.expect(close)?;
|
||||
ExprKind::Repeat(first_expr, count)
|
||||
} else if self.eat(exp!(Comma)) {
|
||||
|
|
|
|||
|
|
@ -1431,7 +1431,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let rhs = if self.eat(exp!(Eq)) {
|
||||
if attr::contains_name(attrs, sym::type_const) {
|
||||
Some(ConstItemRhs::TypeConst(self.parse_expr_anon_const()?))
|
||||
Some(ConstItemRhs::TypeConst(self.parse_const_arg()?))
|
||||
} else {
|
||||
Some(ConstItemRhs::Body(self.parse_expr()?))
|
||||
}
|
||||
|
|
@ -1650,8 +1650,11 @@ impl<'a> Parser<'a> {
|
|||
VariantData::Unit(DUMMY_NODE_ID)
|
||||
};
|
||||
|
||||
let disr_expr =
|
||||
if this.eat(exp!(Eq)) { Some(this.parse_expr_anon_const()?) } else { None };
|
||||
let disr_expr = if this.eat(exp!(Eq)) {
|
||||
Some(this.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let vr = ast::Variant {
|
||||
ident,
|
||||
|
|
@ -1864,7 +1867,7 @@ impl<'a> Parser<'a> {
|
|||
if p.token == token::Eq {
|
||||
let mut snapshot = p.create_snapshot_for_diagnostic();
|
||||
snapshot.bump();
|
||||
match snapshot.parse_expr_anon_const() {
|
||||
match snapshot.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst) {
|
||||
Ok(const_expr) => {
|
||||
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
|
||||
p.psess.gated_spans.gate(sym::default_field_values, sp);
|
||||
|
|
@ -2066,7 +2069,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
let default = if self.token == token::Eq {
|
||||
self.bump();
|
||||
let const_expr = self.parse_expr_anon_const()?;
|
||||
let const_expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
|
||||
let sp = ty.span.shrink_to_hi().to(const_expr.value.span);
|
||||
self.psess.gated_spans.gate(sym::default_field_values, sp);
|
||||
Some(const_expr)
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ use rustc_ast::tokenstream::{
|
|||
};
|
||||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::{
|
||||
self as ast, AnonConst, AttrArgs, AttrId, ByRef, Const, CoroutineKind, DUMMY_NODE_ID,
|
||||
DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, Mutability, Recovered, Safety, StrLit,
|
||||
Visibility, VisibilityKind,
|
||||
self as ast, AnonConst, AttrArgs, AttrId, BlockCheckMode, ByRef, Const, CoroutineKind,
|
||||
DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, Extern, HasAttrs, HasTokens, MgcaDisambiguation,
|
||||
Mutability, Recovered, Safety, StrLit, Visibility, VisibilityKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -727,7 +727,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn check_const_arg(&mut self) -> bool {
|
||||
self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const)
|
||||
let is_mcg_arg = self.check_or_expected(self.token.can_begin_const_arg(), TokenType::Const);
|
||||
let is_mgca_arg = self.is_keyword_ahead(0, &[kw::Const])
|
||||
&& self.look_ahead(1, |t| *t == token::OpenBrace);
|
||||
is_mcg_arg || is_mgca_arg
|
||||
}
|
||||
|
||||
fn check_const_closure(&self) -> bool {
|
||||
|
|
@ -1299,6 +1302,20 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_mgca_const_block(&mut self, gate_syntax: bool) -> PResult<'a, AnonConst> {
|
||||
self.expect_keyword(exp!(Const))?;
|
||||
let kw_span = self.token.span;
|
||||
let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?;
|
||||
if gate_syntax {
|
||||
self.psess.gated_spans.gate(sym::min_generic_const_args, kw_span.to(value.span));
|
||||
}
|
||||
Ok(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value,
|
||||
mgca_disambiguation: MgcaDisambiguation::AnonConst,
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses inline const expressions.
|
||||
fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
|
||||
self.expect_keyword(exp!(Const))?;
|
||||
|
|
@ -1306,6 +1323,7 @@ impl<'a> Parser<'a> {
|
|||
let anon_const = AnonConst {
|
||||
id: DUMMY_NODE_ID,
|
||||
value: self.mk_expr(blk.span, ExprKind::Block(blk, None)),
|
||||
mgca_disambiguation: MgcaDisambiguation::AnonConst,
|
||||
};
|
||||
let blk_span = anon_const.value.span;
|
||||
let kind = if pat {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ use ast::token::IdentIsRaw;
|
|||
use rustc_ast::token::{self, MetaVarKind, Token, TokenKind};
|
||||
use rustc_ast::{
|
||||
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
|
||||
AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
|
||||
Path, PathSegment, QSelf,
|
||||
AssocItemConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, MgcaDisambiguation,
|
||||
ParenthesizedArgs, Path, PathSegment, QSelf,
|
||||
};
|
||||
use rustc_errors::{Applicability, Diag, PResult};
|
||||
use rustc_span::{BytePos, Ident, Span, kw, sym};
|
||||
|
|
@ -16,12 +16,13 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
|
|||
use super::{Parser, Restrictions, TokenType};
|
||||
use crate::ast::{PatKind, TyKind};
|
||||
use crate::errors::{
|
||||
self, AttributeOnEmptyType, AttributeOnGenericArg, FnPathFoundNamedParams,
|
||||
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
|
||||
self, AttributeOnEmptyType, AttributeOnGenericArg, ConstGenericWithoutBraces,
|
||||
ConstGenericWithoutBracesSugg, FnPathFoundNamedParams, PathFoundAttributeInParams,
|
||||
PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
|
||||
};
|
||||
use crate::exp;
|
||||
use crate::parser::{
|
||||
CommaRecoveryMode, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
|
||||
CommaRecoveryMode, Expr, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
|
||||
};
|
||||
|
||||
/// Specifies how to parse a path.
|
||||
|
|
@ -870,12 +871,75 @@ impl<'a> Parser<'a> {
|
|||
/// the caller.
|
||||
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
|
||||
// Parse const argument.
|
||||
let value = if self.token.kind == token::OpenBrace {
|
||||
self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?
|
||||
let (value, mgca_disambiguation) = if self.token.kind == token::OpenBrace {
|
||||
let value = self.parse_expr_block(None, self.token.span, BlockCheckMode::Default)?;
|
||||
(value, MgcaDisambiguation::Direct)
|
||||
} else if self.token.is_keyword(kw::Const) {
|
||||
// While we could just disambiguate `Direct` from `AnonConst` by
|
||||
// treating all const block exprs as `AnonConst`, that would
|
||||
// complicate the DefCollector and likely all other visitors.
|
||||
// So we strip the const blockiness and just store it as a block
|
||||
// in the AST with the extra disambiguator on the AnonConst
|
||||
let value = self.parse_mgca_const_block(true)?;
|
||||
(value.value, MgcaDisambiguation::AnonConst)
|
||||
} else {
|
||||
self.handle_unambiguous_unbraced_const_arg()?
|
||||
self.parse_unambiguous_unbraced_const_arg()?
|
||||
};
|
||||
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
|
||||
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value, mgca_disambiguation })
|
||||
}
|
||||
|
||||
/// Attempt to parse a const argument that has not been enclosed in braces.
|
||||
/// There are a limited number of expressions that are permitted without being
|
||||
/// enclosed in braces:
|
||||
/// - Literals.
|
||||
/// - Single-segment paths (i.e. standalone generic const parameters).
|
||||
/// All other expressions that can be parsed will emit an error suggesting the expression be
|
||||
/// wrapped in braces.
|
||||
pub(super) fn parse_unambiguous_unbraced_const_arg(
|
||||
&mut self,
|
||||
) -> PResult<'a, (Box<Expr>, MgcaDisambiguation)> {
|
||||
let start = self.token.span;
|
||||
let attrs = self.parse_outer_attributes()?;
|
||||
let (expr, _) =
|
||||
self.parse_expr_res(Restrictions::CONST_EXPR, attrs).map_err(|mut err| {
|
||||
err.span_label(
|
||||
start.shrink_to_lo(),
|
||||
"while parsing a const generic argument starting here",
|
||||
);
|
||||
err
|
||||
})?;
|
||||
if !self.expr_is_valid_const_arg(&expr) {
|
||||
self.dcx().emit_err(ConstGenericWithoutBraces {
|
||||
span: expr.span,
|
||||
sugg: ConstGenericWithoutBracesSugg {
|
||||
left: expr.span.shrink_to_lo(),
|
||||
right: expr.span.shrink_to_hi(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
let mgca_disambiguation = self.mgca_direct_lit_hack(&expr);
|
||||
Ok((expr, mgca_disambiguation))
|
||||
}
|
||||
|
||||
/// Under `min_generic_const_args` we still allow *some* anon consts to be written without
|
||||
/// a `const` block as it makes things quite a lot nicer. This function is useful for contexts
|
||||
/// where we would like to use `MgcaDisambiguation::Direct` but need to fudge it to be `AnonConst`
|
||||
/// in the presence of literals.
|
||||
//
|
||||
/// FIXME(min_generic_const_args): In the long term it would be nice to have a way to directly
|
||||
/// represent literals in `hir::ConstArgKind` so that we can remove this special case by not
|
||||
/// needing an anon const.
|
||||
pub fn mgca_direct_lit_hack(&self, expr: &Expr) -> MgcaDisambiguation {
|
||||
match &expr.kind {
|
||||
ast::ExprKind::Lit(_) => MgcaDisambiguation::AnonConst,
|
||||
ast::ExprKind::Unary(ast::UnOp::Neg, expr)
|
||||
if matches!(expr.kind, ast::ExprKind::Lit(_)) =>
|
||||
{
|
||||
MgcaDisambiguation::AnonConst
|
||||
}
|
||||
_ => MgcaDisambiguation::Direct,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a generic argument in a path segment.
|
||||
|
|
@ -976,7 +1040,11 @@ impl<'a> Parser<'a> {
|
|||
GenericArg::Type(_) => GenericArg::Type(self.mk_ty(attr_span, TyKind::Err(guar))),
|
||||
GenericArg::Const(_) => {
|
||||
let error_expr = self.mk_expr(attr_span, ExprKind::Err(guar));
|
||||
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value: error_expr })
|
||||
GenericArg::Const(AnonConst {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
value: error_expr,
|
||||
mgca_disambiguation: MgcaDisambiguation::Direct,
|
||||
})
|
||||
}
|
||||
GenericArg::Lifetime(lt) => GenericArg::Lifetime(lt),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
|
|||
use rustc_ast::util::case::Case;
|
||||
use rustc_ast::{
|
||||
self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy,
|
||||
GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability,
|
||||
Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty,
|
||||
TyKind, UnsafeBinderTy,
|
||||
GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MgcaDisambiguation,
|
||||
MutTy, Mutability, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers,
|
||||
TraitObjectSyntax, Ty, TyKind, UnsafeBinderTy,
|
||||
};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{Applicability, Diag, E0516, PResult};
|
||||
|
|
@ -658,7 +658,19 @@ impl<'a> Parser<'a> {
|
|||
};
|
||||
|
||||
let ty = if self.eat(exp!(Semi)) {
|
||||
let mut length = self.parse_expr_anon_const()?;
|
||||
let mut length = if self.token.is_keyword(kw::Const)
|
||||
&& self.look_ahead(1, |t| *t == token::OpenBrace)
|
||||
{
|
||||
// While we could just disambiguate `Direct` from `AnonConst` by
|
||||
// treating all const block exprs as `AnonConst`, that would
|
||||
// complicate the DefCollector and likely all other visitors.
|
||||
// So we strip the const blockiness and just store it as a block
|
||||
// in the AST with the extra disambiguator on the AnonConst
|
||||
self.parse_mgca_const_block(false)?
|
||||
} else {
|
||||
self.parse_expr_anon_const(|this, expr| this.mgca_direct_lit_hack(expr))?
|
||||
};
|
||||
|
||||
if let Err(e) = self.expect(exp!(CloseBracket)) {
|
||||
// Try to recover from `X<Y, ...>` when `X::<Y, ...>` works
|
||||
self.check_mistyped_turbofish_with_multiple_type_params(e, &mut length.value)?;
|
||||
|
|
@ -699,8 +711,9 @@ impl<'a> Parser<'a> {
|
|||
_ = self.eat(exp!(Comma)) || self.eat(exp!(Colon)) || self.eat(exp!(Star));
|
||||
let suggestion_span = self.prev_token.span.with_lo(hi);
|
||||
|
||||
// FIXME(mgca): recovery is broken for `const {` args
|
||||
// we first try to parse pattern like `[u8 5]`
|
||||
let length = match self.parse_expr_anon_const() {
|
||||
let length = match self.parse_expr_anon_const(|_, _| MgcaDisambiguation::Direct) {
|
||||
Ok(length) => length,
|
||||
Err(e) => {
|
||||
e.cancel();
|
||||
|
|
@ -788,7 +801,7 @@ impl<'a> Parser<'a> {
|
|||
/// an error type.
|
||||
fn parse_typeof_ty(&mut self, lo: Span) -> PResult<'a, TyKind> {
|
||||
self.expect(exp!(OpenParen))?;
|
||||
let _expr = self.parse_expr_anon_const()?;
|
||||
let _expr = self.parse_expr_anon_const(|_, _| MgcaDisambiguation::AnonConst)?;
|
||||
self.expect(exp!(CloseParen))?;
|
||||
let span = lo.to(self.prev_token.span);
|
||||
let guar = self
|
||||
|
|
|
|||
|
|
@ -1222,7 +1222,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
|
|||
if let TyKind::Path(None, ref path) = ty.kind
|
||||
// We cannot disambiguate multi-segment paths right now as that requires type
|
||||
// checking.
|
||||
&& path.is_potential_trivial_const_arg(false)
|
||||
&& path.is_potential_trivial_const_arg()
|
||||
{
|
||||
let mut check_ns = |ns| {
|
||||
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
|
||||
|
|
@ -4840,9 +4840,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
constant, anon_const_kind
|
||||
);
|
||||
|
||||
let is_trivial_const_arg = constant
|
||||
.value
|
||||
.is_potential_trivial_const_arg(self.r.tcx.features().min_generic_const_args());
|
||||
let is_trivial_const_arg = if self.r.tcx.features().min_generic_const_args() {
|
||||
matches!(constant.mgca_disambiguation, MgcaDisambiguation::Direct)
|
||||
} else {
|
||||
constant.value.is_potential_trivial_const_arg()
|
||||
};
|
||||
|
||||
self.resolve_anon_const_manual(is_trivial_const_arg, anon_const_kind, |this| {
|
||||
this.resolve_expr(&constant.value, None)
|
||||
})
|
||||
|
|
@ -5023,9 +5026,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||
// Constant arguments need to be treated as AnonConst since
|
||||
// that is how they will be later lowered to HIR.
|
||||
if const_args.contains(&idx) {
|
||||
let is_trivial_const_arg = argument.is_potential_trivial_const_arg(
|
||||
self.r.tcx.features().min_generic_const_args(),
|
||||
);
|
||||
// FIXME(mgca): legacy const generics doesn't support mgca but maybe
|
||||
// that's okay.
|
||||
let is_trivial_const_arg = argument.is_potential_trivial_const_arg();
|
||||
self.resolve_anon_const_manual(
|
||||
is_trivial_const_arg,
|
||||
AnonConstKind::ConstArg(IsRepeatExpr::No),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ trait Parent0<T> {
|
|||
const K: ();
|
||||
}
|
||||
|
||||
fn take0(_: impl Trait0<K = { () }>) {}
|
||||
fn take0(_: impl Trait0<K = const { }>) {}
|
||||
//~^ ERROR ambiguous associated constant `K` in bounds of `Trait0`
|
||||
|
||||
trait Trait1: Parent1 + Parent2 {}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ LL | const K: ();
|
|||
| ambiguous `K` from `Parent0<u32>`
|
||||
| ambiguous `K` from `Parent0<i32>`
|
||||
...
|
||||
LL | fn take0(_: impl Trait0<K = { () }>) {}
|
||||
| ^^^^^^^^^^ ambiguous associated constant `K`
|
||||
LL | fn take0(_: impl Trait0<K = const { }>) {}
|
||||
| ^^^^^^^^^^^^^ ambiguous associated constant `K`
|
||||
|
|
||||
= help: consider introducing a new type parameter `T` and adding `where` constraints:
|
||||
where
|
||||
T: Trait0,
|
||||
T: Parent0<u32>::K = { () },
|
||||
T: Parent0<i32>::K = { () }
|
||||
T: Parent0<u32>::K = { },
|
||||
T: Parent0<i32>::K = { }
|
||||
|
||||
error[E0222]: ambiguous associated constant `C` in bounds of `Trait1`
|
||||
--> $DIR/assoc-const-eq-ambiguity.rs:26:25
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ trait Trait<T: ConstParamTy_> {
|
|||
fn take(
|
||||
_: impl Trait<
|
||||
<<for<'a> fn(&'a str) -> &'a str as Project>::Out as Discard>::Out,
|
||||
K = { () }
|
||||
K = const { () }
|
||||
>,
|
||||
) {}
|
||||
//~^^^ ERROR higher-ranked subtype error
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:19
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
LL | K = const { () }
|
||||
| ^^^^^^
|
||||
|
||||
error: higher-ranked subtype error
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:13
|
||||
--> $DIR/assoc-const-eq-bound-var-in-ty-not-wf.rs:21:19
|
||||
|
|
||||
LL | K = { () }
|
||||
| ^^^^^^
|
||||
LL | K = const { () }
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ trait Trait<T: ConstParamTy_> {
|
|||
fn take(
|
||||
_: impl Trait<
|
||||
<for<'a> fn(&'a str) -> &'a str as Discard>::Out,
|
||||
K = { () }
|
||||
K = const { }
|
||||
>,
|
||||
) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ trait Trait<'a> {
|
|||
const K: &'a ();
|
||||
}
|
||||
|
||||
fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
|
||||
fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {}
|
||||
//~^ ERROR the type of the associated constant `K` cannot capture late-bound generic parameters
|
||||
//~| NOTE its type cannot capture the late-bound lifetime parameter `'r`
|
||||
//~| NOTE the late-bound lifetime parameter `'r` is defined here
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
error: the type of the associated constant `K` cannot capture late-bound generic parameters
|
||||
--> $DIR/assoc-const-eq-esc-bound-var-in-ty.rs:11:35
|
||||
|
|
||||
LL | fn take(_: impl for<'r> Trait<'r, K = { &() }>) {}
|
||||
LL | fn take(_: impl for<'r> Trait<'r, K = const { &() }>) {}
|
||||
| -- ^ its type cannot capture the late-bound lifetime parameter `'r`
|
||||
| |
|
||||
| the late-bound lifetime parameter `'r` is defined here
|
||||
|
|
|
|||
|
|
@ -15,31 +15,33 @@ trait Trait<'a, T: 'a + ConstParamTy_, const N: usize> {
|
|||
const K: &'a [T; N];
|
||||
}
|
||||
|
||||
fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
//~| NOTE the lifetime parameter `'r` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the type parameter `A`
|
||||
//~| NOTE the type parameter `A` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the const parameter `Q`
|
||||
//~| NOTE the const parameter `Q` is defined here
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(
|
||||
//~^ NOTE the lifetime parameter `'r` is defined here
|
||||
//~| NOTE the type parameter `A` is defined here
|
||||
//~| NOTE the const parameter `Q` is defined here
|
||||
_: impl Trait<'r, A, Q, K = const { loop {} }>
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the type parameter `A`
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the const parameter `Q`
|
||||
//~| NOTE `K` has type `&'r [A; Q]`
|
||||
) {}
|
||||
|
||||
trait Project: ConstParamTy_ {
|
||||
#[type_const]
|
||||
const SELF: Self;
|
||||
}
|
||||
|
||||
fn take1(_: impl Project<SELF = {}>) {}
|
||||
fn take1(_: impl Project<SELF = const {}>) {}
|
||||
//~^ ERROR the type of the associated constant `SELF` must not depend on `impl Trait`
|
||||
//~| NOTE its type must not depend on `impl Trait`
|
||||
//~| NOTE the `impl Trait` is specified here
|
||||
|
||||
fn take2<P: Project<SELF = {}>>(_: P) {}
|
||||
fn take2<P: Project<SELF = const {}>>(_: P) {}
|
||||
//~^ ERROR the type of the associated constant `SELF` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the type parameter `P`
|
||||
//~| NOTE the type parameter `P` is defined here
|
||||
|
|
@ -48,7 +50,7 @@ fn take2<P: Project<SELF = {}>>(_: P) {}
|
|||
trait Iface<'r>: ConstParamTy_ {
|
||||
//~^ NOTE the lifetime parameter `'r` is defined here
|
||||
//~| NOTE the lifetime parameter `'r` is defined here
|
||||
type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
//~^ ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| ERROR the type of the associated constant `K` must not depend on generic parameters
|
||||
//~| NOTE its type must not depend on the lifetime parameter `'r`
|
||||
|
|
|
|||
|
|
@ -1,42 +1,49 @@
|
|||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:22:29
|
||||
|
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| -- the lifetime parameter `'r` is defined here ^ its type must not depend on the lifetime parameter `'r`
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
...
|
||||
LL | _: impl Trait<'r, A, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:22:29
|
||||
|
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - the type parameter `A` is defined here ^ its type must not depend on the type parameter `A`
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(
|
||||
| - the type parameter `A` is defined here
|
||||
...
|
||||
LL | _: impl Trait<'r, A, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on the type parameter `A`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:18:77
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:22:29
|
||||
|
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(_: impl Trait<'r, A, Q, K = { loop {} }>) {}
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
LL | fn take0<'r, A: 'r + ConstParamTy_, const Q: usize>(
|
||||
| - the const parameter `Q` is defined here
|
||||
...
|
||||
LL | _: impl Trait<'r, A, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on the const parameter `Q`
|
||||
|
|
||||
= note: `K` has type `&'r [A; Q]`
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on `impl Trait`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:37:26
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:39:26
|
||||
|
|
||||
LL | fn take1(_: impl Project<SELF = {}>) {}
|
||||
| -------------^^^^------
|
||||
LL | fn take1(_: impl Project<SELF = const {}>) {}
|
||||
| -------------^^^^------------
|
||||
| | |
|
||||
| | its type must not depend on `impl Trait`
|
||||
| the `impl Trait` is specified here
|
||||
|
||||
error: the type of the associated constant `SELF` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:42:21
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:44:21
|
||||
|
|
||||
LL | fn take2<P: Project<SELF = {}>>(_: P) {}
|
||||
LL | fn take2<P: Project<SELF = const {}>>(_: P) {}
|
||||
| - ^^^^ its type must not depend on the type parameter `P`
|
||||
| |
|
||||
| the type parameter `P` is defined here
|
||||
|
|
@ -44,28 +51,28 @@ LL | fn take2<P: Project<SELF = {}>>(_: P) {}
|
|||
= note: `SELF` has type `P`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | trait Iface<'r>: ConstParamTy_ {
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
...
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on `Self`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on `Self`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
|
|
@ -73,30 +80,30 @@ LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
|||
= note: `K` has type `&'r [Self; Q]`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | trait Iface<'r>: ConstParamTy_ {
|
||||
| -- the lifetime parameter `'r` is defined here
|
||||
...
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on the lifetime parameter `'r`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on `Self`
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| ^ its type must not depend on `Self`
|
||||
|
|
||||
= note: `K` has type `&'r [Self; Q]`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: the type of the associated constant `K` must not depend on generic parameters
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:51:52
|
||||
--> $DIR/assoc-const-eq-param-in-ty.rs:53:52
|
||||
|
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = { loop {} }>
|
||||
LL | type Assoc<const Q: usize>: Trait<'r, Self, Q, K = const { loop {} }>
|
||||
| - ^ its type must not depend on the const parameter `Q`
|
||||
| |
|
||||
| the const parameter `Q` is defined here
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ impl Foo for Bar {
|
|||
const N: usize = 3;
|
||||
}
|
||||
|
||||
const TEST:usize = 3;
|
||||
const TEST: usize = 3;
|
||||
|
||||
|
||||
fn foo<F: Foo<N=3usize>>() {}
|
||||
fn foo<F: Foo<N = 3usize>>() {}
|
||||
|
||||
fn main() {
|
||||
foo::<Bar>()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ pub trait Trait {
|
|||
|
||||
pub fn foo<
|
||||
T: Trait<
|
||||
ASSOC = {
|
||||
ASSOC = const {
|
||||
let a = 10_usize;
|
||||
let b: &'_ usize = &a;
|
||||
*b
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
//@ revisions: stock gce
|
||||
|
||||
#![feature(associated_const_equality, min_generic_const_args)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![cfg_attr(gce, feature(generic_const_exprs))]
|
||||
|
||||
trait TraitWAssocConst {
|
||||
#[type_const]
|
||||
const A: usize;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
error[E0271]: type mismatch resolving `<T as TraitWAssocConst>::A == 1`
|
||||
--> $DIR/const-projection-err.rs:16:11
|
||||
--> $DIR/const-projection-err.rs:12:11
|
||||
|
|
||||
LL | foo::<T>();
|
||||
| ^ expected `0`, found `1`
|
||||
| ^ expected `1`, found `0`
|
||||
|
|
||||
= note: expected constant `1`
|
||||
found constant `0`
|
||||
note: required by a bound in `foo`
|
||||
--> $DIR/const-projection-err.rs:13:28
|
||||
--> $DIR/const-projection-err.rs:9:28
|
||||
|
|
||||
LL | fn foo<T: TraitWAssocConst<A = 1>>() {}
|
||||
| ^^^^^ required by this bound in `foo`
|
||||
|
|
@ -81,7 +81,9 @@ fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
|||
|
||||
fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
||||
|
||||
fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}
|
||||
fn uncallable_rtn(
|
||||
_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>
|
||||
) {}
|
||||
|
||||
type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
//~^ ERROR [E0719]
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ LL | iter::empty::<String>()
|
|||
| ----------------------- return type was inferred to be `std::iter::Empty<String>` here
|
||||
|
||||
error[E0271]: expected `IntoIter<u32, 1>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:110:17
|
||||
--> $DIR/duplicate-bound-err.rs:112:17
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
@ -109,7 +109,7 @@ LL | [2u32].into_iter()
|
|||
| ------------------ return type was inferred to be `std::array::IntoIter<u32, 1>` here
|
||||
|
||||
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:86:42
|
||||
--> $DIR/duplicate-bound-err.rs:88:42
|
||||
|
|
||||
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
|
|
@ -117,7 +117,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
|||
| `Item` bound here first
|
||||
|
||||
error: conflicting associated type bounds for `Item`
|
||||
--> $DIR/duplicate-bound-err.rs:86:17
|
||||
--> $DIR/duplicate-bound-err.rs:88:17
|
||||
|
|
||||
LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
||||
| ^^^^^^^^^^^^^----------^^----------^
|
||||
|
|
@ -126,7 +126,7 @@ LL | type MustFail = dyn Iterator<Item = i32, Item = u32>;
|
|||
| `Item` is specified to be `i32` here
|
||||
|
||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:95:43
|
||||
--> $DIR/duplicate-bound-err.rs:97:43
|
||||
|
|
||||
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||
|
|
@ -134,7 +134,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
|||
| `ASSOC` bound here first
|
||||
|
||||
error: conflicting associated type bounds for `ASSOC`
|
||||
--> $DIR/duplicate-bound-err.rs:95:18
|
||||
--> $DIR/duplicate-bound-err.rs:97:18
|
||||
|
|
||||
LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
||||
| ^^^^^^^^^^^------------^^------------^
|
||||
|
|
@ -143,7 +143,7 @@ LL | type MustFail2 = dyn Trait2<ASSOC = 3u32, ASSOC = 4u32>;
|
|||
| `ASSOC` is specified to be `3` here
|
||||
|
||||
error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:99:43
|
||||
--> $DIR/duplicate-bound-err.rs:101:43
|
||||
|
|
||||
LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
||||
| ---------- ^^^^^^^^^^ re-bound here
|
||||
|
|
@ -151,7 +151,7 @@ LL | type MustFail3 = dyn Iterator<Item = i32, Item = i32>;
|
|||
| `Item` bound here first
|
||||
|
||||
error[E0719]: the value of the associated type `ASSOC` in trait `Trait2` is already specified
|
||||
--> $DIR/duplicate-bound-err.rs:102:43
|
||||
--> $DIR/duplicate-bound-err.rs:104:43
|
||||
|
|
||||
LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
||||
| ------------ ^^^^^^^^^^^^ re-bound here
|
||||
|
|
@ -159,19 +159,19 @@ LL | type MustFail4 = dyn Trait2<ASSOC = 3u32, ASSOC = 3u32>;
|
|||
| `ASSOC` bound here first
|
||||
|
||||
error[E0271]: expected `impl Iterator<Item = u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:110:17
|
||||
--> $DIR/duplicate-bound-err.rs:112:17
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
note: required by a bound in `Trait3::foo::{anon_assoc#0}`
|
||||
--> $DIR/duplicate-bound-err.rs:106:31
|
||||
--> $DIR/duplicate-bound-err.rs:108:31
|
||||
|
|
||||
LL | fn foo() -> impl Iterator<Item = i32, Item = u32>;
|
||||
| ^^^^^^^^^^ required by this bound in `Trait3::foo::{anon_assoc#0}`
|
||||
|
||||
error[E0271]: expected `Empty<u32>` to be an iterator that yields `i32`, but it yields `u32`
|
||||
--> $DIR/duplicate-bound-err.rs:118:16
|
||||
--> $DIR/duplicate-bound-err.rs:120:16
|
||||
|
|
||||
LL | uncallable(iter::empty::<u32>());
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32`
|
||||
|
|
@ -185,7 +185,7 @@ LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
|||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||
|
||||
error[E0271]: expected `Empty<i32>` to be an iterator that yields `u32`, but it yields `i32`
|
||||
--> $DIR/duplicate-bound-err.rs:119:16
|
||||
--> $DIR/duplicate-bound-err.rs:121:16
|
||||
|
|
||||
LL | uncallable(iter::empty::<i32>());
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
|
||||
|
|
@ -199,7 +199,7 @@ LL | fn uncallable(_: impl Iterator<Item = i32, Item = u32>) {}
|
|||
| ^^^^^^^^^^ required by this bound in `uncallable`
|
||||
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
||||
--> $DIR/duplicate-bound-err.rs:120:22
|
||||
--> $DIR/duplicate-bound-err.rs:122:22
|
||||
|
|
||||
LL | uncallable_const(());
|
||||
| ---------------- ^^ expected `4`, found `3`
|
||||
|
|
@ -215,7 +215,7 @@ LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
|||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||
|
||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
||||
--> $DIR/duplicate-bound-err.rs:121:22
|
||||
--> $DIR/duplicate-bound-err.rs:123:22
|
||||
|
|
||||
LL | uncallable_const(4u32);
|
||||
| ---------------- ^^^^ expected `3`, found `4`
|
||||
|
|
@ -231,7 +231,7 @@ LL | fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
|||
| ^^^^^^^^^ required by this bound in `uncallable_const`
|
||||
|
||||
error[E0271]: type mismatch resolving `<() as Trait>::ASSOC == 4`
|
||||
--> $DIR/duplicate-bound-err.rs:122:20
|
||||
--> $DIR/duplicate-bound-err.rs:124:20
|
||||
|
|
||||
LL | uncallable_rtn(());
|
||||
| -------------- ^^ expected `4`, found `3`
|
||||
|
|
@ -241,13 +241,15 @@ LL | uncallable_rtn(());
|
|||
= note: expected constant `4`
|
||||
found constant `3`
|
||||
note: required by a bound in `uncallable_rtn`
|
||||
--> $DIR/duplicate-bound-err.rs:84:75
|
||||
--> $DIR/duplicate-bound-err.rs:85:61
|
||||
|
|
||||
LL | fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||
LL | fn uncallable_rtn(
|
||||
| -------------- required by a bound in this function
|
||||
LL | _: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||
|
||||
error[E0271]: type mismatch resolving `<u32 as Trait>::ASSOC == 3`
|
||||
--> $DIR/duplicate-bound-err.rs:123:20
|
||||
--> $DIR/duplicate-bound-err.rs:125:20
|
||||
|
|
||||
LL | uncallable_rtn(17u32);
|
||||
| -------------- ^^^^^ expected `3`, found `4`
|
||||
|
|
@ -257,10 +259,12 @@ LL | uncallable_rtn(17u32);
|
|||
= note: expected constant `3`
|
||||
found constant `4`
|
||||
note: required by a bound in `uncallable_rtn`
|
||||
--> $DIR/duplicate-bound-err.rs:84:48
|
||||
--> $DIR/duplicate-bound-err.rs:85:34
|
||||
|
|
||||
LL | fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||
LL | fn uncallable_rtn(
|
||||
| -------------- required by a bound in this function
|
||||
LL | _: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>
|
||||
| ^^^^^^^^^ required by this bound in `uncallable_rtn`
|
||||
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,9 @@ fn uncallable_const(_: impl Trait<ASSOC = 3, ASSOC = 4>) {}
|
|||
|
||||
fn callable_const(_: impl Trait<ASSOC = 3, ASSOC = 3>) {}
|
||||
|
||||
fn uncallable_rtn(_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>) {}
|
||||
fn uncallable_rtn(
|
||||
_: impl Trait<foo(..): Trait<ASSOC = 3>, foo(..): Trait<ASSOC = 4>>
|
||||
) {}
|
||||
|
||||
fn callable_rtn(_: impl Trait<foo(..): Send, foo(..): Send, foo(..): Eq>) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ impl<T> AssocConst for (T,) {
|
|||
|
||||
trait Trait {}
|
||||
|
||||
impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
impl<U> Trait for () where (U,): AssocConst<A = 0> {}
|
||||
//~^ ERROR associated const equality is incomplete
|
||||
//~| ERROR the type parameter `U` is not constrained by the impl trait
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/unconstrained_impl_param.rs:15:45
|
||||
|
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
| ^^^^^^^^^
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = 0> {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
|
||||
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
|
||||
|
|
@ -11,7 +11,7 @@ LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
|||
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
|
||||
--> $DIR/unconstrained_impl_param.rs:15:6
|
||||
|
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = { 0 }> {}
|
||||
LL | impl<U> Trait for () where (U,): AssocConst<A = 0> {}
|
||||
| ^ unconstrained type parameter
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
|
|
|
|||
70
tests/ui/const-generics/mgca/explicit_anon_consts.rs
Normal file
70
tests/ui/const-generics/mgca/explicit_anon_consts.rs
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#![feature(associated_const_equality, generic_const_items, min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
struct Foo<const N: usize>;
|
||||
|
||||
type Adt1<const N: usize> = Foo<N>;
|
||||
type Adt2<const N: usize> = Foo<{ N }>;
|
||||
type Adt3<const N: usize> = Foo<const { N }>;
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
type Adt4<const N: usize> = Foo<{ 1 + 1 }>;
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
type Adt5<const N: usize> = Foo<const { 1 + 1 }>;
|
||||
|
||||
type Arr<const N: usize> = [(); N];
|
||||
type Arr2<const N: usize> = [(); { N }];
|
||||
type Arr3<const N: usize> = [(); const { N }];
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
type Arr4<const N: usize> = [(); 1 + 1];
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
type Arr5<const N: usize> = [(); const { 1 + 1 }];
|
||||
|
||||
fn repeats<const N: usize>() {
|
||||
let _1 = [(); N];
|
||||
let _2 = [(); { N }];
|
||||
let _3 = [(); const { N }];
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
let _4 = [(); 1 + 1];
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
let _5 = [(); const { 1 + 1 }];
|
||||
}
|
||||
|
||||
#[type_const]
|
||||
const ITEM1<const N: usize>: usize = N;
|
||||
#[type_const]
|
||||
const ITEM2<const N: usize>: usize = { N };
|
||||
#[type_const]
|
||||
const ITEM3<const N: usize>: usize = const { N };
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const ITEM4<const N: usize>: usize = { 1 + 1 };
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
#[type_const]
|
||||
const ITEM5<const N: usize>: usize = const { 1 + 1};
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
fn ace_bounds<
|
||||
const N: usize,
|
||||
// We skip the T1 case because it doesn't resolve
|
||||
// T1: Trait<ASSOC = N>,
|
||||
T2: Trait<ASSOC = { N }>,
|
||||
T3: Trait<ASSOC = const { N }>,
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
T4: Trait<ASSOC = { 1 + 1 }>,
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
T5: Trait<ASSOC = const { 1 + 1 }>,
|
||||
>() {}
|
||||
|
||||
struct Default1<const N: usize, const M: usize = N>;
|
||||
struct Default2<const N: usize, const M: usize = { N }>;
|
||||
struct Default3<const N: usize, const M: usize = const { N }>;
|
||||
//~^ ERROR: generic parameters may not be used in const operations
|
||||
struct Default4<const N: usize, const M: usize = { 1 + 1 }>;
|
||||
//~^ ERROR: complex const arguments must be placed inside of a `const` block
|
||||
struct Default5<const N: usize, const M: usize = const { 1 + 1}>;
|
||||
|
||||
fn main() {}
|
||||
92
tests/ui/const-generics/mgca/explicit_anon_consts.stderr
Normal file
92
tests/ui/const-generics/mgca/explicit_anon_consts.stderr
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:8:41
|
||||
|
|
||||
LL | type Adt3<const N: usize> = Foo<const { N }>;
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:16:42
|
||||
|
|
||||
LL | type Arr3<const N: usize> = [(); const { N }];
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:25:27
|
||||
|
|
||||
LL | let _3 = [(); const { N }];
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:37:46
|
||||
|
|
||||
LL | const ITEM3<const N: usize>: usize = const { N };
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:55:31
|
||||
|
|
||||
LL | T3: Trait<ASSOC = const { N }>,
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/explicit_anon_consts.rs:64:58
|
||||
|
|
||||
LL | struct Default3<const N: usize, const M: usize = const { N }>;
|
||||
| ^ cannot perform const operation using `N`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `N`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:10:33
|
||||
|
|
||||
LL | type Adt4<const N: usize> = Foo<{ 1 + 1 }>;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:18:34
|
||||
|
|
||||
LL | type Arr4<const N: usize> = [(); 1 + 1];
|
||||
| ^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:27:19
|
||||
|
|
||||
LL | let _4 = [(); 1 + 1];
|
||||
| ^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:40:38
|
||||
|
|
||||
LL | const ITEM4<const N: usize>: usize = { 1 + 1 };
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:57:23
|
||||
|
|
||||
LL | T4: Trait<ASSOC = { 1 + 1 }>,
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: complex const arguments must be placed inside of a `const` block
|
||||
--> $DIR/explicit_anon_consts.rs:66:50
|
||||
|
|
||||
LL | struct Default4<const N: usize, const M: usize = { 1 + 1 }>;
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: aborting due to 12 previous errors
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//@ check-pass
|
||||
|
||||
// We allow for literals to implicitly be anon consts still regardless
|
||||
// of whether a const block is placed around them or not
|
||||
|
||||
#![feature(min_generic_const_args, associated_const_equality)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: isize;
|
||||
}
|
||||
|
||||
fn ace<T: Trait<ASSOC = 1, ASSOC = -1>>() {}
|
||||
fn repeat_count() {
|
||||
[(); 1];
|
||||
}
|
||||
type ArrLen = [(); 1];
|
||||
struct Foo<const N: isize>;
|
||||
type NormalArg = (Foo<1>, Foo<-1>);
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(min_generic_const_args)]
|
||||
#![expect(incomplete_features)]
|
||||
|
||||
struct Foo<const N: usize>;
|
||||
|
||||
trait Trait {
|
||||
#[type_const]
|
||||
const ASSOC: usize;
|
||||
}
|
||||
|
||||
type Arr<const N: usize> = [(); {{{ N }}}];
|
||||
type Arr2<T> = [(); {{{ <T as Trait>::ASSOC }}}];
|
||||
type Ty<const N: usize> = Foo<{{{ N }}}>;
|
||||
type Ty2<T> = Foo<{{{ <T as Trait>::ASSOC }}}>;
|
||||
struct Default<const N: usize, const M: usize = {{{ N }}}>;
|
||||
struct Default2<T: Trait, const M: usize = {{{ <T as Trait>::ASSOC }}}>(T);
|
||||
|
||||
fn repeat<T: Trait, const N: usize>() {
|
||||
let _1 = [(); {{{ N }}}];
|
||||
let _2 = [(); {{{ <T as Trait>::ASSOC }}}];
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -4,9 +4,9 @@
|
|||
struct S;
|
||||
|
||||
// FIXME(mgca): need support for ctors without anon const
|
||||
// (we use double-braces to trigger an anon const here)
|
||||
// (we use a const-block to trigger an anon const here)
|
||||
#[type_const]
|
||||
const FREE: S = { { S } };
|
||||
const FREE: S = const { S };
|
||||
//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
|
||||
trait Tr {
|
||||
|
|
@ -17,9 +17,9 @@ trait Tr {
|
|||
|
||||
impl Tr for S {
|
||||
// FIXME(mgca): need support for ctors without anon const
|
||||
// (we use double-braces to trigger an anon const here)
|
||||
// (we use a const-block to trigger an anon const here)
|
||||
#[type_const]
|
||||
const N: S = { { S } };
|
||||
const N: S = const { S };
|
||||
//~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
--> $DIR/type_const-not-constparamty.rs:9:13
|
||||
|
|
||||
LL | const FREE: S = { { S } };
|
||||
LL | const FREE: S = const { S };
|
||||
| ^
|
||||
|
|
||||
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
||||
|
|
@ -13,7 +13,7 @@ LL | struct S;
|
|||
error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||
--> $DIR/type_const-not-constparamty.rs:22:14
|
||||
|
|
||||
LL | const N: S = { { S } };
|
||||
LL | const N: S = const { S };
|
||||
| ^
|
||||
|
|
||||
help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
#![feature(min_generic_const_args, generic_const_items)]
|
||||
|
||||
#[type_const]
|
||||
const FREE1<T>: usize = std::mem::size_of::<T>();
|
||||
const FREE1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const FREE2<const I: usize>: usize = I + 1;
|
||||
const FREE2<const I: usize>: usize = const { I + 1 };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
|
||||
pub trait Tr<const X: usize> {
|
||||
|
|
@ -21,13 +21,13 @@ pub struct S;
|
|||
|
||||
impl<const X: usize> Tr<X> for S {
|
||||
#[type_const]
|
||||
const N1<T>: usize = std::mem::size_of::<T>();
|
||||
const N1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const N2<const I: usize>: usize = I + 1;
|
||||
const N2<const I: usize>: usize = const { I + 1 };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
#[type_const]
|
||||
const N3: usize = 2 & X;
|
||||
const N3: usize = const { 2 & X };
|
||||
//~^ ERROR generic parameters may not be used in const operations
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:5:45
|
||||
--> $DIR/type_const-on-generic-expr.rs:5:53
|
||||
|
|
||||
LL | const FREE1<T>: usize = std::mem::size_of::<T>();
|
||||
| ^ cannot perform const operation using `T`
|
||||
LL | const FREE1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
||||
= note: type parameters may not be used in const expressions
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:8:38
|
||||
--> $DIR/type_const-on-generic-expr.rs:8:46
|
||||
|
|
||||
LL | const FREE2<const I: usize>: usize = I + 1;
|
||||
| ^ cannot perform const operation using `I`
|
||||
LL | const FREE2<const I: usize>: usize = const { I + 1 };
|
||||
| ^ cannot perform const operation using `I`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `I`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:24:46
|
||||
--> $DIR/type_const-on-generic-expr.rs:24:54
|
||||
|
|
||||
LL | const N1<T>: usize = std::mem::size_of::<T>();
|
||||
| ^ cannot perform const operation using `T`
|
||||
LL | const N1<T>: usize = const { std::mem::size_of::<T>() };
|
||||
| ^ cannot perform const operation using `T`
|
||||
|
|
||||
= note: type parameters may not be used in const expressions
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:27:39
|
||||
--> $DIR/type_const-on-generic-expr.rs:27:47
|
||||
|
|
||||
LL | const N2<const I: usize>: usize = I + 1;
|
||||
| ^ cannot perform const operation using `I`
|
||||
LL | const N2<const I: usize>: usize = const { I + 1 };
|
||||
| ^ cannot perform const operation using `I`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `I`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
||||
error: generic parameters may not be used in const operations
|
||||
--> $DIR/type_const-on-generic-expr.rs:30:27
|
||||
--> $DIR/type_const-on-generic-expr.rs:30:35
|
||||
|
|
||||
LL | const N3: usize = 2 & X;
|
||||
| ^ cannot perform const operation using `X`
|
||||
LL | const N3: usize = const { 2 & X };
|
||||
| ^ cannot perform const operation using `X`
|
||||
|
|
||||
= help: const parameters may only be used as standalone arguments here, i.e. `X`
|
||||
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
#![feature(adt_const_params)]
|
||||
|
||||
#[derive(Eq, PartialEq, std::marker::ConstParamTy)]
|
||||
struct Inner<const N: usize>;
|
||||
|
||||
struct Foo<
|
||||
const PARAM_TY: Inner<const { 1 }>,
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
const DEFAULT: usize = const { 1 },
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
>;
|
||||
|
||||
type Array = [(); const { 1 }];
|
||||
type NormalTy = Inner<const { 1 }>;
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
|
||||
fn repeat() {
|
||||
[1_u8; const { 1 }];
|
||||
}
|
||||
|
||||
fn body_ty() {
|
||||
let _: Inner<const { 1 }>;
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
}
|
||||
|
||||
fn generic<const N: usize>() {
|
||||
if false {
|
||||
generic::<const { 1 }>();
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
}
|
||||
}
|
||||
|
||||
const NON_TYPE_CONST: usize = const { 1 };
|
||||
|
||||
#[type_const]
|
||||
//~^ ERROR: the `#[type_const]` attribute is an experimental feature
|
||||
const TYPE_CONST: usize = const { 1 };
|
||||
//~^ ERROR: unbraced const blocks as const args are experimental
|
||||
|
||||
static STATIC: usize = const { 1 };
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:7:33
|
||||
|
|
||||
LL | const PARAM_TY: Inner<const { 1 }>,
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:9:34
|
||||
|
|
||||
LL | const DEFAULT: usize = const { 1 },
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:14:29
|
||||
|
|
||||
LL | type NormalTy = Inner<const { 1 }>;
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:22:24
|
||||
|
|
||||
LL | let _: Inner<const { 1 }>;
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:28:25
|
||||
|
|
||||
LL | generic::<const { 1 }>();
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: unbraced const blocks as const args are experimental
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:37:33
|
||||
|
|
||||
LL | const TYPE_CONST: usize = const { 1 };
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #132980 <https://github.com/rust-lang/rust/issues/132980> for more information
|
||||
= help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: the `#[type_const]` attribute is an experimental feature
|
||||
--> $DIR/unbraced_const_block_const_arg_gated.rs:35:1
|
||||
|
|
||||
LL | #[type_const]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= 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: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -9,6 +9,6 @@ trait Trait {
|
|||
//~^ ERROR using function pointers as const generic parameters is forbidden
|
||||
}
|
||||
|
||||
fn take(_: impl Trait<F = { || {} }>) {}
|
||||
fn take(_: impl Trait<F = const { || {} }>) {}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ impl<TA> Pins<TA> for NoPin {}
|
|||
|
||||
pub trait PinA<PER> {
|
||||
#[type_const]
|
||||
const A: &'static () = &();
|
||||
const A: &'static () = const { &() };
|
||||
}
|
||||
|
||||
pub trait Pins<USART> {}
|
||||
|
||||
impl<USART, T> Pins<USART> for T where T: PinA<USART, A = { &() }> {}
|
||||
impl<USART, T> Pins<USART> for T where T: PinA<USART, A = const { &() }> {}
|
||||
//~^ ERROR conflicting implementations of trait `Pins<_>` for type `NoPin`
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ error[E0119]: conflicting implementations of trait `Pins<_>` for type `NoPin`
|
|||
LL | impl<TA> Pins<TA> for NoPin {}
|
||||
| --------------------------- first implementation here
|
||||
...
|
||||
LL | impl<USART, T> Pins<USART> for T where T: PinA<USART, A = { &() }> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `NoPin`
|
||||
LL | impl<USART, T> Pins<USART> for T where T: PinA<USART, A = const { &() }> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `NoPin`
|
||||
|
|
||||
= note: downstream crates may implement trait `PinA<_>` for type `NoPin`
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl Owner for () {
|
|||
#[type_const]
|
||||
const C<const N: u32>: u32 = N;
|
||||
#[type_const]
|
||||
const K<const N: u32>: u32 = 99 + 1;
|
||||
const K<const N: u32>: u32 = const { 99 + 1 };
|
||||
// FIXME(mgca): re-enable once we properly support ctors and generics on paths
|
||||
// #[type_const]
|
||||
// const Q<T>: Maybe<T> = Maybe::Nothing;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue