diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2021-10-05 12:52:44 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-05 12:52:44 -0700 |
| commit | 0352a2820d65159c19e323b519c147d134fbf9f0 (patch) | |
| tree | c1d674e499c41b620b57197478eaf7f26319ab6f /compiler | |
| parent | 60b9c5d1a98fbeb82b8c229202707a7c59a4526d (diff) | |
| parent | 9cb30f465ed07debfdb95bf2457423d1445e737d (diff) | |
| download | rust-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``
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/const_evaluatable.rs | 137 |
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")? + } }) } } |
