@@ -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}
0 commit comments