1
1
use std:: assert_matches:: assert_matches;
2
+ use std:: ops:: ControlFlow ;
2
3
3
4
use rustc_ast:: ptr:: P as AstP ;
4
5
use rustc_ast:: * ;
6
+ use rustc_ast_pretty:: pprust:: expr_to_string;
5
7
use rustc_data_structures:: stack:: ensure_sufficient_stack;
6
8
use rustc_data_structures:: sync:: Lrc ;
7
9
use rustc_hir as hir;
8
10
use rustc_hir:: HirId ;
9
11
use rustc_hir:: def:: { DefKind , Res } ;
10
12
use rustc_middle:: span_bug;
13
+ use rustc_middle:: ty:: TyCtxt ;
11
14
use rustc_session:: errors:: report_lit_error;
12
15
use rustc_span:: source_map:: { Spanned , respan} ;
13
16
use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
14
17
use rustc_span:: { DUMMY_SP , DesugaringKind , Span } ;
15
18
use thin_vec:: { ThinVec , thin_vec} ;
19
+ use visit:: { Visitor , walk_expr} ;
16
20
17
21
use super :: errors:: {
18
22
AsyncCoroutinesNotSupported , AwaitOnlyInAsyncFnAndBlocks , BaseExpressionDoubleDot ,
@@ -23,9 +27,32 @@ use super::errors::{
23
27
use super :: {
24
28
GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode , ResolverAstLoweringExt ,
25
29
} ;
26
- use crate :: errors:: YieldInClosure ;
30
+ use crate :: errors:: { InvalidLegacyConstGenericArg , UseConstGenericArg , YieldInClosure } ;
27
31
use crate :: { AllowReturnTypeNotation , FnDeclKind , ImplTraitPosition , fluent_generated} ;
28
32
33
+ struct WillCreateDefIdsVisitor { }
34
+
35
+ impl < ' v > rustc_ast:: visit:: Visitor < ' v > for WillCreateDefIdsVisitor {
36
+ type Result = ControlFlow < Span > ;
37
+
38
+ fn visit_anon_const ( & mut self , c : & ' v AnonConst ) -> Self :: Result {
39
+ ControlFlow :: Break ( c. value . span )
40
+ }
41
+
42
+ fn visit_item ( & mut self , item : & ' v Item ) -> Self :: Result {
43
+ ControlFlow :: Break ( item. span )
44
+ }
45
+
46
+ fn visit_expr ( & mut self , ex : & ' v Expr ) -> Self :: Result {
47
+ match ex. kind {
48
+ ExprKind :: Gen ( ..) | ExprKind :: ConstBlock ( ..) | ExprKind :: Closure ( ..) => {
49
+ ControlFlow :: Break ( ex. span )
50
+ }
51
+ _ => walk_expr ( self , ex) ,
52
+ }
53
+ }
54
+ }
55
+
29
56
impl < ' hir > LoweringContext < ' _ , ' hir > {
30
57
fn lower_exprs ( & mut self , exprs : & [ AstP < Expr > ] ) -> & ' hir [ hir:: Expr < ' hir > ] {
31
58
self . arena . alloc_from_iter ( exprs. iter ( ) . map ( |x| self . lower_expr_mut ( x) ) )
@@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
396
423
unreachable ! ( ) ;
397
424
} ;
398
425
426
+ let mut error = None ;
427
+ let mut invalid_expr_error = |tcx : TyCtxt < ' _ > , span| {
428
+ // Avoid emitting the error multiple times.
429
+ if error. is_none ( ) {
430
+ let mut const_args = vec ! [ ] ;
431
+ let mut other_args = vec ! [ ] ;
432
+ for ( idx, arg) in args. iter ( ) . enumerate ( ) {
433
+ if legacy_args_idx. contains ( & idx) {
434
+ const_args. push ( format ! ( "{{ {} }}" , expr_to_string( arg) ) ) ;
435
+ } else {
436
+ other_args. push ( expr_to_string ( arg) ) ;
437
+ }
438
+ }
439
+ let suggestion = UseConstGenericArg {
440
+ end_of_fn : f. span . shrink_to_hi ( ) ,
441
+ const_args : const_args. join ( ", " ) ,
442
+ other_args : other_args. join ( ", " ) ,
443
+ call_args : args[ 0 ] . span . to ( args. last ( ) . unwrap ( ) . span ) ,
444
+ } ;
445
+ error = Some ( tcx. dcx ( ) . emit_err ( InvalidLegacyConstGenericArg { span, suggestion } ) ) ;
446
+ }
447
+ error. unwrap ( )
448
+ } ;
449
+
399
450
// Split the arguments into const generics and normal arguments
400
451
let mut real_args = vec ! [ ] ;
401
452
let mut generic_args = ThinVec :: new ( ) ;
402
- for ( idx, arg) in args. into_iter ( ) . enumerate ( ) {
453
+ for ( idx, arg) in args. iter ( ) . cloned ( ) . enumerate ( ) {
403
454
if legacy_args_idx. contains ( & idx) {
404
455
let parent_def_id = self . current_def_id_parent ;
405
456
let node_id = self . next_node_id ( ) ;
@@ -410,7 +461,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
410
461
self . create_def ( parent_def_id, node_id, kw:: Empty , DefKind :: AnonConst , f. span ) ;
411
462
}
412
463
413
- let anon_const = AnonConst { id : node_id, value : arg } ;
464
+ let mut visitor = WillCreateDefIdsVisitor { } ;
465
+ let const_value = if let ControlFlow :: Break ( span) = visitor. visit_expr ( & arg) {
466
+ AstP ( Expr {
467
+ id : self . next_node_id ( ) ,
468
+ kind : ExprKind :: Err ( invalid_expr_error ( self . tcx , span) ) ,
469
+ span : f. span ,
470
+ attrs : [ ] . into ( ) ,
471
+ tokens : None ,
472
+ } )
473
+ } else {
474
+ arg
475
+ } ;
476
+
477
+ let anon_const = AnonConst { id : node_id, value : const_value } ;
414
478
generic_args. push ( AngleBracketedArg :: Arg ( GenericArg :: Const ( anon_const) ) ) ;
415
479
} else {
416
480
real_args. push ( arg) ;
0 commit comments