@@ -601,7 +601,7 @@ impl TypedAstContext {
601
601
}
602
602
}
603
603
604
- // Pessimistically try to check if an expression doesn't return. If it does, or we can't tell
604
+ /// Pessimistically try to check if an expression doesn't return. If it does, or we can't tell
605
605
/// that it doesn't, return `false`.
606
606
pub fn expr_diverges ( & self , expr_id : CExprId ) -> bool {
607
607
let func_id = match self . index ( expr_id) . kind {
@@ -624,6 +624,71 @@ impl TypedAstContext {
624
624
}
625
625
}
626
626
627
+ /// Pessimistically try to check if an expression is `const`.
628
+ /// If it's not, or we can't tell if it is, return `false`.
629
+ pub fn is_const_expr ( & self , expr : CExprId ) -> bool {
630
+ let is_const = |expr| self . is_const_expr ( expr) ;
631
+
632
+ use CExprKind :: * ;
633
+ match self [ expr] . kind {
634
+ // A literal is always `const`.
635
+ Literal ( _, _) => true ,
636
+ // Unary ops should be `const`.
637
+ // TODO handle `f128` or use the primitive type.
638
+ Unary ( _, _, expr, _) => is_const ( expr) ,
639
+ // Not sure what a `None` `CExprId` means here
640
+ // or how to detect a `sizeof` of a VLA, which is non-`const`.
641
+ UnaryType ( _, _, _, _) => true ,
642
+ // Not sure what a `OffsetOfKind::Variable` means.
643
+ OffsetOf ( _, _) => true ,
644
+ // `ptr::offset` (ptr `BinOp::Add`) was `const` stabilized in `1.61.0`.
645
+ // `ptr::offset_from` (ptr `BinOp::Subtract`) was `const` stabilized in `1.65.0`.
646
+ // TODO `f128` is not yet handled, as we should eventually
647
+ // switch to the (currently unstable) `f128` primitive type (#1262).
648
+ Binary ( _, _, lhs, rhs, _, _) => is_const ( lhs) && is_const ( rhs) ,
649
+ // `as` casts are always `const`.
650
+ ImplicitCast ( _, _, _, _, _) => true ,
651
+ // `as` casts are always `const`.
652
+ // TODO This is `const`, although there's a bug #853.
653
+ ExplicitCast ( _, _, _, _, _) => true ,
654
+ // This is used in `const` locations like `match` patterns and array lengths, so it must be `const`.
655
+ ConstantExpr ( _, _, _) => true ,
656
+ // A reference in an already otherwise `const` context should be `const` itself.
657
+ DeclRef ( _, _, _) => true ,
658
+ Call ( _, fn_expr, ref args) => {
659
+ let is_const_fn = false ; // TODO detect which `fn`s are `const`.
660
+ is_const ( fn_expr) && args. iter ( ) . copied ( ) . all ( is_const) && is_const_fn
661
+ }
662
+ Member ( _, expr, _, _, _) => is_const ( expr) ,
663
+ ArraySubscript ( _, array, index, _) => is_const ( array) && is_const ( index) ,
664
+ Conditional ( _, cond, if_true, if_false) => {
665
+ is_const ( cond) && is_const ( if_true) && is_const ( if_false)
666
+ }
667
+ BinaryConditional ( _, cond, if_false) => is_const ( cond) && is_const ( if_false) ,
668
+ InitList ( _, ref inits, _, _) => inits. iter ( ) . copied ( ) . all ( is_const) ,
669
+ ImplicitValueInit ( _) => true ,
670
+ Paren ( _, expr) => is_const ( expr) ,
671
+ CompoundLiteral ( _, expr) => is_const ( expr) ,
672
+ Predefined ( _, expr) => is_const ( expr) ,
673
+ Statements ( _, stmt) => self . is_const_stmt ( stmt) ,
674
+ VAArg ( _, expr) => is_const ( expr) ,
675
+ // SIMD is not yet `const` in Rust.
676
+ ShuffleVector ( _, _) | ConvertVector ( _, _) => false ,
677
+ DesignatedInitExpr ( _, _, expr) => is_const ( expr) ,
678
+ Choose ( _, cond, if_true, if_false, _) => {
679
+ is_const ( cond) && is_const ( if_true) && is_const ( if_false)
680
+ }
681
+ // Atomics are not yet `const` in Rust.
682
+ Atomic { .. } => false ,
683
+ BadExpr => false ,
684
+ }
685
+ }
686
+
687
+ pub fn is_const_stmt ( & self , _stmt : CStmtId ) -> bool {
688
+ // TODO
689
+ false
690
+ }
691
+
627
692
pub fn prune_unwanted_decls ( & mut self , want_unused_functions : bool ) {
628
693
// Starting from a set of root declarations, walk each one to find declarations it
629
694
// depends on. Then walk each of those, recursively.
@@ -1186,6 +1251,9 @@ pub enum OffsetOfKind {
1186
1251
1187
1252
/// Represents an expression in C (6.5 Expressions)
1188
1253
///
1254
+ /// This is modeled on Clang's APIs, so where documentation
1255
+ /// is lacking here, look at Clang.
1256
+ ///
1189
1257
/// We've kept a qualified type on every node since Clang has this information available, and since
1190
1258
/// the semantics of translations of certain constructs often depend on the type of the things they
1191
1259
/// are given.
0 commit comments