11use std:: assert_matches:: assert_matches;
2+ use std:: ops:: ControlFlow ;
23
34use rustc_ast:: ptr:: P as AstP ;
45use rustc_ast:: * ;
6+ use rustc_ast_pretty:: pprust:: expr_to_string;
57use rustc_data_structures:: stack:: ensure_sufficient_stack;
68use rustc_data_structures:: sync:: Lrc ;
79use rustc_hir as hir;
810use rustc_hir:: HirId ;
911use rustc_hir:: def:: { DefKind , Res } ;
1012use rustc_middle:: span_bug;
13+ use rustc_middle:: ty:: TyCtxt ;
1114use rustc_session:: errors:: report_lit_error;
1215use rustc_span:: source_map:: { Spanned , respan} ;
1316use rustc_span:: symbol:: { Ident , Symbol , kw, sym} ;
1417use rustc_span:: { DUMMY_SP , DesugaringKind , Span } ;
1518use thin_vec:: { ThinVec , thin_vec} ;
19+ use visit:: { Visitor , walk_expr} ;
1620
1721use super :: errors:: {
1822 AsyncCoroutinesNotSupported , AwaitOnlyInAsyncFnAndBlocks , BaseExpressionDoubleDot ,
@@ -23,9 +27,32 @@ use super::errors::{
2327use super :: {
2428 GenericArgsMode , ImplTraitContext , LoweringContext , ParamMode , ResolverAstLoweringExt ,
2529} ;
26- use crate :: errors:: YieldInClosure ;
30+ use crate :: errors:: { InvalidLegacyConstGenericArg , UseConstGenericArg , YieldInClosure } ;
2731use crate :: { AllowReturnTypeNotation , FnDeclKind , ImplTraitPosition , fluent_generated} ;
2832
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+
2956impl < ' hir > LoweringContext < ' _ , ' hir > {
3057 fn lower_exprs ( & mut self , exprs : & [ AstP < Expr > ] ) -> & ' hir [ hir:: Expr < ' hir > ] {
3158 self . arena . alloc_from_iter ( exprs. iter ( ) . map ( |x| self . lower_expr_mut ( x) ) )
@@ -396,10 +423,34 @@ impl<'hir> LoweringContext<'_, 'hir> {
396423 unreachable ! ( ) ;
397424 } ;
398425
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+
399450 // Split the arguments into const generics and normal arguments
400451 let mut real_args = vec ! [ ] ;
401452 let mut generic_args = ThinVec :: new ( ) ;
402- for ( idx, arg) in args. into_iter ( ) . enumerate ( ) {
453+ for ( idx, arg) in args. iter ( ) . cloned ( ) . enumerate ( ) {
403454 if legacy_args_idx. contains ( & idx) {
404455 let parent_def_id = self . current_def_id_parent ;
405456 let node_id = self . next_node_id ( ) ;
@@ -410,7 +461,20 @@ impl<'hir> LoweringContext<'_, 'hir> {
410461 self . create_def ( parent_def_id, node_id, kw:: Empty , DefKind :: AnonConst , f. span ) ;
411462 }
412463
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 } ;
414478 generic_args. push ( AngleBracketedArg :: Arg ( GenericArg :: Const ( anon_const) ) ) ;
415479 } else {
416480 real_args. push ( arg) ;
0 commit comments