FnParam,
}
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum IsRepeatExpr {
+ No,
+ Yes,
+}
+
impl PatternSource {
fn descr(self) -> &'static str {
match self {
self.resolve_block(block);
}
fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
- debug!("visit_anon_const {:?}", constant);
- self.with_constant_rib(constant.value.is_potential_trivial_const_param(), |this| {
- visit::walk_anon_const(this, constant);
- });
+ // We deal with repeat expressions explicitly in `resolve_expr`.
+ self.resolve_anon_const(constant, IsRepeatExpr::No);
}
fn visit_expr(&mut self, expr: &'ast Expr) {
self.resolve_expr(expr, None);
if !check_ns(TypeNS) && check_ns(ValueNS) {
// This must be equivalent to `visit_anon_const`, but we cannot call it
// directly due to visitor lifetimes so we have to copy-paste some code.
- self.with_constant_rib(true, |this| {
+ //
+ // Note that we might not be inside of an repeat expression here,
+ // but considering that `IsRepeatExpr` is only relevant for
+ // non-trivial constants this is doesn't matter.
+ self.with_constant_rib(IsRepeatExpr::No, true, |this| {
this.smart_resolve_path(
ty.id,
qself.as_ref(),
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
- this.with_constant_rib(true, |this| {
- this.visit_expr(expr)
- });
+ this.with_constant_rib(
+ IsRepeatExpr::No,
+ true,
+ |this| this.visit_expr(expr),
+ );
}
}
AssocItemKind::Fn(_, _, generics, _) => {
self.with_item_rib(HasGenericParams::No, |this| {
this.visit_ty(ty);
if let Some(expr) = expr {
- this.with_constant_rib(expr.is_potential_trivial_const_param(), |this| {
+ // We already forbid generic params because of the above item rib,
+ // so it doesn't matter whether this is a trivial constant.
+ this.with_constant_rib(IsRepeatExpr::No, true, |this| {
this.visit_expr(expr)
});
}
self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
}
- fn with_constant_rib(&mut self, trivial: bool, f: impl FnOnce(&mut Self)) {
- debug!("with_constant_rib");
- self.with_rib(ValueNS, ConstantItemRibKind(trivial), |this| {
- this.with_rib(TypeNS, ConstantItemRibKind(trivial), |this| {
- this.with_label_rib(ConstantItemRibKind(trivial), f);
- })
+ // HACK(min_const_generics,const_evaluatable_unchecked): We
+ // want to keep allowing `[0; std::mem::size_of::<*mut T>()]`
+ // with a future compat lint for now. We do this by adding an
+ // additional special case for repeat expressions.
+ //
+ // Note that we intentionally still forbid `[0; N + 1]` during
+ // name resolution so that we don't extend the future
+ // compat lint to new cases.
+ fn with_constant_rib(
+ &mut self,
+ is_repeat: IsRepeatExpr,
+ is_trivial: bool,
+ f: impl FnOnce(&mut Self),
+ ) {
+ debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial);
+ self.with_rib(ValueNS, ConstantItemRibKind(is_trivial), |this| {
+ this.with_rib(
+ TypeNS,
+ ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial),
+ |this| {
+ this.with_label_rib(ConstantItemRibKind(is_trivial), f);
+ },
+ )
});
}
//
// Type parameters can already be used and as associated consts are
// not used as part of the type system, this is far less surprising.
- this.with_constant_rib(true, |this| {
- visit::walk_assoc_item(this, item, AssocCtxt::Impl)
- });
+ this.with_constant_rib(
+ IsRepeatExpr::No,
+ true,
+ |this| {
+ visit::walk_assoc_item(
+ this,
+ item,
+ AssocCtxt::Impl,
+ )
+ },
+ );
}
AssocItemKind::Fn(_, _, generics, _) => {
// We also need a new scope for the impl item type parameters.
debug!("(resolving block) leaving block");
}
+ fn resolve_anon_const(&mut self, constant: &'ast AnonConst, is_repeat: IsRepeatExpr) {
+ debug!("resolve_anon_const {:?} is_repeat: {:?}", constant, is_repeat);
+ self.with_constant_rib(
+ is_repeat,
+ constant.value.is_potential_trivial_const_param(),
+ |this| {
+ visit::walk_anon_const(this, constant);
+ },
+ );
+ }
+
fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
// First, record candidate traits for this expression if it could
// result in the invocation of a method call.
ExprKind::Async(..) | ExprKind::Closure(..) => {
self.with_label_rib(ClosureOrAsyncRibKind, |this| visit::walk_expr(this, expr));
}
+ ExprKind::Repeat(ref elem, ref ct) => {
+ self.visit_expr(elem);
+ self.resolve_anon_const(ct, IsRepeatExpr::Yes);
+ }
_ => {
visit::walk_expr(self, expr);
}
-error: generic `Self` types are currently not permitted in anonymous constants
+error[E0308]: mismatched types
+ --> $DIR/issue-62504.rs:19:21
+ |
+LL | ArrayHolder([0; Self::SIZE])
+ | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE`
+ |
+ = note: expected array `[u32; X]`
+ found array `[u32; _]`
+
+error: constant expression depends on a generic parameter
--> $DIR/issue-62504.rs:19:25
|
LL | ArrayHolder([0; Self::SIZE])
| ^^^^^^^^^^
|
-note: not a concrete type
- --> $DIR/issue-62504.rs:17:22
- |
-LL | impl<const X: usize> ArrayHolder<X> {
- | ^^^^^^^^^^^^^^
+ = note: this may fail depending on what value the parameter takes
-error: aborting due to previous error
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0308`.
impl<const X: usize> ArrayHolder<X> {
pub const fn new() -> Self {
ArrayHolder([0; Self::SIZE])
- //[full]~^ ERROR constant expression depends on a generic parameter
- //[min]~^^ ERROR generic `Self` types are currently
+ //~^ ERROR constant expression depends on a generic parameter
+ //[min]~| ERROR mismatched types
}
}
-error: generic parameters may not be used in const operations
- --> $DIR/issue-67739.rs:12:30
+error: constant expression depends on a generic parameter
+ --> $DIR/issue-67739.rs:12:15
|
LL | [0u8; mem::size_of::<Self::Associated>()];
- | ^^^^^^^^^^^^^^^^ cannot perform const operation using `Self`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: type parameters may not be used in const expressions
+ = note: this may fail depending on what value the parameter takes
error: aborting due to previous error
fn associated_size(&self) -> usize {
[0u8; mem::size_of::<Self::Associated>()];
- //[full]~^ ERROR constant expression depends on a generic parameter
- //[min]~^^ ERROR generic parameters may not be used in const operations
+ //~^ ERROR constant expression depends on a generic parameter
0
}
}
#![feature(min_const_generics)]
+use std::mem::size_of;
+
fn test<const N: usize>() {}
fn ok<const M: usize>() -> [u8; M] {
//~^ ERROR generic parameters may not be used in const operations
}
+struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
+//~^ ERROR generic parameters may not be used in const operations
+
+struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
+//~^ ERROR generic parameters may not be used in const operations
+
+fn break_ty2<T>() {
+ let _: [u8; size_of::<*mut T>() + 1];
+ //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn break_ty3<T>() {
+ let _ = [0; size_of::<*mut T>() + 1];
+ //~^ WARN cannot use constants which depend on generic parameters in types
+ //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+
trait Foo {
const ASSOC: usize;
}
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:9:38
+ --> $DIR/complex-expression.rs:11:38
|
LL | struct Break0<const N: usize>([u8; { N + 1 }]);
| ^ cannot perform const operation using `N`
= help: const parameters may only be used as standalone arguments, i.e. `N`
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:12:40
+ --> $DIR/complex-expression.rs:14:40
|
LL | struct Break1<const N: usize>([u8; { { N } }]);
| ^ cannot perform const operation using `N`
= help: const parameters may only be used as standalone arguments, i.e. `N`
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:16:17
+ --> $DIR/complex-expression.rs:18:17
|
LL | let _: [u8; N + 1];
| ^ cannot perform const operation using `N`
= help: const parameters may only be used as standalone arguments, i.e. `N`
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:21:17
+ --> $DIR/complex-expression.rs:23:17
|
LL | let _ = [0; N + 1];
| ^ cannot perform const operation using `N`
|
= help: const parameters may only be used as standalone arguments, i.e. `N`
-error: aborting due to 4 previous errors
+error: generic parameters may not be used in const operations
+ --> $DIR/complex-expression.rs:27:45
+ |
+LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+
+error: generic parameters may not be used in const operations
+ --> $DIR/complex-expression.rs:30:47
+ |
+LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+
+error: generic parameters may not be used in const operations
+ --> $DIR/complex-expression.rs:34:32
+ |
+LL | let _: [u8; size_of::<*mut T>() + 1];
+ | ^ cannot perform const operation using `T`
+ |
+ = note: type parameters may not be used in const expressions
+
+warning: cannot use constants which depend on generic parameters in types
+ --> $DIR/complex-expression.rs:39:17
+ |
+LL | let _ = [0; size_of::<*mut T>() + 1];
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+error: aborting due to 7 previous errors; 1 warning emitted
--- /dev/null
+// check-pass
+#![allow(dead_code)]
+
+fn foo<T>() {
+ [0; std::mem::size_of::<*mut T>()];
+ //~^ WARN cannot use constants which depend on generic parameters in types
+ //~| WARN this was previously accepted by the compiler but is being phased out
+}
+
+struct Foo<T>(T);
+
+impl<T> Foo<T> {
+ const ASSOC: usize = 4;
+
+ fn test() {
+ [0; Self::ASSOC];
+ //~^ WARN cannot use constants which depend on generic parameters in types
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ }
+}
+
+fn main() {}
--- /dev/null
+warning: cannot use constants which depend on generic parameters in types
+ --> $DIR/const-evaluatable-unchecked.rs:5:9
+ |
+LL | [0; std::mem::size_of::<*mut T>()];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+warning: cannot use constants which depend on generic parameters in types
+ --> $DIR/const-evaluatable-unchecked.rs:16:13
+ |
+LL | [0; Self::ASSOC];
+ | ^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+
+warning: 2 warnings emitted
+