@@ -18,25 +18,31 @@ use crate::builder::{Builder, parse_float_into_constval};
18
18
impl < ' a , ' tcx > Builder < ' a , ' tcx > {
19
19
/// Compile `expr`, yielding a compile-time constant. Assumes that
20
20
/// `expr` is a valid compile-time constant!
21
- pub ( crate ) fn as_constant ( & mut self , expr : & Expr < ' tcx > ) -> ConstOperand < ' tcx > {
22
- let this = self ;
23
- let tcx = this. tcx ;
24
- let Expr { ty, temp_lifetime : _, span, ref kind } = * expr;
25
- match kind {
26
- ExprKind :: Scope { region_scope : _, lint_level : _, value } => {
27
- this. as_constant ( & this. thir [ * value] )
28
- }
29
- _ => as_constant_inner (
21
+ pub ( crate ) fn as_constant ( & mut self , expr : & ' a Expr < ' tcx > ) -> ConstOperand < ' tcx > {
22
+ match self . try_as_constant ( expr) {
23
+ Ok ( const_operand) => const_operand,
24
+ Err ( expr) => span_bug ! ( expr. span, "expression is not a valid constant {:?}" , expr. kind) ,
25
+ }
26
+ }
27
+
28
+ pub ( crate ) fn try_as_constant (
29
+ & mut self ,
30
+ expr : & ' a Expr < ' tcx > ,
31
+ ) -> Result < ConstOperand < ' tcx > , & ' a Expr < ' tcx > > {
32
+ if let ExprKind :: Scope { region_scope : _, lint_level : _, value } = expr. kind {
33
+ self . try_as_constant ( & self . thir [ value] )
34
+ } else {
35
+ try_as_constant_inner (
30
36
expr,
31
37
|user_ty| {
32
- Some ( this . canonical_user_type_annotations . push ( CanonicalUserTypeAnnotation {
33
- span,
38
+ Some ( self . canonical_user_type_annotations . push ( CanonicalUserTypeAnnotation {
39
+ span : expr . span ,
34
40
user_ty : user_ty. clone ( ) ,
35
- inferred_ty : ty,
41
+ inferred_ty : expr . ty ,
36
42
} ) )
37
43
} ,
38
- tcx,
39
- ) ,
44
+ self . tcx ,
45
+ )
40
46
}
41
47
}
42
48
}
@@ -46,8 +52,19 @@ pub(crate) fn as_constant_inner<'tcx>(
46
52
push_cuta : impl FnMut ( & Box < CanonicalUserType < ' tcx > > ) -> Option < UserTypeAnnotationIndex > ,
47
53
tcx : TyCtxt < ' tcx > ,
48
54
) -> ConstOperand < ' tcx > {
55
+ match try_as_constant_inner ( expr, push_cuta, tcx) {
56
+ Ok ( const_operand) => const_operand,
57
+ Err ( expr) => span_bug ! ( expr. span, "expression is not a valid constant {:?}" , expr. kind) ,
58
+ }
59
+ }
60
+
61
+ fn try_as_constant_inner < ' a , ' tcx > (
62
+ expr : & ' a Expr < ' tcx > ,
63
+ push_cuta : impl FnMut ( & Box < CanonicalUserType < ' tcx > > ) -> Option < UserTypeAnnotationIndex > ,
64
+ tcx : TyCtxt < ' tcx > ,
65
+ ) -> Result < ConstOperand < ' tcx > , & ' a Expr < ' tcx > > {
49
66
let Expr { ty, temp_lifetime : _, span, ref kind } = * expr;
50
- match * kind {
67
+ Ok ( match * kind {
51
68
ExprKind :: Literal { lit, neg } => {
52
69
let const_ = lit_to_mir_constant ( tcx, LitToConstInput { lit : lit. node , ty, neg } ) ;
53
70
@@ -93,8 +110,8 @@ pub(crate) fn as_constant_inner<'tcx>(
93
110
94
111
ConstOperand { span, user_ty : None , const_ }
95
112
}
96
- _ => span_bug ! ( span , "expression is not a valid constant {:?}" , kind ) ,
97
- }
113
+ _ => return Err ( expr ) ,
114
+ } )
98
115
}
99
116
100
117
#[ instrument( skip( tcx, lit_input) ) ]
0 commit comments