22
33use crate :: transform:: MirPass ;
44use rustc_middle:: mir:: { Body , StatementKind } ;
5- use rustc_middle:: ty:: TyCtxt ;
5+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
66
77pub struct RemoveZsts ;
88
@@ -15,17 +15,23 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
1515 match statement. kind {
1616 StatementKind :: Assign ( box ( place, _) ) => {
1717 let place_ty = place. ty ( local_decls, tcx) . ty ;
18- if let Ok ( layout) = tcx. layout_of ( param_env. and ( place_ty) ) {
19- if layout. is_zst ( ) {
20- if tcx. consider_optimizing ( || {
21- format ! (
22- "RemoveZsts - Place: {:?} SourceInfo: {:?}" ,
23- place, statement. source_info
24- )
25- } ) {
26- statement. make_nop ( ) ;
27- }
28- }
18+ if !maybe_zst ( place_ty) {
19+ continue ;
20+ }
21+ let layout = match tcx. layout_of ( param_env. and ( place_ty) ) {
22+ Ok ( layout) => layout,
23+ Err ( _) => continue ,
24+ } ;
25+ if !layout. is_zst ( ) {
26+ continue ;
27+ }
28+ if tcx. consider_optimizing ( || {
29+ format ! (
30+ "RemoveZsts - Place: {:?} SourceInfo: {:?}" ,
31+ place, statement. source_info
32+ )
33+ } ) {
34+ statement. make_nop ( ) ;
2935 }
3036 }
3137 _ => { }
@@ -34,3 +40,15 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
3440 }
3541 }
3642}
43+
44+ /// A cheap, approximate check to avoid unnecessary `layout_of` calls.
45+ fn maybe_zst ( ty : Ty < ' _ > ) -> bool {
46+ match ty. kind ( ) {
47+ // maybe ZST (could be more precise)
48+ ty:: Adt ( ..) | ty:: Array ( ..) | ty:: Closure ( ..) | ty:: Tuple ( ..) | ty:: Opaque ( ..) => true ,
49+ // definitely ZST
50+ ty:: FnDef ( ..) | ty:: Never => true ,
51+ // unreachable or can't be ZST
52+ _ => false ,
53+ }
54+ }
0 commit comments