about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2021-10-05 12:52:44 -0700
committerGitHub <noreply@github.com>2021-10-05 12:52:44 -0700
commit0352a2820d65159c19e323b519c147d134fbf9f0 (patch)
treec1d674e499c41b620b57197478eaf7f26319ab6f
parent60b9c5d1a98fbeb82b8c229202707a7c59a4526d (diff)
parent9cb30f465ed07debfdb95bf2457423d1445e737d (diff)
downloadrust-0352a2820d65159c19e323b519c147d134fbf9f0.tar.gz
rust-0352a2820d65159c19e323b519c147d134fbf9f0.zip
Rollup merge of #89317 - JulianKnodt:precise_errors, r=BoxyUwU
Move generic error message to separate branches

This decomposes an error message in generic constants into more specific branches, for better
readability.

r? ``@lcnr``
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs137
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr3
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/closures.stderr3
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr6
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr9
-rw-r--r--src/test/ui/const-generics/issues/issue-67375.full.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-2.full.stderr3
7 files changed, 111 insertions, 52 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 24fa5007f1e..25ec9682d84 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -236,16 +236,27 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
         self.body.exprs[self.body_id].span
     }
 
-    fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
+    fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
         self.tcx
             .sess
             .struct_span_err(self.root_span(), "overly complex generic constant")
-            .span_label(span.unwrap_or(self.root_span()), msg)
+            .span_label(span, msg)
             .help("consider moving this anonymous constant into a `const` function")
             .emit();
 
         Err(ErrorReported)
     }
+    fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
+        self.tcx
+            .sess
+            .struct_span_err(self.root_span(), "overly complex generic constant")
+            .span_label(span, msg)
+            .help("consider moving this anonymous constant into a `const` function")
+            .note("this operation may be supported in the future")
+            .emit();
+
+        Err(ErrorReported)
+    }
 
     fn new(
         tcx: TyCtxt<'tcx>,
@@ -337,14 +348,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
         Ok(match &node.kind {
             // I dont know if handling of these 3 is correct
             &ExprKind::Scope { value, .. } => self.recurse_build(value)?,
-            &ExprKind::PlaceTypeAscription { source, .. } |
-            &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
+            &ExprKind::PlaceTypeAscription { source, .. }
+            | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
 
             // subtle: associated consts are literals this arm handles
             // `<T as Trait>::ASSOC` as well as `12`
             &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
 
-            ExprKind::Call { fun, args,  .. } => {
+            ExprKind::Call { fun, args, .. } => {
                 let fun = self.recurse_build(*fun)?;
 
                 let mut new_args = Vec::<NodeId>::with_capacity(args.len());
@@ -353,7 +364,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 }
                 let new_args = self.tcx.arena.alloc_slice(&new_args);
                 self.nodes.push(Node::FunctionCall(fun, new_args))
-            },
+            }
             &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
                 let lhs = self.recurse_build(lhs)?;
                 let rhs = self.recurse_build(rhs)?;
@@ -362,7 +373,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
             &ExprKind::Unary { op, arg } if Self::check_unop(op) => {
                 let arg = self.recurse_build(arg)?;
                 self.nodes.push(Node::UnaryOp(op, arg))
-            },
+            }
             // This is necessary so that the following compiles:
             //
             // ```
@@ -370,60 +381,100 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
             //     bar::<{ N + 1 }>();
             // }
             // ```
-            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
+            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => {
+                self.recurse_build(*e)?
+            }
             // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
             // "coercion cast" i.e. using a coercion or is a no-op.
             // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
             &ExprKind::Use { source } => {
                 let arg = self.recurse_build(source)?;
                 self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
-            },
+            }
             &ExprKind::Cast { source } => {
                 let arg = self.recurse_build(source)?;
                 self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
-            },
+            }
 
             // FIXME(generic_const_exprs): We may want to support these.
             ExprKind::AddressOf { .. }
             | ExprKind::Borrow { .. }
-            | ExprKind::Deref { .. }
-            | ExprKind::Repeat { .. }
-            | ExprKind::Array { .. }
-            | ExprKind::Block { .. }
-            | ExprKind::NeverToAny { .. }
-            | ExprKind::Tuple { .. }
-            | ExprKind::Index { .. }
-            | ExprKind::Field { .. }
-            | ExprKind::ConstBlock { .. }
-            | ExprKind::Adt(_) => self.error(
-                    Some(node.span),
-                    "unsupported operation in generic constant, this may be supported in the future",
+            | ExprKind::Deref { .. } => self.maybe_supported_error(
+                node.span,
+                "dereferencing is not supported in generic constants",
+            )?,
+            ExprKind::Repeat { .. } | ExprKind::Array { .. } =>  self.maybe_supported_error(
+                node.span,
+                "array construction is not supported in generic constants",
+            )?,
+            ExprKind::Block { .. } => self.maybe_supported_error(
+                node.span,
+                "blocks are not supported in generic constant",
+            )?,
+            ExprKind::NeverToAny { .. } => self.maybe_supported_error(
+                node.span,
+                "converting nevers to any is not supported in generic constant",
+            )?,
+            ExprKind::Tuple { .. } => self.maybe_supported_error(
+                node.span,
+                "tuple construction is not supported in generic constants",
+            )?,
+            ExprKind::Index { .. } => self.maybe_supported_error(
+                node.span,
+                "indexing is not supported in generic constant",
+            )?,
+            ExprKind::Field { .. } => self.maybe_supported_error(
+                node.span,
+                "field access is not supported in generic constant",
+            )?,
+            ExprKind::ConstBlock { .. } => self.maybe_supported_error(
+                node.span,
+                "const blocks are not supported in generic constant",
+            )?,
+            ExprKind::Adt(_) => self.maybe_supported_error(
+                node.span,
+                "struct/enum construction is not supported in generic constants",
+            )?,
+            // dont know if this is correct
+            ExprKind::Pointer { .. } =>
+                self.error(node.span, "pointer casts are not allowed in generic constants")?,
+            ExprKind::Yield { .. } =>
+                self.error(node.span, "generator control flow is not allowed in generic constants")?,
+            ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self
+                .error(
+                    node.span,
+                    "loops and loop control flow are not supported in generic constants",
                 )?,
+            ExprKind::Box { .. } =>
+                self.error(node.span, "allocations are not allowed in generic constants")?,
+
+            ExprKind::Unary { .. } => unreachable!(),
+            // we handle valid unary/binary ops above
+            ExprKind::Binary { .. } =>
+                self.error(node.span, "unsupported binary operation in generic constants")?,
+            ExprKind::LogicalOp { .. } =>
+                self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?,
+            ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
+                self.error(node.span, "assignment is not supported in generic constants")?
+            }
+            ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error(
+                node.span,
+                "closures and function keywords are not supported in generic constants",
+            )?,
+            // let expressions imply control flow
+            ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } =>
+                self.error(node.span, "control flow is not supported in generic constants")?,
+            ExprKind::LlvmInlineAsm { .. } | ExprKind::InlineAsm { .. } => {
+                self.error(node.span, "assembly is not supported in generic constants")?
+            }
 
-            ExprKind::Match { .. }
             // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
-            | ExprKind::VarRef { .. }
+            ExprKind::VarRef { .. }
             | ExprKind::UpvarRef { .. }
-            | ExprKind::Closure { .. }
-            | ExprKind::Let { .. } // let expressions imply control flow
-            | ExprKind::Loop { .. }
-            | ExprKind::Assign { .. }
             | ExprKind::StaticRef { .. }
-            | ExprKind::LogicalOp { .. }
-            // we handle valid unary/binary ops above
-            | ExprKind::Unary { .. }
-            | ExprKind::Binary { .. }
-            | ExprKind::Break { .. }
-            | ExprKind::Continue { .. }
-            | ExprKind::If { .. }
-            | ExprKind::Pointer { .. } // dont know if this is correct
-            | ExprKind::ThreadLocalRef(_)
-            | ExprKind::LlvmInlineAsm { .. }
-            | ExprKind::Return { .. }
-            | ExprKind::Box { .. } // allocations not allowed in constants
-            | ExprKind::AssignOp { .. }
-            | ExprKind::InlineAsm { .. }
-            | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
+            | ExprKind::ThreadLocalRef(_) => {
+                self.error(node.span, "unsupported operation in generic constant")?
+            }
         })
     }
 }
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
index 9b3c32a9397..041232e8690 100644
--- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
@@ -10,9 +10,10 @@ error: overly complex generic constant
   --> $DIR/array-size-in-generic-struct-param.rs:19:15
    |
 LL |     arr: [u8; CFG.arr_size],
-   |               ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |               ^^^^^^^^^^^^ field access is not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
index 95dae4ecc04..0dfd804be41 100644
--- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
@@ -4,9 +4,10 @@ error: overly complex generic constant
 LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
    |                                   ^^^^-------^^
    |                                       |
-   |                                       unsupported operation in generic constant, this may be supported in the future
+   |                                       dereferencing is not supported in generic constants
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
index c9f84799522..5ebb4c3999c 100644
--- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
@@ -2,17 +2,19 @@ error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:68
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                                                    ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:35
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                   ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                   ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
index 3da91b19a5e..df73acf53de 100644
--- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
@@ -2,25 +2,28 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:4:34
    |
 LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                  ^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/unused_expr.rs:9:34
    |
 LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                  ^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/unused_expr.rs:16:38
    |
 LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-   |                                      ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                      ^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
index 8c9672fd7fc..0f0e339655b 100644
--- a/src/test/ui/const-generics/issues/issue-67375.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr
@@ -4,7 +4,7 @@ error: overly complex generic constant
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
    |                 ^^---------------------^^
    |                   |
-   |                   unsupported operation in generic constant
+   |                   pointer casts are not allowed in generic constants
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
index fe0351a8292..cce85772aa4 100644
--- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
@@ -8,9 +8,10 @@ LL | |         let x: Option<Box<Self>> = None;
 LL | |
 LL | |         0
 LL | |     }],
-   | |_____^ unsupported operation in generic constant, this may be supported in the future
+   | |_____^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to previous error