@@ -236,16 +236,27 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
236
236
self . body . exprs [ self . body_id ] . span
237
237
}
238
238
239
- fn error ( & mut self , span : Option < Span > , msg : & str ) -> Result < !, ErrorReported > {
239
+ fn error ( & mut self , span : Span , msg : & str ) -> Result < !, ErrorReported > {
240
240
self . tcx
241
241
. sess
242
242
. 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)
244
244
. help ( "consider moving this anonymous constant into a `const` function" )
245
245
. emit ( ) ;
246
246
247
247
Err ( ErrorReported )
248
248
}
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
+ }
249
260
250
261
fn new (
251
262
tcx : TyCtxt < ' tcx > ,
@@ -337,14 +348,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
337
348
Ok ( match & node. kind {
338
349
// I dont know if handling of these 3 is correct
339
350
& 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) ?,
342
353
343
354
// subtle: associated consts are literals this arm handles
344
355
// `<T as Trait>::ASSOC` as well as `12`
345
356
& ExprKind :: Literal { literal, .. } => self . nodes . push ( Node :: Leaf ( literal) ) ,
346
357
347
- ExprKind :: Call { fun, args, .. } => {
358
+ ExprKind :: Call { fun, args, .. } => {
348
359
let fun = self . recurse_build ( * fun) ?;
349
360
350
361
let mut new_args = Vec :: < NodeId > :: with_capacity ( args. len ( ) ) ;
@@ -353,7 +364,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
353
364
}
354
365
let new_args = self . tcx . arena . alloc_slice ( & new_args) ;
355
366
self . nodes . push ( Node :: FunctionCall ( fun, new_args) )
356
- } ,
367
+ }
357
368
& ExprKind :: Binary { op, lhs, rhs } if Self :: check_binop ( op) => {
358
369
let lhs = self . recurse_build ( lhs) ?;
359
370
let rhs = self . recurse_build ( rhs) ?;
@@ -362,68 +373,108 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
362
373
& ExprKind :: Unary { op, arg } if Self :: check_unop ( op) => {
363
374
let arg = self . recurse_build ( arg) ?;
364
375
self . nodes . push ( Node :: UnaryOp ( op, arg) )
365
- } ,
376
+ }
366
377
// This is necessary so that the following compiles:
367
378
//
368
379
// ```
369
380
// fn foo<const N: usize>(a: [(); N + 1]) {
370
381
// bar::<{ N + 1 }>();
371
382
// }
372
383
// ```
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
+ }
374
387
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
375
388
// "coercion cast" i.e. using a coercion or is a no-op.
376
389
// This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
377
390
& ExprKind :: Use { source } => {
378
391
let arg = self . recurse_build ( source) ?;
379
392
self . nodes . push ( Node :: Cast ( abstract_const:: CastKind :: Use , arg, node. ty ) )
380
- } ,
393
+ }
381
394
& ExprKind :: Cast { source } => {
382
395
let arg = self . recurse_build ( source) ?;
383
396
self . nodes . push ( Node :: Cast ( abstract_const:: CastKind :: As , arg, node. ty ) )
384
- } ,
397
+ }
385
398
386
399
// FIXME(generic_const_exprs): We may want to support these.
387
400
ExprKind :: AddressOf { .. }
388
401
| 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" ,
401
447
) ?,
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
+ }
402
470
403
- ExprKind :: Match { .. }
404
471
// we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
405
- | ExprKind :: VarRef { .. }
472
+ ExprKind :: VarRef { .. }
406
473
| ExprKind :: UpvarRef { .. }
407
- | ExprKind :: Closure { .. }
408
- | ExprKind :: Let { .. } // let expressions imply control flow
409
- | ExprKind :: Loop { .. }
410
- | ExprKind :: Assign { .. }
411
474
| 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
+ }
427
478
} )
428
479
}
429
480
}
0 commit comments