mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Introduce const Trait
(always-const trait bounds)
This commit is contained in:
parent
2fe50cd72c
commit
3eb48a35c8
@ -2481,15 +2481,6 @@ pub enum Const {
|
||||
No,
|
||||
}
|
||||
|
||||
impl From<BoundConstness> for Const {
|
||||
fn from(constness: BoundConstness) -> Self {
|
||||
match constness {
|
||||
BoundConstness::Maybe(span) => Self::Yes(span),
|
||||
BoundConstness::Never => Self::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Item defaultness.
|
||||
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
@ -2543,6 +2534,8 @@ impl BoundPolarity {
|
||||
pub enum BoundConstness {
|
||||
/// `Type: Trait`
|
||||
Never,
|
||||
/// `Type: const Trait`
|
||||
Always(Span),
|
||||
/// `Type: ~const Trait`
|
||||
Maybe(Span),
|
||||
}
|
||||
@ -2551,6 +2544,7 @@ impl BoundConstness {
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Never => "",
|
||||
Self::Always(_) => "const",
|
||||
Self::Maybe(_) => "~const",
|
||||
}
|
||||
}
|
||||
|
@ -528,15 +528,6 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token can appear at the start of a generic bound.
|
||||
pub fn can_begin_bound(&self) -> bool {
|
||||
self.is_path_start()
|
||||
|| self.is_lifetime()
|
||||
|| self.is_keyword(kw::For)
|
||||
|| self == &Question
|
||||
|| self == &OpenDelim(Delimiter::Parenthesis)
|
||||
}
|
||||
|
||||
/// Returns `true` if the token can appear at the start of an item.
|
||||
pub fn can_begin_item(&self) -> bool {
|
||||
match self.kind {
|
||||
|
@ -339,9 +339,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let itctx = ImplTraitContext::Universal;
|
||||
let (generics, (trait_ref, lowered_ty)) =
|
||||
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
||||
let constness = match *constness {
|
||||
Const::Yes(span) => BoundConstness::Maybe(span),
|
||||
Const::No => BoundConstness::Never,
|
||||
};
|
||||
|
||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||
this.lower_trait_ref(
|
||||
*constness,
|
||||
constness,
|
||||
trait_ref,
|
||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||
)
|
||||
|
@ -1324,7 +1324,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
span: t.span,
|
||||
},
|
||||
itctx,
|
||||
ast::Const::No,
|
||||
ast::BoundConstness::Never,
|
||||
);
|
||||
let bounds = this.arena.alloc_from_iter([bound]);
|
||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||
@ -1435,7 +1435,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
polarity: BoundPolarity::Positive | BoundPolarity::Negative(_),
|
||||
constness,
|
||||
},
|
||||
) => Some(this.lower_poly_trait_ref(ty, itctx, (*constness).into())),
|
||||
) => Some(this.lower_poly_trait_ref(ty, itctx, *constness)),
|
||||
// We can safely ignore constness here, since AST validation
|
||||
// will take care of invalid modifier combinations.
|
||||
GenericBound::Trait(
|
||||
@ -2174,7 +2174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
fn lower_trait_ref(
|
||||
&mut self,
|
||||
constness: ast::Const,
|
||||
constness: ast::BoundConstness,
|
||||
p: &TraitRef,
|
||||
itctx: &ImplTraitContext,
|
||||
) -> hir::TraitRef<'hir> {
|
||||
@ -2197,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
&mut self,
|
||||
p: &PolyTraitRef,
|
||||
itctx: &ImplTraitContext,
|
||||
constness: ast::Const,
|
||||
constness: ast::BoundConstness,
|
||||
) -> hir::PolyTraitRef<'hir> {
|
||||
let bound_generic_params =
|
||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
|
||||
@ -2322,9 +2322,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
&mut self,
|
||||
modifiers: TraitBoundModifiers,
|
||||
) -> hir::TraitBoundModifier {
|
||||
// Invalid modifier combinations will cause an error during AST validation.
|
||||
// Arbitrarily pick a placeholder for them to make compilation proceed.
|
||||
match (modifiers.constness, modifiers.polarity) {
|
||||
(BoundConstness::Never, BoundPolarity::Positive) => hir::TraitBoundModifier::None,
|
||||
(BoundConstness::Never, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||
(_, BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||
(BoundConstness::Never, BoundPolarity::Negative(_)) => {
|
||||
if self.tcx.features().negative_bounds {
|
||||
hir::TraitBoundModifier::Negative
|
||||
@ -2332,15 +2334,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
hir::TraitBoundModifier::None
|
||||
}
|
||||
}
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Positive) => {
|
||||
hir::TraitBoundModifier::MaybeConst
|
||||
}
|
||||
// Invalid modifier combinations will cause an error during AST validation.
|
||||
// Arbitrarily pick a placeholder for compilation to proceed.
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Maybe(_)) => hir::TraitBoundModifier::Maybe,
|
||||
(BoundConstness::Maybe(_), BoundPolarity::Negative(_)) => {
|
||||
hir::TraitBoundModifier::MaybeConst
|
||||
}
|
||||
(BoundConstness::Always(_), _) => hir::TraitBoundModifier::Const,
|
||||
(BoundConstness::Maybe(_), _) => hir::TraitBoundModifier::MaybeConst,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2558,18 +2553,28 @@ struct GenericArgsCtor<'hir> {
|
||||
}
|
||||
|
||||
impl<'hir> GenericArgsCtor<'hir> {
|
||||
fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
|
||||
fn push_constness(
|
||||
&mut self,
|
||||
lcx: &mut LoweringContext<'_, 'hir>,
|
||||
constness: ast::BoundConstness,
|
||||
) {
|
||||
if !lcx.tcx.features().effects {
|
||||
return;
|
||||
}
|
||||
|
||||
// if bound is non-const, don't add host effect param
|
||||
let ast::Const::Yes(span) = constness else { return };
|
||||
|
||||
let (span, body) = match constness {
|
||||
BoundConstness::Never => return,
|
||||
BoundConstness::Always(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let id = lcx.next_node_id();
|
||||
let hir_id = lcx.next_id();
|
||||
let body = hir::ExprKind::Lit(
|
||||
lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }),
|
||||
);
|
||||
|
||||
(span, body)
|
||||
}
|
||||
BoundConstness::Maybe(span) => {
|
||||
let span = lcx.lower_span(span);
|
||||
|
||||
let Some(host_param_id) = lcx.host_param_id else {
|
||||
lcx.dcx().span_delayed_bug(
|
||||
@ -2579,24 +2584,31 @@ impl<'hir> GenericArgsCtor<'hir> {
|
||||
return;
|
||||
};
|
||||
|
||||
let body = lcx.lower_body(|lcx| {
|
||||
(&[], {
|
||||
let hir_id = lcx.next_id();
|
||||
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
||||
let expr_kind = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
let body = hir::ExprKind::Path(hir::QPath::Resolved(
|
||||
None,
|
||||
lcx.arena.alloc(hir::Path {
|
||||
span,
|
||||
res,
|
||||
segments: arena_vec![lcx; hir::PathSegment::new(Ident {
|
||||
name: sym::host,
|
||||
span,
|
||||
}, hir_id, res)],
|
||||
segments: arena_vec![
|
||||
lcx;
|
||||
hir::PathSegment::new(
|
||||
Ident { name: sym::host, span },
|
||||
hir_id,
|
||||
res
|
||||
)
|
||||
],
|
||||
}),
|
||||
));
|
||||
lcx.expr(span, expr_kind)
|
||||
})
|
||||
});
|
||||
|
||||
(span, body)
|
||||
}
|
||||
};
|
||||
let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body)));
|
||||
|
||||
let id = lcx.next_node_id();
|
||||
let hir_id = lcx.next_id();
|
||||
|
||||
let def_id = lcx.create_def(
|
||||
lcx.current_hir_id_owner.def_id,
|
||||
|
@ -25,7 +25,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
param_mode: ParamMode,
|
||||
itctx: &ImplTraitContext,
|
||||
// constness of the impl/bound if this is a trait path
|
||||
constness: Option<ast::Const>,
|
||||
constness: Option<ast::BoundConstness>,
|
||||
) -> hir::QPath<'hir> {
|
||||
let qself_position = qself.as_ref().map(|q| q.position);
|
||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
||||
@ -179,7 +179,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
param_mode: ParamMode,
|
||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||
itctx: &ImplTraitContext,
|
||||
constness: Option<ast::Const>,
|
||||
constness: Option<ast::BoundConstness>,
|
||||
) -> hir::PathSegment<'hir> {
|
||||
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
|
||||
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
||||
|
@ -46,6 +46,8 @@ ast_passes_const_and_c_variadic = functions cannot be both `const` and C-variadi
|
||||
.const = `const` because of this
|
||||
.variadic = C-variadic because of this
|
||||
|
||||
ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types
|
||||
|
||||
ast_passes_const_without_body =
|
||||
free constant item without body
|
||||
.suggestion = provide a definition for the constant
|
||||
|
@ -1207,6 +1207,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) => {
|
||||
self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span });
|
||||
}
|
||||
(BoundKind::TraitObject, BoundConstness::Always(_), BoundPolarity::Positive) => {
|
||||
self.dcx().emit_err(errors::ConstBoundTraitObject { span: poly.span });
|
||||
}
|
||||
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||
if let Some(reason) = &self.disallow_tilde_const =>
|
||||
{
|
||||
@ -1237,8 +1240,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
(
|
||||
_,
|
||||
BoundConstness::Maybe(_),
|
||||
BoundPolarity::Maybe(_) | BoundPolarity::Negative(_),
|
||||
BoundConstness::Always(_) | BoundConstness::Maybe(_),
|
||||
BoundPolarity::Negative(_) | BoundPolarity::Maybe(_),
|
||||
) => {
|
||||
self.dcx().emit_err(errors::IncompatibleTraitBoundModifiers {
|
||||
span: bound.span(),
|
||||
|
@ -540,6 +540,13 @@ pub struct OptionalTraitObject {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_const_bound_trait_object)]
|
||||
pub struct ConstBoundTraitObject {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_tilde_const_disallowed)]
|
||||
pub struct TildeConstDisallowed {
|
||||
|
@ -1561,7 +1561,7 @@ impl<'a> State<'a> {
|
||||
GenericBound::Trait(tref, modifier) => {
|
||||
match modifier.constness {
|
||||
ast::BoundConstness::Never => {}
|
||||
ast::BoundConstness::Maybe(_) => {
|
||||
ast::BoundConstness::Always(_) | ast::BoundConstness::Maybe(_) => {
|
||||
self.word_space(modifier.constness.as_str());
|
||||
}
|
||||
}
|
||||
|
@ -420,9 +420,15 @@ pub enum GenericArgsParentheses {
|
||||
/// A modifier on a trait bound.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum TraitBoundModifier {
|
||||
/// `Type: Trait`
|
||||
None,
|
||||
/// `Type: !Trait`
|
||||
Negative,
|
||||
/// `Type: ?Trait`
|
||||
Maybe,
|
||||
/// `Type: const Trait`
|
||||
Const,
|
||||
/// `Type: ~const Trait`
|
||||
MaybeConst,
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ hir_analysis_coercion_between_struct_same_note = expected coercion between the s
|
||||
hir_analysis_coercion_between_struct_single_note = expected a single field to be coerced, none found
|
||||
|
||||
hir_analysis_const_bound_for_non_const_trait =
|
||||
~const can only be applied to `#[const_trait]` traits
|
||||
`{$modifier}` can only be applied to `#[const_trait]` traits
|
||||
|
||||
hir_analysis_const_impl_for_non_const_trait =
|
||||
const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
|
||||
|
@ -112,6 +112,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||
match ast_bound {
|
||||
hir::GenericBound::Trait(poly_trait_ref, modifier) => {
|
||||
let (constness, polarity) = match modifier {
|
||||
hir::TraitBoundModifier::Const => {
|
||||
(ty::BoundConstness::Const, ty::ImplPolarity::Positive)
|
||||
}
|
||||
hir::TraitBoundModifier::MaybeConst => {
|
||||
(ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive)
|
||||
}
|
||||
|
@ -560,11 +560,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
inferred_params: vec![],
|
||||
infer_args,
|
||||
};
|
||||
if let ty::BoundConstness::ConstIfConst = constness
|
||||
if let ty::BoundConstness::Const | ty::BoundConstness::ConstIfConst = constness
|
||||
&& generics.has_self
|
||||
&& !tcx.has_attr(def_id, sym::const_trait)
|
||||
{
|
||||
let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait { span });
|
||||
let e = tcx.dcx().emit_err(crate::errors::ConstBoundForNonConstTrait {
|
||||
span,
|
||||
modifier: constness.as_str(),
|
||||
});
|
||||
arg_count.correct =
|
||||
Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
|
||||
}
|
||||
|
@ -408,6 +408,7 @@ pub struct ConstImplForNonConstTrait {
|
||||
pub struct ConstBoundForNonConstTrait {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub modifier: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -309,23 +309,22 @@ impl Visibility {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum BoundConstness {
|
||||
/// `T: Trait`
|
||||
/// `Type: Trait`
|
||||
NotConst,
|
||||
/// `T: ~const Trait`
|
||||
/// `Type: const Trait`
|
||||
Const,
|
||||
/// `Type: ~const Trait`
|
||||
///
|
||||
/// Requires resolving to const only when we are in a const context.
|
||||
ConstIfConst,
|
||||
}
|
||||
|
||||
impl BoundConstness {
|
||||
/// Reduce `self` and `constness` to two possible combined states instead of four.
|
||||
pub fn and(&mut self, constness: hir::Constness) -> hir::Constness {
|
||||
match (constness, self) {
|
||||
(hir::Constness::Const, BoundConstness::ConstIfConst) => hir::Constness::Const,
|
||||
(_, this) => {
|
||||
*this = BoundConstness::NotConst;
|
||||
hir::Constness::NotConst
|
||||
}
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::NotConst => "",
|
||||
Self::Const => "const",
|
||||
Self::ConstIfConst => "~const",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -334,7 +333,7 @@ impl fmt::Display for BoundConstness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::NotConst => f.write_str("normal"),
|
||||
Self::ConstIfConst => f.write_str("`~const`"),
|
||||
_ => write!(f, "`{self}`"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,9 +95,6 @@ parse_compound_assignment_expression_in_let = can't reassign to an uninitialized
|
||||
.suggestion = initialize the variable
|
||||
.help = if you meant to overwrite, remove the `let` binding
|
||||
|
||||
parse_const_bounds_missing_tilde = const bounds must start with `~`
|
||||
.suggestion = add `~`
|
||||
|
||||
parse_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
|
||||
.suggestion = enclose the `const` expression in braces
|
||||
|
||||
@ -555,8 +552,8 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl
|
||||
.suggestion_add_trait = add a trait here
|
||||
.suggestion_remove_for = for an inherent impl, drop this `for`
|
||||
|
||||
parse_modifier_lifetime = `{$sigil}` may only modify trait bounds, not lifetime bounds
|
||||
.suggestion = remove the `{$sigil}`
|
||||
parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
|
||||
.suggestion = remove the `{$modifier}`
|
||||
|
||||
parse_more_than_one_char = character literal may only contain one codepoint
|
||||
.followed_by = this `{$chr}` is followed by the combining {$len ->
|
||||
@ -729,8 +726,6 @@ parse_switch_ref_box_order = switch the order of `ref` and `box`
|
||||
parse_ternary_operator = Rust has no ternary operator
|
||||
.help = use an `if-else` expression instead
|
||||
|
||||
parse_tilde_const_lifetime = `~const` may only modify trait bounds, not lifetime bounds
|
||||
|
||||
parse_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
|
||||
.suggestion = use `!` to perform bitwise not
|
||||
|
||||
|
@ -2555,20 +2555,13 @@ pub(crate) struct AssocLifetime {
|
||||
pub lifetime: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_tilde_const_lifetime)]
|
||||
pub(crate) struct TildeConstLifetime {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_modifier_lifetime)]
|
||||
pub(crate) struct ModifierLifetime {
|
||||
#[primary_span]
|
||||
#[suggestion(style = "tool-only", applicability = "maybe-incorrect", code = "")]
|
||||
pub span: Span,
|
||||
pub sigil: &'static str,
|
||||
pub modifier: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@ -2581,15 +2574,6 @@ pub(crate) struct ParenthesizedLifetime {
|
||||
pub snippet: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_const_bounds_missing_tilde)]
|
||||
pub(crate) struct ConstMissingTilde {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(code = "~", applicability = "machine-applicable")]
|
||||
pub start: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parse_underscore_literal_suffix)]
|
||||
pub(crate) struct UnderscoreLiteralSuffix {
|
||||
|
@ -86,6 +86,18 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
|
||||
t == &token::ModSep || t == &token::Lt || t == &token::BinOp(token::Shl)
|
||||
}
|
||||
|
||||
fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
|
||||
// `Not`, `Tilde` & `Const` are deliberately not part of this list to
|
||||
// contain the number of potential regressions esp. in MBE code.
|
||||
// `Const` would regress `rfc-2632-const-trait-impl/mbe-dyn-const-2015.rs`.
|
||||
// `Not` would regress `dyn!(...)` macro calls in Rust 2015.
|
||||
t.is_path_start()
|
||||
|| t.is_lifetime()
|
||||
|| t == &TokenKind::Question
|
||||
|| t.is_keyword(kw::For)
|
||||
|| t == &TokenKind::OpenDelim(Delimiter::Parenthesis)
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
/// Parses a type.
|
||||
pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
|
||||
@ -665,7 +677,8 @@ impl<'a> Parser<'a> {
|
||||
self.check_keyword(kw::Dyn)
|
||||
&& (self.token.uninterpolated_span().at_least_rust_2018()
|
||||
|| self.look_ahead(1, |t| {
|
||||
(t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
|
||||
(can_begin_dyn_bound_in_edition_2015(t)
|
||||
|| t.kind == TokenKind::BinOp(token::Star))
|
||||
&& !can_continue_type_after_non_fn_ident(t)
|
||||
}))
|
||||
}
|
||||
@ -758,12 +771,12 @@ impl<'a> Parser<'a> {
|
||||
|
||||
/// Can the current token begin a bound?
|
||||
fn can_begin_bound(&mut self) -> bool {
|
||||
// This needs to be synchronized with `TokenKind::can_begin_bound`.
|
||||
self.check_path()
|
||||
|| self.check_lifetime()
|
||||
|| self.check(&token::Not)
|
||||
|| self.check(&token::Question)
|
||||
|| self.check(&token::Tilde)
|
||||
|| self.check_keyword(kw::Const)
|
||||
|| self.check_keyword(kw::For)
|
||||
|| self.check(&token::OpenDelim(Delimiter::Parenthesis))
|
||||
}
|
||||
@ -812,8 +825,11 @@ impl<'a> Parser<'a> {
|
||||
fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) {
|
||||
match modifiers.constness {
|
||||
BoundConstness::Never => {}
|
||||
BoundConstness::Maybe(span) => {
|
||||
self.dcx().emit_err(errors::TildeConstLifetime { span });
|
||||
BoundConstness::Always(span) | BoundConstness::Maybe(span) => {
|
||||
self.dcx().emit_err(errors::ModifierLifetime {
|
||||
span,
|
||||
modifier: modifiers.constness.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -822,7 +838,7 @@ impl<'a> Parser<'a> {
|
||||
BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => {
|
||||
self.dcx().emit_err(errors::ModifierLifetime {
|
||||
span,
|
||||
sigil: modifiers.polarity.as_str(),
|
||||
modifier: modifiers.polarity.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -848,7 +864,7 @@ impl<'a> Parser<'a> {
|
||||
/// If no modifiers are present, this does not consume any tokens.
|
||||
///
|
||||
/// ```ebnf
|
||||
/// TRAIT_BOUND_MODIFIERS = ["~const"] ["?" | "!"]
|
||||
/// TRAIT_BOUND_MODIFIERS = [["~"] "const"] ["?" | "!"]
|
||||
/// ```
|
||||
fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> {
|
||||
let constness = if self.eat(&token::Tilde) {
|
||||
@ -858,11 +874,8 @@ impl<'a> Parser<'a> {
|
||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
||||
BoundConstness::Maybe(span)
|
||||
} else if self.eat_keyword(kw::Const) {
|
||||
let span = self.prev_token.span;
|
||||
self.sess.gated_spans.gate(sym::const_trait_impl, span);
|
||||
self.dcx().emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() });
|
||||
|
||||
BoundConstness::Maybe(span)
|
||||
self.sess.gated_spans.gate(sym::const_trait_impl, self.prev_token.span);
|
||||
BoundConstness::Always(self.prev_token.span)
|
||||
} else {
|
||||
BoundConstness::Never
|
||||
};
|
||||
|
@ -449,8 +449,8 @@ impl clean::GenericBound {
|
||||
hir::TraitBoundModifier::None => "",
|
||||
hir::TraitBoundModifier::Maybe => "?",
|
||||
hir::TraitBoundModifier::Negative => "!",
|
||||
// ~const is experimental; do not display those bounds in rustdoc
|
||||
hir::TraitBoundModifier::MaybeConst => "",
|
||||
// `const` and `~const` trait bounds are experimental; don't render them.
|
||||
hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "",
|
||||
};
|
||||
if f.alternate() {
|
||||
write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx))
|
||||
|
@ -547,6 +547,9 @@ pub(crate) fn from_trait_bound_modifier(
|
||||
None => TraitBoundModifier::None,
|
||||
Maybe => TraitBoundModifier::Maybe,
|
||||
MaybeConst => TraitBoundModifier::MaybeConst,
|
||||
// FIXME(const_trait_impl): Create rjt::TBM::Const and map to it once always-const bounds
|
||||
// are less experimental.
|
||||
Const => TraitBoundModifier::None,
|
||||
// FIXME(negative-bounds): This bound should be rendered negative, but
|
||||
// since that's experimental, maybe let's not add it to the rustdoc json
|
||||
// API just now...
|
||||
|
@ -4,13 +4,13 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls`
|
||||
LL | #![feature(const_fn_trait_ref_impls)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:15:15
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
| ^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:15:15
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
@ -18,13 +18,13 @@ LL | T: ~const Fn<()> + ~const Destruct,
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:22:15
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:22:15
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
@ -32,13 +32,13 @@ LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:29:15
|
||||
|
|
||||
LL | T: ~const FnOnce<()>,
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:29:15
|
||||
|
|
||||
LL | T: ~const FnOnce<()>,
|
||||
@ -46,13 +46,13 @@ LL | T: ~const FnOnce<()>,
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:36:15
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
| ^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:36:15
|
||||
|
|
||||
LL | T: ~const Fn<()> + ~const Destruct,
|
||||
@ -60,13 +60,13 @@ LL | T: ~const Fn<()> + ~const Destruct,
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:50:15
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/fn_trait_refs.rs:50:15
|
||||
|
|
||||
LL | T: ~const FnMut<()> + ~const Destruct,
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/unstable-const-fn-in-libcore.rs:19:39
|
||||
|
|
||||
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
|
||||
|
@ -1,14 +1,12 @@
|
||||
// known-bug: #110395
|
||||
// FIXME check-pass
|
||||
// check-pass
|
||||
|
||||
// Test that we can call methods from const trait impls inside of generic const items.
|
||||
|
||||
#![feature(generic_const_items, const_trait_impl)]
|
||||
#![feature(generic_const_items, const_trait_impl, effects)]
|
||||
#![allow(incomplete_features)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work.
|
||||
const CREATE<T: Create>: T = T::create();
|
||||
const CREATE<T: const Create>: T = T::create();
|
||||
|
||||
pub const K0: i32 = CREATE::<i32>;
|
||||
pub const K1: i32 = CREATE; // arg inferred
|
||||
@ -23,3 +21,13 @@ impl const Create for i32 {
|
||||
4096
|
||||
}
|
||||
}
|
||||
|
||||
trait Mod { // doesn't need to be a `#[const_trait]`
|
||||
const CREATE<T: const Create>: T;
|
||||
}
|
||||
|
||||
impl Mod for () {
|
||||
const CREATE<T: const Create>: T = T::create();
|
||||
}
|
||||
|
||||
pub const K2: i32 = <() as Mod>::CREATE::<i32>;
|
||||
|
@ -1,12 +0,0 @@
|
||||
error[E0015]: cannot call non-const fn `<T as Create>::create` in constants
|
||||
--> $DIR/const-trait-impl.rs:11:30
|
||||
|
|
||||
LL | const CREATE<T: Create>: T = T::create();
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||
= help: add `#![feature(effects)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0015`.
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/normalize-tait-in-const.rs:25:42
|
||||
|
|
||||
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
|
||||
|
@ -13,6 +13,7 @@ struct S<
|
||||
T: ~const ?Tr, // OK
|
||||
T: ~const Tr + 'a, // OK
|
||||
T: ~const 'a, //~ ERROR `~const` may only modify trait bounds, not lifetime bounds
|
||||
T: const 'a, //~ ERROR `const` may only modify trait bounds, not lifetime bounds
|
||||
>;
|
||||
|
||||
fn main() {}
|
||||
|
@ -10,5 +10,11 @@ error: `~const` may only modify trait bounds, not lifetime bounds
|
||||
LL | T: ~const 'a,
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: `const` may only modify trait bounds, not lifetime bounds
|
||||
--> $DIR/bounds-type.rs:16:8
|
||||
|
|
||||
LL | T: const 'a,
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
// Check that `?Trait` matches the macro fragment specifier `ty`.
|
||||
// Syntactically trait object types can be "bare" (i.e., lack the prefix `dyn`),
|
||||
// even in newer editions like Rust 2021.
|
||||
// Therefore the arm `?$Trait:path` shouldn't get reached.
|
||||
|
||||
// edition: 2021
|
||||
// check-pass
|
||||
|
||||
macro_rules! check {
|
||||
($Ty:ty) => {};
|
||||
(?$Trait:path) => { compile_error!("non-ty"); };
|
||||
}
|
||||
|
||||
check! { ?Trait }
|
||||
|
||||
fn main() {}
|
@ -8,7 +8,7 @@ fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around t
|
||||
fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
|
||||
|
||||
fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
|
||||
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
|
||||
//~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
|
||||
//~| ERROR at least one trait is required for an object type
|
||||
|
||||
fn foo4(_: &dyn <Drop + AsRef<str>>) {} //~ ERROR expected identifier, found `<`
|
||||
|
@ -34,11 +34,11 @@ error: expected parameter name, found `{`
|
||||
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
||||
| ^ expected parameter name
|
||||
|
||||
error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
|
||||
error: expected one of `!`, `(`, `)`, `*`, `,`, `?`, `const`, `for`, `~`, lifetime, or path, found `{`
|
||||
--> $DIR/trait-object-delimiters.rs:10:17
|
||||
|
|
||||
LL | fn foo3(_: &dyn {Drop + AsRef<str>}) {}
|
||||
| -^ expected one of 10 possible tokens
|
||||
| -^ expected one of 11 possible tokens
|
||||
| |
|
||||
| help: missing `,`
|
||||
|
||||
|
@ -6,7 +6,7 @@ LL | type Bar: ~const std::ops::Add;
|
||||
|
|
||||
= note: this item cannot have `~const` trait bounds
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/assoc-type.rs:17:22
|
||||
|
|
||||
LL | type Bar: ~const std::ops::Add;
|
||||
|
@ -0,0 +1,12 @@
|
||||
// Regression test for issue #117244.
|
||||
#![feature(const_trait_impl, effects)]
|
||||
|
||||
trait NonConst {}
|
||||
|
||||
const fn perform<T: ~const NonConst>() {}
|
||||
//~^ ERROR `~const` can only be applied to `#[const_trait]` traits
|
||||
|
||||
fn operate<T: const NonConst>() {}
|
||||
//~^ ERROR `const` can only be applied to `#[const_trait]` traits
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-bounds-non-const-trait.rs:6:28
|
||||
|
|
||||
LL | const fn perform<T: ~const NonConst>() {}
|
||||
| ^^^^^^^^
|
||||
|
||||
error: `const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-bounds-non-const-trait.rs:9:21
|
||||
|
|
||||
LL | fn operate<T: const NonConst>() {}
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closure-parse-not-item.rs:7:32
|
||||
|
|
||||
LL | const fn test() -> impl ~const Fn() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closure-trait-method-fail.rs:14:39
|
||||
|
|
||||
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closure-trait-method.rs:14:39
|
||||
|
|
||||
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
|
||||
|
@ -1,22 +1,22 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closures.rs:8:19
|
||||
|
|
||||
LL | F: ~const FnOnce() -> u8,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closures.rs:9:19
|
||||
|
|
||||
LL | F: ~const FnMut() -> u8,
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closures.rs:10:19
|
||||
|
|
||||
LL | F: ~const Fn() -> u8,
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-closures.rs:23:27
|
||||
|
|
||||
LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
|
||||
|
@ -7,7 +7,7 @@ LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||
= note: adding a non-const method body in the future would be a breaking change
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-drop-fail-2.rs:29:26
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
|
@ -7,7 +7,7 @@ LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
|
||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||
= note: adding a non-const method body in the future would be a breaking change
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const-drop-fail-2.rs:29:26
|
||||
|
|
||||
LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||
|
@ -1,10 +1,15 @@
|
||||
error: `~const` is not allowed here
|
||||
--> $DIR/const-drop.rs:67:38
|
||||
error[E0493]: destructor of `T` cannot be evaluated at compile-time
|
||||
--> $DIR/const-drop.rs:19:32
|
||||
|
|
||||
LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
| ^^^^^^
|
||||
LL | const fn a<T: ~const Destruct>(_: T) {}
|
||||
| ^ the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time
|
||||
--> $DIR/const-drop.rs:24:13
|
||||
|
|
||||
= note: this item cannot have `~const` trait bounds
|
||||
LL | let _ = S(&mut c);
|
||||
| ^^^^^^^^^ the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
|
@ -4,7 +4,7 @@
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(never_type)]
|
||||
// #![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||
|
||||
use std::marker::Destruct;
|
||||
|
||||
@ -63,8 +63,7 @@ mod t {
|
||||
fn foo() {}
|
||||
}
|
||||
|
||||
// FIXME(effects): This should be a `const` bound instead of a `~const` one.
|
||||
pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
pub struct ConstDropWithBound<T: const SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
|
||||
impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
|
||||
fn drop(&mut self) {
|
||||
|
@ -1,10 +1,19 @@
|
||||
error: `~const` is not allowed here
|
||||
--> $DIR/const-drop.rs:67:38
|
||||
error[E0493]: destructor of `T` cannot be evaluated at compile-time
|
||||
--> $DIR/const-drop.rs:19:32
|
||||
|
|
||||
LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
|
||||
| ^^^^^^
|
||||
LL | const fn a<T: ~const Destruct>(_: T) {}
|
||||
| ^ - value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time
|
||||
--> $DIR/const-drop.rs:24:13
|
||||
|
|
||||
= note: this item cannot have `~const` trait bounds
|
||||
LL | let _ = S(&mut c);
|
||||
| ^^^^^^^^^- value is dropped here
|
||||
| |
|
||||
| the destructor for this type cannot be evaluated in constant functions
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0493`.
|
||||
|
@ -0,0 +1,9 @@
|
||||
#![feature(const_trait_impl)]
|
||||
// edition: 2021
|
||||
|
||||
#[const_trait]
|
||||
trait Trait {}
|
||||
|
||||
fn main() {
|
||||
let _: &dyn const Trait; //~ ERROR const trait bounds are not allowed in trait object types
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
error: const trait bounds are not allowed in trait object types
|
||||
--> $DIR/const-trait-bounds-trait-objects.rs:8:17
|
||||
|
|
||||
LL | let _: &dyn const Trait;
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -0,0 +1,31 @@
|
||||
// check-pass
|
||||
|
||||
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
fn main() {
|
||||
let _ = process::<()>([()]);
|
||||
let _ = Struct::<(), 4> { field: [1, 0] };
|
||||
}
|
||||
|
||||
fn process<T: const Trait>(input: [(); T::make(2)]) -> [(); T::make(2)] {
|
||||
input
|
||||
}
|
||||
|
||||
struct Struct<T: const Trait, const P: usize>
|
||||
where
|
||||
[u32; T::make(P)]:,
|
||||
{
|
||||
field: [u32; T::make(P)],
|
||||
}
|
||||
|
||||
#[const_trait]
|
||||
trait Trait {
|
||||
fn make(input: usize) -> usize;
|
||||
}
|
||||
|
||||
impl const Trait for () {
|
||||
fn make(input: usize) -> usize {
|
||||
input / 2
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#![feature(const_trait_impl, effects)]
|
||||
|
||||
const fn test() -> impl ~const Fn() { //~ ERROR ~const can only be applied to `#[const_trait]` traits
|
||||
const fn test() -> impl ~const Fn() { //~ ERROR `~const` can only be applied to `#[const_trait]` traits
|
||||
const move || { //~ ERROR const closures are experimental
|
||||
let sl: &[u8] = b"foo";
|
||||
|
||||
|
@ -7,7 +7,7 @@ LL | const move || {
|
||||
= note: see issue #106003 <https://github.com/rust-lang/rust/issues/106003> for more information
|
||||
= help: add `#![feature(const_closures)]` to the crate attributes to enable
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/ice-112822-expected-type-for-param.rs:3:32
|
||||
|
|
||||
LL | const fn test() -> impl ~const Fn() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
error: fatal error triggered by #[rustc_error]
|
||||
--> $DIR/feature-gate.rs:14:1
|
||||
--> $DIR/feature-gate.rs:22:1
|
||||
|
|
||||
LL | fn main() {}
|
||||
| ^^^^^^^^^
|
||||
|
@ -10,5 +10,13 @@ trait T {}
|
||||
impl const T for S {}
|
||||
//[stock]~^ ERROR const trait impls are experimental
|
||||
|
||||
const fn f<A: ~const T>() {} //[stock]~ ERROR const trait impls are experimental
|
||||
fn g<A: const T>() {} //[stock]~ ERROR const trait impls are experimental
|
||||
|
||||
macro_rules! discard { ($ty:ty) => {} }
|
||||
|
||||
discard! { impl ~const T } //[stock]~ ERROR const trait impls are experimental
|
||||
discard! { impl const T } //[stock]~ ERROR const trait impls are experimental
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error]
|
||||
|
@ -7,6 +7,42 @@ LL | impl const T for S {}
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/feature-gate.rs:13:15
|
||||
|
|
||||
LL | const fn f<A: ~const T>() {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/feature-gate.rs:14:9
|
||||
|
|
||||
LL | fn g<A: const T>() {}
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/feature-gate.rs:18:17
|
||||
|
|
||||
LL | discard! { impl ~const T }
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/feature-gate.rs:19:17
|
||||
|
|
||||
LL | discard! { impl const T }
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
|
||||
--> $DIR/feature-gate.rs:8:1
|
||||
|
|
||||
@ -16,6 +52,6 @@ LL | #[const_trait]
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
@ -0,0 +1,20 @@
|
||||
// Ensure that we don't consider `const Trait` and `~const Trait` to
|
||||
// match the macro fragment specifier `ty` as that would be a breaking
|
||||
// change theoretically speaking. Syntactically trait object types can
|
||||
// be "bare", i.e., lack the prefix `dyn`.
|
||||
// By contrast, `?Trait` *does* match `ty` and therefore an arm like
|
||||
// `?$Trait:path` would never be reached.
|
||||
// See `parser/macro/mbe-bare-trait-object-maybe-trait-bound.rs`.
|
||||
|
||||
// check-pass
|
||||
|
||||
macro_rules! check {
|
||||
($Type:ty) => { compile_error!("ty"); };
|
||||
(const $Trait:path) => {};
|
||||
(~const $Trait:path) => {};
|
||||
}
|
||||
|
||||
check! { const Trait }
|
||||
check! { ~const Trait }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,20 @@
|
||||
// Demonstrates and records a theoretical regressions / breaking changes caused by the
|
||||
// introduction of const trait bounds.
|
||||
|
||||
// Setting the edition to 2018 since we don't regress `demo! { dyn const }` in Rust <2018.
|
||||
// edition:2018
|
||||
|
||||
macro_rules! demo {
|
||||
($ty:ty) => { compile_error!("ty"); };
|
||||
(impl $c:ident) => {};
|
||||
(dyn $c:ident) => {};
|
||||
}
|
||||
|
||||
demo! { impl const }
|
||||
//~^ ERROR expected identifier, found `<eof>`
|
||||
|
||||
demo! { dyn const }
|
||||
//~^ ERROR const trait impls are experimental
|
||||
//~| ERROR expected identifier, found `<eof>`
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,30 @@
|
||||
error: expected identifier, found `<eof>`
|
||||
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:13:14
|
||||
|
|
||||
LL | ($ty:ty) => { compile_error!("ty"); };
|
||||
| ------ while parsing argument for this `ty` macro fragment
|
||||
...
|
||||
LL | demo! { impl const }
|
||||
| ^^^^^ expected identifier
|
||||
|
||||
error: expected identifier, found `<eof>`
|
||||
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
|
||||
|
|
||||
LL | ($ty:ty) => { compile_error!("ty"); };
|
||||
| ------ while parsing argument for this `ty` macro fragment
|
||||
...
|
||||
LL | demo! { dyn const }
|
||||
| ^^^^^ expected identifier
|
||||
|
||||
error[E0658]: const trait impls are experimental
|
||||
--> $DIR/mbe-const-trait-bound-theoretical-regression.rs:16:13
|
||||
|
|
||||
LL | demo! { dyn const }
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
|
||||
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,13 @@
|
||||
// Ensure that the introduction of const trait bound didn't regress this code in Rust 2015.
|
||||
// See also `mbe-const-trait-bound-theoretical-regression.rs`.
|
||||
|
||||
// check-pass
|
||||
|
||||
macro_rules! check {
|
||||
($ty:ty) => { compile_error!("ty"); };
|
||||
(dyn $c:ident) => {};
|
||||
}
|
||||
|
||||
check! { dyn const }
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,20 @@
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
const fn maybe_const_maybe<T: ~const ?Sized>() {}
|
||||
//~^ ERROR `~const` and `?` are mutually exclusive
|
||||
|
||||
fn const_maybe<T: const ?Sized>() {}
|
||||
//~^ ERROR `const` and `?` are mutually exclusive
|
||||
|
||||
const fn maybe_const_negative<T: ~const !Trait>() {}
|
||||
//~^ ERROR `~const` and `!` are mutually exclusive
|
||||
//~| ERROR negative bounds are not supported
|
||||
|
||||
fn const_negative<T: const !Trait>() {}
|
||||
//~^ ERROR `const` and `!` are mutually exclusive
|
||||
//~| ERROR negative bounds are not supported
|
||||
|
||||
#[const_trait]
|
||||
trait Trait {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,38 @@
|
||||
error: `~const` and `?` are mutually exclusive
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31
|
||||
|
|
||||
LL | const fn maybe_const_maybe<T: ~const ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: `const` and `?` are mutually exclusive
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:19
|
||||
|
|
||||
LL | fn const_maybe<T: const ?Sized>() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: `~const` and `!` are mutually exclusive
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:34
|
||||
|
|
||||
LL | const fn maybe_const_negative<T: ~const !Trait>() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: `const` and `!` are mutually exclusive
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:22
|
||||
|
|
||||
LL | fn const_negative<T: const !Trait>() {}
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: negative bounds are not supported
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:41
|
||||
|
|
||||
LL | const fn maybe_const_negative<T: ~const !Trait>() {}
|
||||
| ^
|
||||
|
||||
error: negative bounds are not supported
|
||||
--> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28
|
||||
|
|
||||
LL | fn const_negative<T: const !Trait>() {}
|
||||
| ^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
@ -1,4 +1,4 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/non-const-op-in-closure-in-const.rs:10:51
|
||||
|
|
||||
LL | impl<A, B> const Convert<B> for A where B: ~const From<A> {
|
||||
|
@ -10,13 +10,13 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-2.rs:10:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-2.rs:10:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-2.rs:10:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-2.rs:10:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
|
@ -8,8 +8,8 @@ trait Foo {
|
||||
|
||||
#[cfg_attr(any(yy, ny), const_trait)]
|
||||
trait Bar: ~const Foo {}
|
||||
//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
|
||||
//[yn,nn]~^^^ ERROR: `~const` is not allowed here
|
||||
|
||||
const fn foo<T: Bar>(x: &T) {
|
||||
|
@ -10,13 +10,13 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:12:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:12:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
@ -24,7 +24,7 @@ LL | trait Bar: ~const Foo {}
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:17:24
|
||||
|
|
||||
LL | const fn foo<T: ~const Bar>(x: &T) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:12:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:12:19
|
||||
|
|
||||
LL | trait Bar: ~const Foo {}
|
||||
|
@ -10,12 +10,12 @@ trait Foo {
|
||||
|
||||
#[cfg_attr(any(yy, ny), const_trait)]
|
||||
trait Bar: ~const Foo {}
|
||||
//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
|
||||
//[ny,nn]~| ERROR: `~const` can only be applied to `#[const_trait]`
|
||||
//[yn,nn]~^^^ ERROR: `~const` is not allowed here
|
||||
|
||||
const fn foo<T: ~const Bar>(x: &T) {
|
||||
//[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
|
||||
//[yn,nn]~^ ERROR: `~const` can only be applied to `#[const_trait]`
|
||||
x.a();
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ note: this trait is not a `#[const_trait]`, so it cannot have `~const` trait bou
|
||||
LL | trait Bar: ~const Foo {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/super-traits-fail-3.rs:17:24
|
||||
|
|
||||
LL | const fn foo<T: ~const Bar>(x: &T) {
|
||||
|
@ -1,6 +0,0 @@
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
const fn tilde_question<T: ~const ?Sized>() {}
|
||||
//~^ ERROR `~const` and `?` are mutually exclusive
|
||||
|
||||
fn main() {}
|
@ -1,8 +0,0 @@
|
||||
error: `~const` and `?` are mutually exclusive
|
||||
--> $DIR/tilde-const-maybe-trait.rs:3:28
|
||||
|
|
||||
LL | const fn tilde_question<T: ~const ?Sized>() {}
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,6 +0,0 @@
|
||||
// compile-flags: -Z parse-only
|
||||
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
struct S<T: const Tr>;
|
||||
//~^ ERROR const bounds must start with `~`
|
@ -1,10 +0,0 @@
|
||||
error: const bounds must start with `~`
|
||||
--> $DIR/without-tilde.rs:5:13
|
||||
|
|
||||
LL | struct S<T: const Tr>;
|
||||
| -^^^^
|
||||
| |
|
||||
| help: add `~`: `~`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -1,16 +1,16 @@
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const_trait_impl.rs:34:16
|
||||
|
|
||||
LL | impl<T: ~const Default> const A for T {
|
||||
| ^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const_trait_impl.rs:40:16
|
||||
|
|
||||
LL | impl<T: ~const Default + ~const Sup> const A for T {
|
||||
| ^^^^^^^
|
||||
|
||||
error: ~const can only be applied to `#[const_trait]` traits
|
||||
error: `~const` can only be applied to `#[const_trait]` traits
|
||||
--> $DIR/const_trait_impl.rs:46:16
|
||||
|
|
||||
LL | impl<T: ~const Default + ~const Sub> const A for T {
|
||||
|
Loading…
Reference in New Issue
Block a user