@@ -120,15 +120,17 @@ use rustc_middle::ty::{
120
120
TyCtxt , TypeVisitableExt , UintTy , UpvarCapture ,
121
121
} ;
122
122
use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
123
- use rustc_span:: source_map:: SourceMap ;
123
+ use rustc_span:: source_map:: { SourceMap , Spanned } ;
124
124
use rustc_span:: symbol:: { Ident , Symbol , kw} ;
125
125
use rustc_span:: { InnerSpan , Span , sym} ;
126
126
use rustc_target:: abi:: Integer ;
127
127
use visitors:: { Visitable , for_each_unconsumed_temporary} ;
128
128
129
129
use crate :: consts:: { ConstEvalCtxt , Constant , mir_to_const} ;
130
130
use crate :: higher:: Range ;
131
- use crate :: ty:: { adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type} ;
131
+ use crate :: ty:: {
132
+ adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_normalizable, is_recursively_primitive_type,
133
+ } ;
132
134
use crate :: visitors:: for_each_expr_without_closures;
133
135
use rustc_middle:: hir:: nested_filter;
134
136
@@ -2226,6 +2228,44 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
2226
2228
)
2227
2229
}
2228
2230
2231
+ // Checks if the given expression is a call to `align_of`
2232
+ // or casting to a type with the same alignment
2233
+ pub fn is_expr_const_aligned ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
2234
+ match expr. kind {
2235
+ ExprKind :: Call ( fun, _) => is_align_of_call ( cx, fun, expr) ,
2236
+ ExprKind :: Lit ( lit) => is_align_lit ( cx, lit, expr) ,
2237
+ _ => false ,
2238
+ }
2239
+ }
2240
+
2241
+ fn is_align_of_call ( cx : & LateContext < ' _ > , fun : & Expr < ' _ > , expr : & Expr < ' _ > ) -> bool {
2242
+ let ExprKind :: Path ( QPath :: Resolved ( None , path) ) = fun. kind else {
2243
+ return false ;
2244
+ } ;
2245
+ let Some ( args) = path. segments . last ( ) . and_then ( |seg| seg. args ) else {
2246
+ return false ;
2247
+ } ;
2248
+ let [ hir:: GenericArg :: Type ( ty) ] = args. args else {
2249
+ return false ;
2250
+ } ;
2251
+ path_def_id ( cx, fun) . is_some_and ( |id| {
2252
+ let typeck = cx. typeck_results ( ) ;
2253
+ match_any_def_paths ( cx, id, & [ & paths:: CORE_ALIGN_OF , & paths:: STD_ALIGN_OF ] ) . is_some ( )
2254
+ && typeck. node_type ( ty. hir_id ) == typeck. expr_ty ( expr)
2255
+ } )
2256
+ }
2257
+
2258
+ fn is_align_lit ( cx : & LateContext < ' _ > , lit : & Spanned < LitKind > , expr : & Expr < ' _ > ) -> bool {
2259
+ let LitKind :: Int ( val, _) = lit. node else { return false } ;
2260
+ let ty = cx. typeck_results ( ) . expr_ty ( expr) ;
2261
+ if !is_normalizable ( cx, cx. param_env , ty) {
2262
+ return false ;
2263
+ }
2264
+ cx. tcx
2265
+ . layout_of ( cx. typing_env ( ) . as_query_input ( ty) )
2266
+ . is_ok_and ( |layout| val == u128:: from ( layout. align . abi . bytes ( ) ) )
2267
+ }
2268
+
2229
2269
/// Checks if the expression is the final expression returned from a block.
2230
2270
pub fn is_expr_final_block_expr ( tcx : TyCtxt < ' _ > , expr : & Expr < ' _ > ) -> bool {
2231
2271
matches ! ( tcx. parent_hir_node( expr. hir_id) , Node :: Block ( ..) )
0 commit comments