@@ -138,6 +138,51 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
138138 ) ;
139139 assert ! ( old_parent. is_none( ) , "parent `LocalDefId` is reset for an invocation" ) ;
140140 }
141+
142+ /// Determines whether the const argument's expression is a simple macro call, optionally
143+ /// surrounded in braces depending on whether a brace has already been unwrapped on this
144+ /// const argument.
145+ ///
146+ /// If this expresion *is* a trivial macro call then the id for the macro call is
147+ /// returned along with the information required to build the anon const's def if
148+ /// the macro call expands to a non-trivial expression.
149+ fn is_const_arg_trivial_macro_expansion (
150+ & self ,
151+ const_arg_expr : & ' a Expr ,
152+ anon_const : Option < & ' a AnonConst > ,
153+ ) -> Option < ( PendingAnonConstInfo , NodeId ) > {
154+ let ( anon_const_id, anon_const_span) = if let Some ( anon_const) = anon_const {
155+ ( anon_const. id , anon_const. value . span )
156+ } else if let Some ( pending_anon) = & self . pending_anon_const_info {
157+ ( pending_anon. id , pending_anon. span )
158+ } else {
159+ panic ! (
160+ "`is_const_arg_trivial_macro_expansion` called without having recursed into anon const"
161+ ) ;
162+ } ;
163+
164+ let ( block_was_stripped, expr) = if self
165+ . pending_anon_const_info
166+ . is_some_and ( |pending_anon| pending_anon. block_was_stripped )
167+ {
168+ ( true , const_arg_expr)
169+ } else {
170+ const_arg_expr. maybe_unwrap_block ( )
171+ } ;
172+
173+ if let Expr { kind : ExprKind :: MacCall ( ..) , id, .. } = expr {
174+ Some ( (
175+ PendingAnonConstInfo {
176+ id : anon_const_id,
177+ span : anon_const_span,
178+ block_was_stripped,
179+ } ,
180+ * id,
181+ ) )
182+ } else {
183+ None
184+ }
185+ }
141186}
142187
143188impl < ' a , ' ra , ' tcx > visit:: Visitor < ' a > for DefCollector < ' a , ' ra , ' tcx > {
@@ -354,12 +399,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
354399 // items will be messed up, but that's ok because there can't be any if we're just looking
355400 // for bare idents.
356401
357- if matches ! ( constant . value . maybe_unwrap_block ( ) . kind , ExprKind :: MacCall ( .. ) ) {
358- // See self.pending_anon_const_info for explanation
359- self . pending_anon_const_info =
360- Some ( PendingAnonConstInfo { id : constant . id , span : constant . value . span } ) ;
361- return visit :: walk_anon_const ( self , constant ) ;
362- } else if constant. value . is_potential_trivial_const_arg ( ) {
402+ if let Some ( ( pending_anon , macro_invoc ) ) =
403+ self . is_const_arg_trivial_macro_expansion ( & * constant . value , Some ( & constant ) )
404+ {
405+ self . pending_anon_const_info = Some ( pending_anon ) ;
406+ return self . visit_macro_invoc ( macro_invoc ) ;
407+ } else if constant. value . is_potential_trivial_const_arg ( true ) {
363408 return visit:: walk_anon_const ( self , constant) ;
364409 }
365410
@@ -368,23 +413,36 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
368413 }
369414
370415 fn visit_expr ( & mut self , expr : & ' a Expr ) {
371- if matches ! ( expr. kind, ExprKind :: MacCall ( ..) ) {
372- return self . visit_macro_invoc ( expr. id ) ;
416+ // If we're visiting the expression of a const argument that was a macro call then
417+ // check if it is *still* unknown whether it is a trivial const arg or not. If so
418+ // recurse into the macro call and delay creating the anon const def until expansion.
419+ if self . pending_anon_const_info . is_some ( )
420+ && let Some ( ( pending_anon, macro_invoc) ) =
421+ self . is_const_arg_trivial_macro_expansion ( expr, None )
422+ {
423+ self . pending_anon_const_info = Some ( pending_anon) ;
424+ return self . visit_macro_invoc ( macro_invoc) ;
373425 }
374426
375- let grandparent_def = if let Some ( pending_anon) = self . pending_anon_const_info . take ( ) {
376- // See self.pending_anon_const_info for explanation
377- if !expr. is_potential_trivial_const_arg ( ) {
427+ // See self.pending_anon_const_info for explanation
428+ let parent_def = self
429+ . pending_anon_const_info
430+ . take ( )
431+ // If we already stripped away a set of braces then do not do it again when determining
432+ // if the macro expanded to a trivial const arg. This arises in cases such as:
433+ // `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a
434+ // trivial const argument even though `{ N }` by itself *is*.
435+ . filter ( |pending_anon| {
436+ !expr. is_potential_trivial_const_arg ( !pending_anon. block_was_stripped )
437+ } )
438+ . map ( |pending_anon| {
378439 self . create_def ( pending_anon. id , kw:: Empty , DefKind :: AnonConst , pending_anon. span )
379- } else {
380- self . parent_def
381- }
382- } else {
383- self . parent_def
384- } ;
440+ } )
441+ . unwrap_or ( self . parent_def ) ;
385442
386- self . with_parent ( grandparent_def , |this| {
443+ self . with_parent ( parent_def , |this| {
387444 let parent_def = match expr. kind {
445+ ExprKind :: MacCall ( ..) => return this. visit_macro_invoc ( expr. id ) ,
388446 ExprKind :: Closure ( ..) | ExprKind :: Gen ( ..) => {
389447 this. create_def ( expr. id , kw:: Empty , DefKind :: Closure , expr. span )
390448 }
0 commit comments