@@ -276,7 +276,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
276
276
&& let ty:: Adt ( adt_def, args) = ty. kind ( )
277
277
{
278
278
let def_id = adt_def. did ( ) ;
279
- // If any sub type reference the original type definition and the sub type has a type
279
+ // If any child type references the original type definition and the child type has a type
280
280
// parameter that strictly contains the original parameter, the original type is a recursive
281
281
// type that can expanding indefinitely. Example,
282
282
// ```
@@ -285,21 +285,43 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
285
285
// Item(T),
286
286
// }
287
287
// ```
288
- let is_expanding_recursive = adt_def. is_enum ( )
289
- && debug_context ( cx) . adt_stack . borrow ( ) . iter ( ) . any ( |( parent_def_id, parent_args) | {
290
- if def_id == * parent_def_id {
291
- args. iter ( ) . zip ( parent_args. iter ( ) ) . any ( |( arg, parent_arg) | {
292
- if let ( Some ( arg) , Some ( parent_arg) ) = ( arg. as_type ( ) , parent_arg. as_type ( ) )
293
- {
294
- arg != parent_arg && arg. contains ( parent_arg)
295
- } else {
296
- false
297
- }
298
- } )
299
- } else {
300
- false
301
- }
302
- } ) ;
288
+ let is_expanding_recursive = {
289
+ let stack = debug_context ( cx) . adt_stack . borrow ( ) ;
290
+ stack
291
+ . iter ( )
292
+ . enumerate ( )
293
+ . rev ( )
294
+ . skip ( 1 )
295
+ . filter ( |( _, ( ancestor_def_id, _) ) | def_id == * ancestor_def_id)
296
+ . any ( |( ancestor_index, ( _, ancestor_args) ) | {
297
+ args. iter ( )
298
+ . zip ( ancestor_args. iter ( ) )
299
+ . filter_map ( |( arg, ancestor_arg) | arg. as_type ( ) . zip ( ancestor_arg. as_type ( ) ) )
300
+ . any ( |( arg, ancestor_arg) |
301
+ // Strictly contains.
302
+ ( arg != ancestor_arg && arg. contains ( ancestor_arg) )
303
+ // Check all types between current and ancestor use the
304
+ // ancestor_arg.
305
+ // Otherwise, duplicate wrappers in normal recursive type may be
306
+ // regarded as expanding.
307
+ // ```
308
+ // struct Recursive {
309
+ // a: Box<Box<Recursive>>,
310
+ // }
311
+ // ```
312
+ // It can produce an ADT stack like this,
313
+ // - Box<Recursive>
314
+ // - Recursive
315
+ // - Box<Box<Recursive>>
316
+ && stack[ ancestor_index + 1 ..stack. len ( ) ] . iter ( ) . all (
317
+ |( _, intermediate_args) |
318
+ intermediate_args
319
+ . iter ( )
320
+ . filter_map ( |arg| arg. as_type ( ) )
321
+ . any ( |mid_arg| mid_arg. contains ( ancestor_arg) )
322
+ ) )
323
+ } )
324
+ } ;
303
325
if is_expanding_recursive {
304
326
// FIXME: indicate that this is an expanding recursive type in stub metadata?
305
327
return DINodeCreationResult :: new ( stub_info. metadata , false ) ;
0 commit comments