Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move generic error message to separate branches #89317

Merged
merged 1 commit into from
Oct 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 94 additions & 43 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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());
Expand All @@ -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)?;
Expand All @@ -362,68 +373,108 @@ 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:
//
// ```
// fn foo<const N: usize>(a: [(); N + 1]) {
// 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")?
}
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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

2 changes: 1 addition & 1 deletion src/test/ui/const-generics/issues/issue-67375.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/const-generics/issues/issue-67945-2.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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