about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src/traits
diff options
context:
space:
mode:
authorkadmin <julianknodt@gmail.com>2021-09-28 04:10:33 +0000
committerkadmin <julianknodt@gmail.com>2021-10-04 06:49:49 +0000
commit9cb30f465ed07debfdb95bf2457423d1445e737d (patch)
treef2a395362454eca0f680516f8543ff8ba80931c5 /compiler/rustc_trait_selection/src/traits
parent8a12be741290b16c29293f87bdb3e8e5129bd4a9 (diff)
Move generic error message to separate branches
This decomposes an error message in generic constants into more specific branches, for better
readability.
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits')
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs137
1 files changed, 94 insertions, 43 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")?
+            }
         })
     }
 }