@@ -18,7 +18,11 @@ use std::borrow::Cow;
18
18
19
19
type McfResult = Result < ( ) , ( Span , Cow < ' static , str > ) > ;
20
20
21
- pub fn is_min_const_fn < ' a , ' tcx > ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > , msrv : Option < RustcVersion > ) -> McfResult {
21
+ pub fn is_min_const_fn < ' a , ' tcx > (
22
+ tcx : TyCtxt < ' tcx > ,
23
+ body : & ' a Body < ' tcx > ,
24
+ msrv : Option < RustcVersion > ,
25
+ ) -> McfResult {
22
26
let def_id = body. source . def_id ( ) ;
23
27
let mut current = def_id;
24
28
loop {
@@ -33,10 +37,18 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
33
37
| ty:: PredicateKind :: ConstEquate ( ..)
34
38
| ty:: PredicateKind :: Trait ( ..)
35
39
| ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => continue ,
36
- ty:: PredicateKind :: ObjectSafe ( _) => panic ! ( "object safe predicate on function: {:#?}" , predicate) ,
37
- ty:: PredicateKind :: ClosureKind ( ..) => panic ! ( "closure kind predicate on function: {:#?}" , predicate) ,
38
- ty:: PredicateKind :: Subtype ( _) => panic ! ( "subtype predicate on function: {:#?}" , predicate) ,
39
- ty:: PredicateKind :: Coerce ( _) => panic ! ( "coerce predicate on function: {:#?}" , predicate) ,
40
+ ty:: PredicateKind :: ObjectSafe ( _) => {
41
+ panic ! ( "object safe predicate on function: {:#?}" , predicate)
42
+ }
43
+ ty:: PredicateKind :: ClosureKind ( ..) => {
44
+ panic ! ( "closure kind predicate on function: {:#?}" , predicate)
45
+ }
46
+ ty:: PredicateKind :: Subtype ( _) => {
47
+ panic ! ( "subtype predicate on function: {:#?}" , predicate)
48
+ }
49
+ ty:: PredicateKind :: Coerce ( _) => {
50
+ panic ! ( "coerce predicate on function: {:#?}" , predicate)
51
+ }
40
52
}
41
53
}
42
54
match predicates. parent {
@@ -77,22 +89,23 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
77
89
match ty. kind ( ) {
78
90
ty:: Ref ( _, _, hir:: Mutability :: Mut ) => {
79
91
return Err ( ( span, "mutable references in const fn are unstable" . into ( ) ) ) ;
80
- } ,
92
+ }
81
93
ty:: Opaque ( ..) => return Err ( ( span, "`impl Trait` in const fn is unstable" . into ( ) ) ) ,
82
94
ty:: FnPtr ( ..) => {
83
95
return Err ( ( span, "function pointers in const fn are unstable" . into ( ) ) ) ;
84
- } ,
85
- ty:: Dynamic ( preds, _) => {
96
+ }
97
+ ty:: Dynamic ( preds, _, _ ) => {
86
98
for pred in preds. iter ( ) {
87
99
match pred. skip_binder ( ) {
88
- ty:: ExistentialPredicate :: AutoTrait ( _) | ty:: ExistentialPredicate :: Projection ( _) => {
100
+ ty:: ExistentialPredicate :: AutoTrait ( _)
101
+ | ty:: ExistentialPredicate :: Projection ( _) => {
89
102
return Err ( (
90
103
span,
91
104
"trait bounds other than `Sized` \
92
105
on const fn parameters are unstable"
93
106
. into ( ) ,
94
107
) ) ;
95
- } ,
108
+ }
96
109
ty:: ExistentialPredicate :: Trait ( trait_ref) => {
97
110
if Some ( trait_ref. def_id ) != tcx. lang_items ( ) . sized_trait ( ) {
98
111
return Err ( (
@@ -102,11 +115,11 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
102
115
. into ( ) ,
103
116
) ) ;
104
117
}
105
- } ,
118
+ }
106
119
}
107
120
}
108
- } ,
109
- _ => { } ,
121
+ }
122
+ _ => { }
110
123
}
111
124
}
112
125
Ok ( ( ) )
@@ -120,10 +133,13 @@ fn check_rvalue<'tcx>(
120
133
span : Span ,
121
134
) -> McfResult {
122
135
match rvalue {
123
- Rvalue :: ThreadLocalRef ( _) => Err ( ( span, "cannot access thread local storage in const fn" . into ( ) ) ) ,
124
- Rvalue :: Len ( place) | Rvalue :: Discriminant ( place) | Rvalue :: Ref ( _, _, place) | Rvalue :: AddressOf ( _, place) => {
125
- check_place ( tcx, * place, span, body)
126
- } ,
136
+ Rvalue :: ThreadLocalRef ( _) => {
137
+ Err ( ( span, "cannot access thread local storage in const fn" . into ( ) ) )
138
+ }
139
+ Rvalue :: Len ( place)
140
+ | Rvalue :: Discriminant ( place)
141
+ | Rvalue :: Ref ( _, _, place)
142
+ | Rvalue :: AddressOf ( _, place) => check_place ( tcx, * place, span, body) ,
127
143
Rvalue :: CopyForDeref ( place) => check_place ( tcx, * place, span, body) ,
128
144
Rvalue :: Repeat ( operand, _)
129
145
| Rvalue :: Use ( operand)
@@ -136,7 +152,9 @@ fn check_rvalue<'tcx>(
136
152
) => check_operand ( tcx, operand, span, body) ,
137
153
Rvalue :: Cast (
138
154
CastKind :: Pointer (
139
- PointerCast :: UnsafeFnPointer | PointerCast :: ClosureFnPointer ( _) | PointerCast :: ReifyFnPointer ,
155
+ PointerCast :: UnsafeFnPointer
156
+ | PointerCast :: ClosureFnPointer ( _)
157
+ | PointerCast :: ReifyFnPointer ,
140
158
) ,
141
159
_,
142
160
_,
@@ -146,7 +164,10 @@ fn check_rvalue<'tcx>(
146
164
deref_ty. ty
147
165
} else {
148
166
// We cannot allow this for now.
149
- return Err ( ( span, "unsizing casts are only allowed for references right now" . into ( ) ) ) ;
167
+ return Err ( (
168
+ span,
169
+ "unsizing casts are only allowed for references right now" . into ( ) ,
170
+ ) ) ;
150
171
} ;
151
172
let unsized_ty = tcx. struct_tail_erasing_lifetimes ( pointee_ty, tcx. param_env ( def_id) ) ;
152
173
if let ty:: Slice ( _) | ty:: Str = unsized_ty. kind ( ) {
@@ -157,10 +178,14 @@ fn check_rvalue<'tcx>(
157
178
// We just can't allow trait objects until we have figured out trait method calls.
158
179
Err ( ( span, "unsizing casts are not allowed in const fn" . into ( ) ) )
159
180
}
160
- } ,
181
+ }
161
182
Rvalue :: Cast ( CastKind :: PointerExposeAddress , _, _) => {
162
183
Err ( ( span, "casting pointers to ints is unstable in const fn" . into ( ) ) )
163
- } ,
184
+ }
185
+ Rvalue :: Cast ( CastKind :: DynStar , _, _) => {
186
+ // FIXME(dyn-star)
187
+ unimplemented ! ( )
188
+ }
164
189
// binops are fine on integers
165
190
Rvalue :: BinaryOp ( _, box ( lhs, rhs) ) | Rvalue :: CheckedBinaryOp ( _, box ( lhs, rhs) ) => {
166
191
check_operand ( tcx, lhs, span, body) ?;
@@ -169,27 +194,26 @@ fn check_rvalue<'tcx>(
169
194
if ty. is_integral ( ) || ty. is_bool ( ) || ty. is_char ( ) {
170
195
Ok ( ( ) )
171
196
} else {
172
- Err ( (
173
- span,
174
- "only int, `bool` and `char` operations are stable in const fn" . into ( ) ,
175
- ) )
197
+ Err ( ( span, "only int, `bool` and `char` operations are stable in const fn" . into ( ) ) )
176
198
}
177
- } ,
178
- Rvalue :: NullaryOp ( NullOp :: SizeOf | NullOp :: AlignOf , _) | Rvalue :: ShallowInitBox ( _, _) => Ok ( ( ) ) ,
199
+ }
200
+ Rvalue :: NullaryOp ( NullOp :: SizeOf | NullOp :: AlignOf , _) | Rvalue :: ShallowInitBox ( _, _) => {
201
+ Ok ( ( ) )
202
+ }
179
203
Rvalue :: UnaryOp ( _, operand) => {
180
204
let ty = operand. ty ( body, tcx) ;
181
205
if ty. is_integral ( ) || ty. is_bool ( ) {
182
206
check_operand ( tcx, operand, span, body)
183
207
} else {
184
208
Err ( ( span, "only int and `bool` operations are stable in const fn" . into ( ) ) )
185
209
}
186
- } ,
210
+ }
187
211
Rvalue :: Aggregate ( _, operands) => {
188
212
for operand in operands {
189
213
check_operand ( tcx, operand, span, body) ?;
190
214
}
191
215
Ok ( ( ) )
192
- } ,
216
+ }
193
217
}
194
218
}
195
219
@@ -204,7 +228,7 @@ fn check_statement<'tcx>(
204
228
StatementKind :: Assign ( box ( place, rval) ) => {
205
229
check_place ( tcx, * place, span, body) ?;
206
230
check_rvalue ( tcx, body, def_id, rval, span)
207
- } ,
231
+ }
208
232
209
233
StatementKind :: FakeRead ( box ( _, place) ) => check_place ( tcx, * place, span, body) ,
210
234
// just an assignment
@@ -214,14 +238,15 @@ fn check_statement<'tcx>(
214
238
215
239
StatementKind :: Intrinsic ( box NonDivergingIntrinsic :: Assume ( op) ) => check_operand ( tcx, op, span, body) ,
216
240
217
- StatementKind :: Intrinsic ( box NonDivergingIntrinsic :: CopyNonOverlapping (
218
- rustc_middle:: mir:: CopyNonOverlapping { dst, src, count } ,
219
- ) ) => {
241
+ StatementKind :: CopyNonOverlapping ( box rustc_middle:: mir:: CopyNonOverlapping {
242
+ dst,
243
+ src,
244
+ count,
245
+ } ) => {
220
246
check_operand ( tcx, dst, span, body) ?;
221
247
check_operand ( tcx, src, span, body) ?;
222
248
check_operand ( tcx, count, span, body)
223
- } ,
224
-
249
+ }
225
250
// These are all NOPs
226
251
StatementKind :: StorageLive ( _)
227
252
| StatementKind :: StorageDead ( _)
@@ -232,7 +257,12 @@ fn check_statement<'tcx>(
232
257
}
233
258
}
234
259
235
- fn check_operand < ' tcx > ( tcx : TyCtxt < ' tcx > , operand : & Operand < ' tcx > , span : Span , body : & Body < ' tcx > ) -> McfResult {
260
+ fn check_operand < ' tcx > (
261
+ tcx : TyCtxt < ' tcx > ,
262
+ operand : & Operand < ' tcx > ,
263
+ span : Span ,
264
+ body : & Body < ' tcx > ,
265
+ ) -> McfResult {
236
266
match operand {
237
267
Operand :: Move ( place) | Operand :: Copy ( place) => check_place ( tcx, * place, span, body) ,
238
268
Operand :: Constant ( c) => match c. check_static_ptr ( tcx) {
@@ -242,7 +272,12 @@ fn check_operand<'tcx>(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, b
242
272
}
243
273
}
244
274
245
- fn check_place < ' tcx > ( tcx : TyCtxt < ' tcx > , place : Place < ' tcx > , span : Span , body : & Body < ' tcx > ) -> McfResult {
275
+ fn check_place < ' tcx > (
276
+ tcx : TyCtxt < ' tcx > ,
277
+ place : Place < ' tcx > ,
278
+ span : Span ,
279
+ body : & Body < ' tcx > ,
280
+ ) -> McfResult {
246
281
let mut cursor = place. projection . as_ref ( ) ;
247
282
while let [ ref proj_base @ .., elem] = * cursor {
248
283
cursor = proj_base;
@@ -255,12 +290,12 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
255
290
return Err ( ( span, "accessing union fields is unstable" . into ( ) ) ) ;
256
291
}
257
292
}
258
- } ,
293
+ }
259
294
ProjectionElem :: ConstantIndex { .. }
260
295
| ProjectionElem :: Downcast ( ..)
261
296
| ProjectionElem :: Subslice { .. }
262
297
| ProjectionElem :: Deref
263
- | ProjectionElem :: Index ( _) => { } ,
298
+ | ProjectionElem :: Index ( _) => { }
264
299
}
265
300
}
266
301
@@ -286,18 +321,16 @@ fn check_terminator<'a, 'tcx>(
286
321
TerminatorKind :: DropAndReplace { place, value, .. } => {
287
322
check_place ( tcx, * place, span, body) ?;
288
323
check_operand ( tcx, value, span, body)
289
- } ,
324
+ }
290
325
291
- TerminatorKind :: SwitchInt {
292
- discr,
293
- switch_ty : _,
294
- targets : _,
295
- } => check_operand ( tcx, discr, span, body) ,
326
+ TerminatorKind :: SwitchInt { discr, switch_ty : _, targets : _ } => {
327
+ check_operand ( tcx, discr, span, body)
328
+ }
296
329
297
330
TerminatorKind :: Abort => Err ( ( span, "abort is not stable in const fn" . into ( ) ) ) ,
298
331
TerminatorKind :: GeneratorDrop | TerminatorKind :: Yield { .. } => {
299
332
Err ( ( span, "const fn generators are unstable" . into ( ) ) )
300
- } ,
333
+ }
301
334
302
335
TerminatorKind :: Call {
303
336
func,
@@ -342,17 +375,15 @@ fn check_terminator<'a, 'tcx>(
342
375
} else {
343
376
Err ( ( span, "can only call other const fns within const fn" . into ( ) ) )
344
377
}
345
- } ,
378
+ }
346
379
347
- TerminatorKind :: Assert {
348
- cond,
349
- expected : _,
350
- msg : _,
351
- target : _,
352
- cleanup : _,
353
- } => check_operand ( tcx, cond, span, body) ,
380
+ TerminatorKind :: Assert { cond, expected : _, msg : _, target : _, cleanup : _ } => {
381
+ check_operand ( tcx, cond, span, body)
382
+ }
354
383
355
- TerminatorKind :: InlineAsm { .. } => Err ( ( span, "cannot use inline assembly in const fn" . into ( ) ) ) ,
384
+ TerminatorKind :: InlineAsm { .. } => {
385
+ Err ( ( span, "cannot use inline assembly in const fn" . into ( ) ) )
386
+ }
356
387
}
357
388
}
358
389
0 commit comments