@@ -36,31 +36,37 @@ struct Replacer<'a, 'tcx> {
36
36
}
37
37
38
38
/// A cheap, approximate check to avoid unnecessary `layout_of` calls.
39
- fn maybe_zst ( ty : Ty < ' _ > ) -> bool {
39
+ ///
40
+ /// `Some(true)` is definitely ZST; `Some(false)` is definitely *not* ZST.
41
+ ///
42
+ /// `None` may or may not be, and must check `layout_of` to be sure.
43
+ fn trivially_zst < ' tcx > ( ty : Ty < ' tcx > , tcx : TyCtxt < ' tcx > ) -> Option < bool > {
40
44
match ty. kind ( ) {
45
+ // definitely ZST
46
+ ty:: FnDef ( ..) | ty:: Never => Some ( true ) ,
47
+ ty:: Tuple ( fields) if fields. is_empty ( ) => Some ( true ) ,
48
+ ty:: Array ( _ty, len) if let Some ( 0 ) = len. try_to_target_usize ( tcx) => Some ( true ) ,
41
49
// maybe ZST (could be more precise)
42
50
ty:: Adt ( ..)
43
51
| ty:: Array ( ..)
44
52
| ty:: Closure ( ..)
45
53
| ty:: CoroutineClosure ( ..)
46
54
| ty:: Tuple ( ..)
47
- | ty:: Alias ( ty:: Opaque , ..) => true ,
48
- // definitely ZST
49
- ty:: FnDef ( ..) | ty:: Never => true ,
55
+ | ty:: Alias ( ty:: Opaque , ..) => None ,
50
56
// unreachable or can't be ZST
51
- _ => false ,
57
+ _ => Some ( false ) ,
52
58
}
53
59
}
54
60
55
61
impl < ' tcx > Replacer < ' _ , ' tcx > {
56
62
fn known_to_be_zst ( & self , ty : Ty < ' tcx > ) -> bool {
57
- if !maybe_zst ( ty) {
58
- return false ;
63
+ if let Some ( is_zst) = trivially_zst ( ty, self . tcx ) {
64
+ is_zst
65
+ } else {
66
+ self . tcx
67
+ . layout_of ( self . typing_env . as_query_input ( ty) )
68
+ . is_ok_and ( |layout| layout. is_zst ( ) )
59
69
}
60
- let Ok ( layout) = self . tcx . layout_of ( self . typing_env . as_query_input ( ty) ) else {
61
- return false ;
62
- } ;
63
- layout. is_zst ( )
64
70
}
65
71
66
72
fn make_zst ( & self , ty : Ty < ' tcx > ) -> ConstOperand < ' tcx > {
0 commit comments