@@ -21,7 +21,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUs
21
21
use rustc:: middle:: lang_items;
22
22
use rustc:: session:: config:: nightly_options;
23
23
use syntax:: ast:: LitKind ;
24
- use syntax:: feature_gate:: { UnstableFeatures , feature_err , emit_feature_err, GateIssue } ;
24
+ use syntax:: feature_gate:: { UnstableFeatures , emit_feature_err, GateIssue } ;
25
25
use syntax_pos:: { Span , DUMMY_SP } ;
26
26
27
27
use std:: fmt;
@@ -104,7 +104,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
104
104
param_env : ty:: ParamEnv < ' tcx > ,
105
105
local_qualif : IndexVec < Local , Option < Qualif > > ,
106
106
qualif : Qualif ,
107
- const_fn_arg_vars : BitSet < Local > ,
108
107
temp_promotion_state : IndexVec < Local , TempState > ,
109
108
promotion_candidates : Vec < Candidate >
110
109
}
@@ -139,7 +138,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
139
138
param_env,
140
139
local_qualif,
141
140
qualif : Qualif :: empty ( ) ,
142
- const_fn_arg_vars : BitSet :: new_empty ( mir. local_decls . len ( ) ) ,
143
141
temp_promotion_state : temps,
144
142
promotion_candidates : vec ! [ ]
145
143
}
@@ -168,26 +166,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
168
166
}
169
167
}
170
168
171
- /// Error about extra statements in a constant.
172
- fn statement_like ( & mut self ) {
173
- self . add ( Qualif :: NOT_CONST ) ;
174
- if self . mode != Mode :: Fn {
175
- let mut err = feature_err (
176
- & self . tcx . sess . parse_sess ,
177
- "const_let" ,
178
- self . span ,
179
- GateIssue :: Language ,
180
- & format ! ( "statements in {}s are unstable" , self . mode) ,
181
- ) ;
182
- if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
183
- err. note ( "Blocks in constants may only contain items (such as constant, function \
184
- definition, etc...) and a tail expression.") ;
185
- err. help ( "To avoid it, you have to replace the non-item object." ) ;
186
- }
187
- err. emit ( ) ;
188
- }
189
- }
190
-
191
169
/// Add the given qualification to self.qualif.
192
170
fn add ( & mut self , qualif : Qualif ) {
193
171
self . qualif = self . qualif | qualif;
@@ -233,80 +211,46 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
233
211
return ;
234
212
}
235
213
236
- if self . tcx . features ( ) . const_let {
237
- let mut dest = dest;
238
- let index = loop {
239
- match dest {
240
- // with `const_let` active, we treat all locals equal
241
- Place :: Local ( index) => break * index,
242
- // projections are transparent for assignments
243
- // we qualify the entire destination at once, even if just a field would have
244
- // stricter qualification
245
- Place :: Projection ( proj) => {
246
- // Catch more errors in the destination. `visit_place` also checks various
247
- // projection rules like union field access and raw pointer deref
248
- self . visit_place (
249
- dest,
250
- PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) ,
251
- location
252
- ) ;
253
- dest = & proj. base ;
254
- } ,
255
- Place :: Promoted ( ..) => bug ! ( "promoteds don't exist yet during promotion" ) ,
256
- Place :: Static ( ..) => {
257
- // Catch more errors in the destination. `visit_place` also checks that we
258
- // do not try to access statics from constants or try to mutate statics
259
- self . visit_place (
260
- dest,
261
- PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) ,
262
- location
263
- ) ;
264
- return ;
265
- }
214
+ let mut dest = dest;
215
+ let index = loop {
216
+ match dest {
217
+ // We treat all locals equal in constants
218
+ Place :: Local ( index) => break * index,
219
+ // projections are transparent for assignments
220
+ // we qualify the entire destination at once, even if just a field would have
221
+ // stricter qualification
222
+ Place :: Projection ( proj) => {
223
+ // Catch more errors in the destination. `visit_place` also checks various
224
+ // projection rules like union field access and raw pointer deref
225
+ self . visit_place (
226
+ dest,
227
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) ,
228
+ location
229
+ ) ;
230
+ dest = & proj. base ;
231
+ } ,
232
+ Place :: Promoted ( ..) => bug ! ( "promoteds don't exist yet during promotion" ) ,
233
+ Place :: Static ( ..) => {
234
+ // Catch more errors in the destination. `visit_place` also checks that we
235
+ // do not try to access statics from constants or try to mutate statics
236
+ self . visit_place (
237
+ dest,
238
+ PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) ,
239
+ location
240
+ ) ;
241
+ return ;
266
242
}
267
- } ;
268
- debug ! ( "store to var {:?}" , index) ;
269
- match & mut self . local_qualif [ index] {
270
- // this is overly restrictive, because even full assignments do not clear the qualif
271
- // While we could special case full assignments, this would be inconsistent with
272
- // aggregates where we overwrite all fields via assignments, which would not get
273
- // that feature.
274
- Some ( ref mut qualif) => * qualif = * qualif | self . qualif ,
275
- // insert new qualification
276
- qualif @ None => * qualif = Some ( self . qualif ) ,
277
- }
278
- return ;
279
- }
280
-
281
- match * dest {
282
- Place :: Local ( index) if self . mir . local_kind ( index) == LocalKind :: Temp ||
283
- self . mir . local_kind ( index) == LocalKind :: ReturnPointer => {
284
- debug ! ( "store to {:?} (temp or return pointer)" , index) ;
285
- store ( & mut self . local_qualif [ index] )
286
- }
287
-
288
- Place :: Projection ( box Projection {
289
- base : Place :: Local ( index) ,
290
- elem : ProjectionElem :: Deref
291
- } ) if self . mir . local_kind ( index) == LocalKind :: Temp
292
- && self . mir . local_decls [ index] . ty . is_box ( )
293
- && self . local_qualif [ index] . map_or ( false , |qualif| {
294
- qualif. contains ( Qualif :: NOT_CONST )
295
- } ) => {
296
- // Part of `box expr`, we should've errored
297
- // already for the Box allocation Rvalue.
298
- }
299
-
300
- // This must be an explicit assignment.
301
- _ => {
302
- // Catch more errors in the destination.
303
- self . visit_place (
304
- dest,
305
- PlaceContext :: MutatingUse ( MutatingUseContext :: Store ) ,
306
- location
307
- ) ;
308
- self . statement_like ( ) ;
309
243
}
244
+ } ;
245
+ debug ! ( "store to var {:?}" , index) ;
246
+ match & mut self . local_qualif [ index] {
247
+ // this is overly restrictive, because even full assignments do not clear the qualif
248
+ // While we could special case full assignments, this would be inconsistent with
249
+ // aggregates where we overwrite all fields via assignments, which would not get
250
+ // that feature.
251
+ Some ( ref mut qualif) => * qualif = * qualif | self . qualif ,
252
+ // insert new qualification
253
+ qualif @ None => * qualif = Some ( self . qualif ) ,
310
254
}
311
255
}
312
256
@@ -347,45 +291,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
347
291
TerminatorKind :: FalseUnwind { .. } => None ,
348
292
349
293
TerminatorKind :: Return => {
350
- if !self . tcx . features ( ) . const_let {
351
- // Check for unused values. This usually means
352
- // there are extra statements in the AST.
353
- for temp in mir. temps_iter ( ) {
354
- if self . local_qualif [ temp] . is_none ( ) {
355
- continue ;
356
- }
357
-
358
- let state = self . temp_promotion_state [ temp] ;
359
- if let TempState :: Defined { location, uses : 0 } = state {
360
- let data = & mir[ location. block ] ;
361
- let stmt_idx = location. statement_index ;
362
-
363
- // Get the span for the initialization.
364
- let source_info = if stmt_idx < data. statements . len ( ) {
365
- data. statements [ stmt_idx] . source_info
366
- } else {
367
- data. terminator ( ) . source_info
368
- } ;
369
- self . span = source_info. span ;
370
-
371
- // Treat this as a statement in the AST.
372
- self . statement_like ( ) ;
373
- }
374
- }
375
-
376
- // Make sure there are no extra unassigned variables.
377
- self . qualif = Qualif :: NOT_CONST ;
378
- for index in mir. vars_iter ( ) {
379
- if !self . const_fn_arg_vars . contains ( index) {
380
- debug ! ( "unassigned variable {:?}" , index) ;
381
- self . assign ( & Place :: Local ( index) , Location {
382
- block : bb,
383
- statement_index : usize:: MAX ,
384
- } ) ;
385
- }
386
- }
387
- }
388
-
389
294
break ;
390
295
}
391
296
} ;
@@ -454,12 +359,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
454
359
LocalKind :: ReturnPointer => {
455
360
self . not_const ( ) ;
456
361
}
457
- LocalKind :: Var if !self . tcx . features ( ) . const_let => {
458
- if self . mode != Mode :: Fn {
459
- emit_feature_err ( & self . tcx . sess . parse_sess , "const_let" ,
460
- self . span , GateIssue :: Language ,
461
- & format ! ( "let bindings in {}s are unstable" , self . mode) ) ;
462
- }
362
+ LocalKind :: Var if self . mode == Mode :: Fn => {
463
363
self . add ( Qualif :: NOT_CONST ) ;
464
364
}
465
365
LocalKind :: Var |
@@ -569,6 +469,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
569
469
}
570
470
}
571
471
472
+ ProjectionElem :: ConstantIndex { ..} |
473
+ ProjectionElem :: Subslice { ..} |
572
474
ProjectionElem :: Field ( ..) |
573
475
ProjectionElem :: Index ( _) => {
574
476
let base_ty = proj. base . ty ( this. mir , this. tcx ) . to_ty ( this. tcx ) ;
@@ -598,8 +500,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
598
500
this. qualif . restrict ( ty, this. tcx , this. param_env ) ;
599
501
}
600
502
601
- ProjectionElem :: ConstantIndex { ..} |
602
- ProjectionElem :: Subslice { ..} |
603
503
ProjectionElem :: Downcast ( ..) => {
604
504
this. not_const ( )
605
505
}
@@ -1168,46 +1068,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
1168
1068
debug ! ( "visit_assign: dest={:?} rvalue={:?} location={:?}" , dest, rvalue, location) ;
1169
1069
self . visit_rvalue ( rvalue, location) ;
1170
1070
1171
- // Check the allowed const fn argument forms.
1172
- if let ( Mode :: ConstFn , & Place :: Local ( index) ) = ( self . mode , dest) {
1173
- if self . mir . local_kind ( index) == LocalKind :: Var &&
1174
- self . const_fn_arg_vars . insert ( index) &&
1175
- !self . tcx . features ( ) . const_let {
1176
- // Direct use of an argument is permitted.
1177
- match * rvalue {
1178
- Rvalue :: Use ( Operand :: Copy ( Place :: Local ( local) ) ) |
1179
- Rvalue :: Use ( Operand :: Move ( Place :: Local ( local) ) ) => {
1180
- if self . mir . local_kind ( local) == LocalKind :: Arg {
1181
- return ;
1182
- }
1183
- }
1184
- _ => { }
1185
- }
1186
- // Avoid a generic error for other uses of arguments.
1187
- if self . qualif . contains ( Qualif :: FN_ARGUMENT ) {
1188
- let decl = & self . mir . local_decls [ index] ;
1189
- let mut err = feature_err (
1190
- & self . tcx . sess . parse_sess ,
1191
- "const_let" ,
1192
- decl. source_info . span ,
1193
- GateIssue :: Language ,
1194
- "arguments of constant functions can only be immutable by-value bindings"
1195
- ) ;
1196
- if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
1197
- err. note ( "Constant functions are not allowed to mutate anything. Thus, \
1198
- binding to an argument with a mutable pattern is not allowed.") ;
1199
- err. note ( "Remove any mutable bindings from the argument list to fix this \
1200
- error. In case you need to mutate the argument, try lazily \
1201
- initializing a global variable instead of using a const fn, or \
1202
- refactoring the code to a functional style to avoid mutation if \
1203
- possible.") ;
1204
- }
1205
- err. emit ( ) ;
1206
- return ;
1207
- }
1208
- }
1209
- }
1210
-
1211
1071
self . assign ( dest, location) ;
1212
1072
}
1213
1073
0 commit comments