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