@@ -2257,8 +2257,33 @@ pub fn fnc_typetrees<'tcx>(tcx: TyCtxt<'tcx>, fn_ty: Ty<'tcx>) -> FncTree {
2257
2257
2258
2258
/// Generate TypeTree for a specific type.
2259
2259
/// This function analyzes a Rust type and creates appropriate TypeTree metadata.
2260
+
2261
+ /// Maximum recursion depth for TypeTree generation to prevent stack overflow
2262
+ /// from pathological deeply nested types. Combined with cycle detection.
2263
+ const MAX_TYPETREE_DEPTH : usize = 32 ;
2264
+
2260
2265
pub fn typetree_from_ty < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> TypeTree {
2261
- if ty. is_scalar ( ) {
2266
+ let mut visited = Vec :: new ( ) ;
2267
+ typetree_from_ty_impl ( tcx, ty, 0 , & mut visited)
2268
+ }
2269
+
2270
+ fn typetree_from_ty_impl < ' tcx > (
2271
+ tcx : TyCtxt < ' tcx > ,
2272
+ ty : Ty < ' tcx > ,
2273
+ depth : usize ,
2274
+ visited : & mut Vec < Ty < ' tcx > > ,
2275
+ ) -> TypeTree {
2276
+ if depth > MAX_TYPETREE_DEPTH {
2277
+ return TypeTree :: new ( ) ;
2278
+ }
2279
+
2280
+ if visited. contains ( & ty) {
2281
+ return TypeTree :: new ( ) ;
2282
+ }
2283
+
2284
+ visited. push ( ty) ;
2285
+
2286
+ let result = if ty. is_scalar ( ) {
2262
2287
let ( kind, size) = if ty. is_integral ( ) || ty. is_char ( ) || ty. is_bool ( ) {
2263
2288
( Kind :: Integer , ty. primitive_size ( tcx) . bytes_usize ( ) )
2264
2289
} else if ty. is_floating_point ( ) {
@@ -2267,116 +2292,118 @@ pub fn typetree_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> TypeTree {
2267
2292
x if x == tcx. types . f32 => ( Kind :: Float , 4 ) ,
2268
2293
x if x == tcx. types . f64 => ( Kind :: Double , 8 ) ,
2269
2294
x if x == tcx. types . f128 => ( Kind :: F128 , 16 ) ,
2270
- _ => return TypeTree :: new ( ) ,
2295
+ _ => ( Kind :: Integer , 0 ) ,
2271
2296
}
2272
2297
} else {
2273
- return TypeTree :: new ( ) ;
2298
+ ( Kind :: Integer , 0 )
2274
2299
} ;
2275
2300
2276
- return TypeTree ( vec ! [ Type { offset: -1 , size, kind, child: TypeTree :: new( ) } ] ) ;
2277
- }
2278
-
2279
- if ty. is_ref ( ) || ty. is_raw_ptr ( ) || ty. is_box ( ) {
2280
- let inner_ty = if let Some ( inner) = ty. builtin_deref ( true ) {
2281
- inner
2301
+ if size > 0 {
2302
+ TypeTree ( vec ! [ Type { offset: -1 , size, kind, child: TypeTree :: new( ) } ] )
2282
2303
} else {
2283
- return TypeTree :: new ( ) ;
2284
- } ;
2285
-
2286
- let child = typetree_from_ty ( tcx, inner_ty) ;
2287
- return TypeTree ( vec ! [ Type {
2288
- offset: -1 ,
2289
- size: tcx. data_layout. pointer_size( ) . bytes_usize( ) ,
2290
- kind: Kind :: Pointer ,
2291
- child,
2292
- } ] ) ;
2293
- }
2294
-
2295
- if ty. is_array ( ) {
2304
+ TypeTree :: new ( )
2305
+ }
2306
+ } else if ty. is_ref ( ) || ty. is_raw_ptr ( ) || ty. is_box ( ) {
2307
+ if let Some ( inner_ty) = ty. builtin_deref ( true ) {
2308
+ let child = typetree_from_ty_impl ( tcx, inner_ty, depth + 1 , visited) ;
2309
+ TypeTree ( vec ! [ Type {
2310
+ offset: -1 ,
2311
+ size: tcx. data_layout. pointer_size( ) . bytes_usize( ) ,
2312
+ kind: Kind :: Pointer ,
2313
+ child,
2314
+ } ] )
2315
+ } else {
2316
+ TypeTree :: new ( )
2317
+ }
2318
+ } else if ty. is_array ( ) {
2296
2319
if let ty:: Array ( element_ty, len_const) = ty. kind ( ) {
2297
2320
let len = len_const. try_to_target_usize ( tcx) . unwrap_or ( 0 ) ;
2298
2321
if len == 0 {
2299
- return TypeTree :: new ( ) ;
2300
- }
2301
-
2302
- let element_tree = typetree_from_ty ( tcx, * element_ty) ;
2303
-
2304
- let element_layout = tcx
2305
- . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( * element_ty) )
2306
- . ok ( )
2307
- . map ( |layout| layout. size . bytes_usize ( ) )
2308
- . unwrap_or ( 0 ) ;
2309
-
2310
- if element_layout == 0 {
2311
- return TypeTree :: new ( ) ;
2322
+ TypeTree :: new ( )
2323
+ } else {
2324
+ let element_tree = typetree_from_ty_impl ( tcx, * element_ty, depth + 1 , visited) ;
2325
+ let element_layout = tcx
2326
+ . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( * element_ty) )
2327
+ . ok ( )
2328
+ . map ( |layout| layout. size . bytes_usize ( ) )
2329
+ . unwrap_or ( 0 ) ;
2330
+
2331
+ if element_layout == 0 {
2332
+ TypeTree :: new ( )
2333
+ } else {
2334
+ // For homogeneous arrays, use offset -1 instead of individual entries
2335
+ if element_tree. 0 . len ( ) == 1 && element_tree. 0 [ 0 ] . offset == -1 {
2336
+ TypeTree ( vec ! [ Type {
2337
+ offset: -1 ,
2338
+ size: element_tree. 0 [ 0 ] . size,
2339
+ kind: element_tree. 0 [ 0 ] . kind,
2340
+ child: element_tree. 0 [ 0 ] . child. clone( ) ,
2341
+ } ] )
2342
+ } else {
2343
+ let mut types = Vec :: new ( ) ;
2344
+ for i in 0 ..len {
2345
+ let base_offset = ( i as usize * element_layout) as isize ;
2346
+
2347
+ for elem_type in & element_tree. 0 {
2348
+ types. push ( Type {
2349
+ offset : if elem_type. offset == -1 {
2350
+ base_offset
2351
+ } else {
2352
+ base_offset + elem_type. offset
2353
+ } ,
2354
+ size : elem_type. size ,
2355
+ kind : elem_type. kind ,
2356
+ child : elem_type. child . clone ( ) ,
2357
+ } ) ;
2358
+ }
2359
+ }
2360
+ TypeTree ( types)
2361
+ }
2362
+ }
2312
2363
}
2313
-
2364
+ } else {
2365
+ TypeTree :: new ( )
2366
+ }
2367
+ } else if ty. is_slice ( ) {
2368
+ if let ty:: Slice ( element_ty) = ty. kind ( ) {
2369
+ typetree_from_ty_impl ( tcx, * element_ty, depth + 1 , visited)
2370
+ } else {
2371
+ TypeTree :: new ( )
2372
+ }
2373
+ } else if let ty:: Tuple ( tuple_types) = ty. kind ( ) {
2374
+ if tuple_types. is_empty ( ) {
2375
+ TypeTree :: new ( )
2376
+ } else {
2314
2377
let mut types = Vec :: new ( ) ;
2315
- for i in 0 ..len {
2316
- let base_offset = ( i as usize * element_layout) as isize ;
2378
+ let mut current_offset = 0 ;
2379
+
2380
+ for tuple_ty in tuple_types. iter ( ) {
2381
+ let element_tree = typetree_from_ty_impl ( tcx, tuple_ty, depth + 1 , visited) ;
2382
+ let element_layout = tcx
2383
+ . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( tuple_ty) )
2384
+ . ok ( )
2385
+ . map ( |layout| layout. size . bytes_usize ( ) )
2386
+ . unwrap_or ( 0 ) ;
2317
2387
2318
2388
for elem_type in & element_tree. 0 {
2319
2389
types. push ( Type {
2320
2390
offset : if elem_type. offset == -1 {
2321
- base_offset
2391
+ current_offset as isize
2322
2392
} else {
2323
- base_offset + elem_type. offset
2393
+ current_offset as isize + elem_type. offset
2324
2394
} ,
2325
2395
size : elem_type. size ,
2326
2396
kind : elem_type. kind ,
2327
2397
child : elem_type. child . clone ( ) ,
2328
2398
} ) ;
2329
2399
}
2330
- }
2331
2400
2332
- return TypeTree ( types) ;
2333
- }
2334
- }
2335
-
2336
- if ty. is_slice ( ) {
2337
- if let ty:: Slice ( element_ty) = ty. kind ( ) {
2338
- let element_tree = typetree_from_ty ( tcx, * element_ty) ;
2339
- return element_tree;
2340
- }
2341
- }
2342
-
2343
- if let ty:: Tuple ( tuple_types) = ty. kind ( ) {
2344
- if tuple_types. is_empty ( ) {
2345
- return TypeTree :: new ( ) ;
2346
- }
2347
-
2348
- let mut types = Vec :: new ( ) ;
2349
- let mut current_offset = 0 ;
2350
-
2351
- for tuple_ty in tuple_types. iter ( ) {
2352
- let element_tree = typetree_from_ty ( tcx, tuple_ty) ;
2353
-
2354
- let element_layout = tcx
2355
- . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( tuple_ty) )
2356
- . ok ( )
2357
- . map ( |layout| layout. size . bytes_usize ( ) )
2358
- . unwrap_or ( 0 ) ;
2359
-
2360
- for elem_type in & element_tree. 0 {
2361
- types. push ( Type {
2362
- offset : if elem_type. offset == -1 {
2363
- current_offset as isize
2364
- } else {
2365
- current_offset as isize + elem_type. offset
2366
- } ,
2367
- size : elem_type. size ,
2368
- kind : elem_type. kind ,
2369
- child : elem_type. child . clone ( ) ,
2370
- } ) ;
2401
+ current_offset += element_layout;
2371
2402
}
2372
2403
2373
- current_offset += element_layout ;
2404
+ TypeTree ( types )
2374
2405
}
2375
-
2376
- return TypeTree ( types) ;
2377
- }
2378
-
2379
- if let ty:: Adt ( adt_def, args) = ty. kind ( ) {
2406
+ } else if let ty:: Adt ( adt_def, args) = ty. kind ( ) {
2380
2407
if adt_def. is_struct ( ) {
2381
2408
let struct_layout =
2382
2409
tcx. layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( ty) ) ;
@@ -2385,7 +2412,7 @@ pub fn typetree_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> TypeTree {
2385
2412
2386
2413
for ( field_idx, field_def) in adt_def. all_fields ( ) . enumerate ( ) {
2387
2414
let field_ty = field_def. ty ( tcx, args) ;
2388
- let field_tree = typetree_from_ty ( tcx, field_ty) ;
2415
+ let field_tree = typetree_from_ty_impl ( tcx, field_ty, depth + 1 , visited ) ;
2389
2416
2390
2417
let field_offset = layout. fields . offset ( field_idx) . bytes_usize ( ) ;
2391
2418
@@ -2403,10 +2430,17 @@ pub fn typetree_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> TypeTree {
2403
2430
}
2404
2431
}
2405
2432
2406
- return TypeTree ( types) ;
2433
+ TypeTree ( types)
2434
+ } else {
2435
+ TypeTree :: new ( )
2407
2436
}
2437
+ } else {
2438
+ TypeTree :: new ( )
2408
2439
}
2409
- }
2440
+ } else {
2441
+ TypeTree :: new ( )
2442
+ } ;
2410
2443
2411
- TypeTree :: new ( )
2444
+ visited. pop ( ) ;
2445
+ result
2412
2446
}
0 commit comments