Skip to content

Commit 9cb30f4

Browse files
committedOct 4, 2021
Move generic error message to separate branches
This decomposes an error message in generic constants into more specific branches, for better readability.
·
1.89.01.57.0
1 parent 8a12be7 commit 9cb30f4

File tree

7 files changed

+111
-52
lines changed

7 files changed

+111
-52
lines changed
 

‎compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 94 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -236,16 +236,27 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
236236
self.body.exprs[self.body_id].span
237237
}
238238

239-
fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
239+
fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
240240
self.tcx
241241
.sess
242242
.struct_span_err(self.root_span(), "overly complex generic constant")
243-
.span_label(span.unwrap_or(self.root_span()), msg)
243+
.span_label(span, msg)
244244
.help("consider moving this anonymous constant into a `const` function")
245245
.emit();
246246

247247
Err(ErrorReported)
248248
}
249+
fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
250+
self.tcx
251+
.sess
252+
.struct_span_err(self.root_span(), "overly complex generic constant")
253+
.span_label(span, msg)
254+
.help("consider moving this anonymous constant into a `const` function")
255+
.note("this operation may be supported in the future")
256+
.emit();
257+
258+
Err(ErrorReported)
259+
}
249260

250261
fn new(
251262
tcx: TyCtxt<'tcx>,
@@ -337,14 +348,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
337348
Ok(match &node.kind {
338349
// I dont know if handling of these 3 is correct
339350
&ExprKind::Scope { value, .. } => self.recurse_build(value)?,
340-
&ExprKind::PlaceTypeAscription { source, .. } |
341-
&ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
351+
&ExprKind::PlaceTypeAscription { source, .. }
352+
| &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
342353

343354
// subtle: associated consts are literals this arm handles
344355
// `<T as Trait>::ASSOC` as well as `12`
345356
&ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
346357

347-
ExprKind::Call { fun, args, .. } => {
358+
ExprKind::Call { fun, args, .. } => {
348359
let fun = self.recurse_build(*fun)?;
349360

350361
let mut new_args = Vec::<NodeId>::with_capacity(args.len());
@@ -353,7 +364,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
353364
}
354365
let new_args = self.tcx.arena.alloc_slice(&new_args);
355366
self.nodes.push(Node::FunctionCall(fun, new_args))
356-
},
367+
}
357368
&ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
358369
let lhs = self.recurse_build(lhs)?;
359370
let rhs = self.recurse_build(rhs)?;
@@ -362,68 +373,108 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
362373
&ExprKind::Unary { op, arg } if Self::check_unop(op) => {
363374
let arg = self.recurse_build(arg)?;
364375
self.nodes.push(Node::UnaryOp(op, arg))
365-
},
376+
}
366377
// This is necessary so that the following compiles:
367378
//
368379
// ```
369380
// fn foo<const N: usize>(a: [(); N + 1]) {
370381
// bar::<{ N + 1 }>();
371382
// }
372383
// ```
373-
ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
384+
ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => {
385+
self.recurse_build(*e)?
386+
}
374387
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
375388
// "coercion cast" i.e. using a coercion or is a no-op.
376389
// This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
377390
&ExprKind::Use { source } => {
378391
let arg = self.recurse_build(source)?;
379392
self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
380-
},
393+
}
381394
&ExprKind::Cast { source } => {
382395
let arg = self.recurse_build(source)?;
383396
self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
384-
},
397+
}
385398

386399
// FIXME(generic_const_exprs): We may want to support these.
387400
ExprKind::AddressOf { .. }
388401
| ExprKind::Borrow { .. }
389-
| ExprKind::Deref { .. }
390-
| ExprKind::Repeat { .. }
391-
| ExprKind::Array { .. }
392-
| ExprKind::Block { .. }
393-
| ExprKind::NeverToAny { .. }
394-
| ExprKind::Tuple { .. }
395-
| ExprKind::Index { .. }
396-
| ExprKind::Field { .. }
397-
| ExprKind::ConstBlock { .. }
398-
| ExprKind::Adt(_) => self.error(
399-
Some(node.span),
400-
"unsupported operation in generic constant, this may be supported in the future",
402+
| ExprKind::Deref { .. } => self.maybe_supported_error(
403+
node.span,
404+
"dereferencing is not supported in generic constants",
405+
)?,
406+
ExprKind::Repeat { .. } | ExprKind::Array { .. } => self.maybe_supported_error(
407+
node.span,
408+
"array construction is not supported in generic constants",
409+
)?,
410+
ExprKind::Block { .. } => self.maybe_supported_error(
411+
node.span,
412+
"blocks are not supported in generic constant",
413+
)?,
414+
ExprKind::NeverToAny { .. } => self.maybe_supported_error(
415+
node.span,
416+
"converting nevers to any is not supported in generic constant",
417+
)?,
418+
ExprKind::Tuple { .. } => self.maybe_supported_error(
419+
node.span,
420+
"tuple construction is not supported in generic constants",
421+
)?,
422+
ExprKind::Index { .. } => self.maybe_supported_error(
423+
node.span,
424+
"indexing is not supported in generic constant",
425+
)?,
426+
ExprKind::Field { .. } => self.maybe_supported_error(
427+
node.span,
428+
"field access is not supported in generic constant",
429+
)?,
430+
ExprKind::ConstBlock { .. } => self.maybe_supported_error(
431+
node.span,
432+
"const blocks are not supported in generic constant",
433+
)?,
434+
ExprKind::Adt(_) => self.maybe_supported_error(
435+
node.span,
436+
"struct/enum construction is not supported in generic constants",
437+
)?,
438+
// dont know if this is correct
439+
ExprKind::Pointer { .. } =>
440+
self.error(node.span, "pointer casts are not allowed in generic constants")?,
441+
ExprKind::Yield { .. } =>
442+
self.error(node.span, "generator control flow is not allowed in generic constants")?,
443+
ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self
444+
.error(
445+
node.span,
446+
"loops and loop control flow are not supported in generic constants",
401447
)?,
448+
ExprKind::Box { .. } =>
449+
self.error(node.span, "allocations are not allowed in generic constants")?,
450+
451+
ExprKind::Unary { .. } => unreachable!(),
452+
// we handle valid unary/binary ops above
453+
ExprKind::Binary { .. } =>
454+
self.error(node.span, "unsupported binary operation in generic constants")?,
455+
ExprKind::LogicalOp { .. } =>
456+
self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?,
457+
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
458+
self.error(node.span, "assignment is not supported in generic constants")?
459+
}
460+
ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error(
461+
node.span,
462+
"closures and function keywords are not supported in generic constants",
463+
)?,
464+
// let expressions imply control flow
465+
ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } =>
466+
self.error(node.span, "control flow is not supported in generic constants")?,
467+
ExprKind::LlvmInlineAsm { .. } | ExprKind::InlineAsm { .. } => {
468+
self.error(node.span, "assembly is not supported in generic constants")?
469+
}
402470

403-
ExprKind::Match { .. }
404471
// we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
405-
| ExprKind::VarRef { .. }
472+
ExprKind::VarRef { .. }
406473
| ExprKind::UpvarRef { .. }
407-
| ExprKind::Closure { .. }
408-
| ExprKind::Let { .. } // let expressions imply control flow
409-
| ExprKind::Loop { .. }
410-
| ExprKind::Assign { .. }
411474
| ExprKind::StaticRef { .. }
412-
| ExprKind::LogicalOp { .. }
413-
// we handle valid unary/binary ops above
414-
| ExprKind::Unary { .. }
415-
| ExprKind::Binary { .. }
416-
| ExprKind::Break { .. }
417-
| ExprKind::Continue { .. }
418-
| ExprKind::If { .. }
419-
| ExprKind::Pointer { .. } // dont know if this is correct
420-
| ExprKind::ThreadLocalRef(_)
421-
| ExprKind::LlvmInlineAsm { .. }
422-
| ExprKind::Return { .. }
423-
| ExprKind::Box { .. } // allocations not allowed in constants
424-
| ExprKind::AssignOp { .. }
425-
| ExprKind::InlineAsm { .. }
426-
| ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
475+
| ExprKind::ThreadLocalRef(_) => {
476+
self.error(node.span, "unsupported operation in generic constant")?
477+
}
427478
})
428479
}
429480
}

‎src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ error: overly complex generic constant
1010
--> $DIR/array-size-in-generic-struct-param.rs:19:15
1111
|
1212
LL | arr: [u8; CFG.arr_size],
13-
| ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
13+
| ^^^^^^^^^^^^ field access is not supported in generic constant
1414
|
1515
= help: consider moving this anonymous constant into a `const` function
16+
= note: this operation may be supported in the future
1617

1718
error: aborting due to 2 previous errors
1819

‎src/test/ui/const-generics/generic_const_exprs/closures.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ error: overly complex generic constant
44
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
55
| ^^^^-------^^
66
| |
7-
| unsupported operation in generic constant, this may be supported in the future
7+
| dereferencing is not supported in generic constants
88
|
99
= help: consider moving this anonymous constant into a `const` function
10+
= note: this operation may be supported in the future
1011

1112
error: aborting due to previous error
1213

‎src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@ error: overly complex generic constant
22
--> $DIR/let-bindings.rs:6:68
33
|
44
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
5-
| ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
5+
| ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
66
|
77
= help: consider moving this anonymous constant into a `const` function
8+
= note: this operation may be supported in the future
89

910
error: overly complex generic constant
1011
--> $DIR/let-bindings.rs:6:35
1112
|
1213
LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
13-
| ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
14+
| ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
1415
|
1516
= help: consider moving this anonymous constant into a `const` function
17+
= note: this operation may be supported in the future
1618

1719
error: aborting due to 2 previous errors
1820

‎src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,28 @@ error: overly complex generic constant
22
--> $DIR/unused_expr.rs:4:34
33
|
44
LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
5-
| ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
5+
| ^^^^^^^^^^^^ blocks are not supported in generic constant
66
|
77
= help: consider moving this anonymous constant into a `const` function
8+
= note: this operation may be supported in the future
89

910
error: overly complex generic constant
1011
--> $DIR/unused_expr.rs:9:34
1112
|
1213
LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
13-
| ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
14+
| ^^^^^^^^^^^^ blocks are not supported in generic constant
1415
|
1516
= help: consider moving this anonymous constant into a `const` function
17+
= note: this operation may be supported in the future
1618

1719
error: overly complex generic constant
1820
--> $DIR/unused_expr.rs:16:38
1921
|
2022
LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
21-
| ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
23+
| ^^^^^^^^^^^^^ blocks are not supported in generic constant
2224
|
2325
= help: consider moving this anonymous constant into a `const` function
26+
= note: this operation may be supported in the future
2427

2528
error: aborting due to 3 previous errors
2629

‎src/test/ui/const-generics/issues/issue-67375.full.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: overly complex generic constant
44
LL | inner: [(); { [|_: &T| {}; 0].len() }],
55
| ^^---------------^^^^^^^^
66
| |
7-
| unsupported operation in generic constant
7+
| pointer casts are not allowed in generic constants
88
|
99
= help: consider moving this anonymous constant into a `const` function
1010

‎src/test/ui/const-generics/issues/issue-67945-2.full.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ LL | | let x: Option<Box<Self>> = None;
88
LL | |
99
LL | | 0
1010
LL | | }],
11-
| |_____^ unsupported operation in generic constant, this may be supported in the future
11+
| |_____^ blocks are not supported in generic constant
1212
|
1313
= help: consider moving this anonymous constant into a `const` function
14+
= note: this operation may be supported in the future
1415

1516
error: aborting due to previous error
1617

0 commit comments

Comments
 (0)
Please sign in to comment.