@@ -32,7 +32,7 @@ use rustc::middle::lang_items;
32
32
use rustc_target:: spec:: abi:: Abi ;
33
33
use syntax:: attr;
34
34
use syntax:: ast:: LitKind ;
35
- use syntax:: feature_gate:: UnstableFeatures ;
35
+ use syntax:: feature_gate:: { UnstableFeatures , emit_feature_err , GateIssue } ;
36
36
use syntax_pos:: { Span , DUMMY_SP } ;
37
37
38
38
use std:: fmt;
@@ -120,8 +120,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
120
120
rpo : ReversePostorder < ' a , ' tcx > ,
121
121
tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
122
122
param_env : ty:: ParamEnv < ' tcx > ,
123
- temp_qualif : IndexVec < Local , Option < Qualif > > ,
124
- return_qualif : Option < Qualif > ,
123
+ local_qualif : IndexVec < Local , Option < Qualif > > ,
125
124
qualif : Qualif ,
126
125
const_fn_arg_vars : BitVector ,
127
126
temp_promotion_state : IndexVec < Local , TempState > ,
@@ -140,11 +139,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
140
139
141
140
let param_env = tcx. param_env ( def_id) ;
142
141
143
- let mut temp_qualif = IndexVec :: from_elem ( None , & mir. local_decls ) ;
142
+ let mut local_qualif = IndexVec :: from_elem ( None , & mir. local_decls ) ;
144
143
for arg in mir. args_iter ( ) {
145
144
let mut qualif = Qualif :: NEEDS_DROP ;
146
145
qualif. restrict ( mir. local_decls [ arg] . ty , tcx, param_env) ;
147
- temp_qualif [ arg] = Some ( qualif) ;
146
+ local_qualif [ arg] = Some ( qualif) ;
148
147
}
149
148
150
149
Qualifier {
@@ -155,8 +154,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
155
154
rpo,
156
155
tcx,
157
156
param_env,
158
- temp_qualif,
159
- return_qualif : None ,
157
+ local_qualif,
160
158
qualif : Qualif :: empty ( ) ,
161
159
const_fn_arg_vars : BitVector :: new ( mir. local_decls . len ( ) ) ,
162
160
temp_promotion_state : temps,
@@ -191,6 +189,11 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
191
189
fn statement_like ( & mut self ) {
192
190
self . add ( Qualif :: NOT_CONST ) ;
193
191
if self . mode != Mode :: Fn {
192
+ if self . span . allows_unstable ( ) {
193
+ emit_feature_err ( & self . tcx . sess . parse_sess , "const_let" ,
194
+ self . span , GateIssue :: Language ,
195
+ "statements in const fn are unstable" ) ;
196
+ }
194
197
let mut err = struct_span_err ! (
195
198
self . tcx. sess,
196
199
self . span,
@@ -266,6 +269,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
266
269
267
270
/// Assign the current qualification to the given destination.
268
271
fn assign ( & mut self , dest : & Place < ' tcx > , location : Location ) {
272
+ trace ! ( "assign: {:?}" , dest) ;
269
273
let qualif = self . qualif ;
270
274
let span = self . span ;
271
275
let store = |slot : & mut Option < Qualif > | {
@@ -281,28 +285,34 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
281
285
if self . mir . local_kind ( index) == LocalKind :: Temp
282
286
&& self . temp_promotion_state [ index] . is_promotable ( ) {
283
287
debug ! ( "store to promotable temp {:?}" , index) ;
284
- store ( & mut self . temp_qualif [ index] ) ;
288
+ store ( & mut self . local_qualif [ index] ) ;
285
289
}
286
290
}
287
291
return ;
288
292
}
289
293
290
294
match * dest {
295
+ Place :: Local ( index) if ( self . mir . local_kind ( index) == LocalKind :: Var ||
296
+ self . mir . local_kind ( index) == LocalKind :: Arg ) &&
297
+ self . tcx . sess . features_untracked ( ) . const_let => {
298
+ debug ! ( "store to var {:?}" , index) ;
299
+ self . local_qualif [ index] = Some ( self . qualif ) ;
300
+ }
291
301
Place :: Local ( index) if self . mir . local_kind ( index) == LocalKind :: Temp => {
292
302
debug ! ( "store to temp {:?}" , index) ;
293
- store ( & mut self . temp_qualif [ index] )
303
+ store ( & mut self . local_qualif [ index] )
294
304
}
295
305
Place :: Local ( index) if self . mir . local_kind ( index) == LocalKind :: ReturnPointer => {
296
306
debug ! ( "store to return place {:?}" , index) ;
297
- store ( & mut self . return_qualif )
307
+ store ( & mut self . local_qualif [ RETURN_PLACE ] )
298
308
}
299
309
300
310
Place :: Projection ( box Projection {
301
311
base : Place :: Local ( index) ,
302
312
elem : ProjectionElem :: Deref
303
313
} ) if self . mir . local_kind ( index) == LocalKind :: Temp
304
314
&& self . mir . local_decls [ index] . ty . is_box ( )
305
- && self . temp_qualif [ index] . map_or ( false , |qualif| {
315
+ && self . local_qualif [ index] . map_or ( false , |qualif| {
306
316
qualif. intersects ( Qualif :: NOT_CONST )
307
317
} ) => {
308
318
// Part of `box expr`, we should've errored
@@ -355,10 +365,13 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
355
365
TerminatorKind :: FalseUnwind { .. } => None ,
356
366
357
367
TerminatorKind :: Return => {
368
+ if self . tcx . sess . features_untracked ( ) . const_let {
369
+ break ;
370
+ }
358
371
// Check for unused values. This usually means
359
372
// there are extra statements in the AST.
360
373
for temp in mir. temps_iter ( ) {
361
- if self . temp_qualif [ temp] . is_none ( ) {
374
+ if self . local_qualif [ temp] . is_none ( ) {
362
375
continue ;
363
376
}
364
377
@@ -408,7 +421,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
408
421
}
409
422
}
410
423
411
- self . qualif = self . return_qualif . unwrap_or ( Qualif :: NOT_CONST ) ;
424
+ self . qualif = self . local_qualif [ RETURN_PLACE ] . unwrap_or ( Qualif :: NOT_CONST ) ;
412
425
413
426
// Account for errors in consts by using the
414
427
// conservative type qualification instead.
@@ -453,9 +466,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
453
466
LocalKind :: ReturnPointer => {
454
467
self . not_const ( ) ;
455
468
}
456
- LocalKind :: Var => {
469
+ LocalKind :: Var if !self . tcx . sess . features_untracked ( ) . const_let => {
470
+ if self . mode != Mode :: Fn && self . span . allows_unstable ( ) {
471
+ emit_feature_err ( & self . tcx . sess . parse_sess , "const_let" ,
472
+ self . span , GateIssue :: Language ,
473
+ "let bindings in const fn are unstable" ) ;
474
+ }
457
475
self . add ( Qualif :: NOT_CONST ) ;
458
476
}
477
+ LocalKind :: Var |
459
478
LocalKind :: Arg |
460
479
LocalKind :: Temp => {
461
480
if let LocalKind :: Arg = kind {
@@ -466,7 +485,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
466
485
self . add ( Qualif :: NOT_PROMOTABLE ) ;
467
486
}
468
487
469
- if let Some ( qualif) = self . temp_qualif [ local] {
488
+ if let Some ( qualif) = self . local_qualif [ local] {
470
489
self . add ( qualif) ;
471
490
} else {
472
491
self . not_const ( ) ;
@@ -588,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
588
607
589
608
// Mark the consumed locals to indicate later drops are noops.
590
609
if let Operand :: Move ( Place :: Local ( local) ) = * operand {
591
- self . temp_qualif [ local] = self . temp_qualif [ local] . map ( |q|
610
+ self . local_qualif [ local] = self . local_qualif [ local] . map ( |q|
592
611
q - Qualif :: NEEDS_DROP
593
612
) ;
594
613
}
@@ -1033,7 +1052,7 @@ This does not pose a problem by itself because they can't be accessed directly."
1033
1052
// HACK(eddyb) Emulate a bit of dataflow analysis,
1034
1053
// conservatively, that drop elaboration will do.
1035
1054
let needs_drop = if let Place :: Local ( local) = * place {
1036
- if self . temp_qualif [ local] . map_or ( true , |q| q. intersects ( Qualif :: NEEDS_DROP ) ) {
1055
+ if self . local_qualif [ local] . map_or ( true , |q| q. intersects ( Qualif :: NEEDS_DROP ) ) {
1037
1056
Some ( self . mir . local_decls [ local] . source_info . span )
1038
1057
} else {
1039
1058
None
@@ -1070,7 +1089,8 @@ This does not pose a problem by itself because they can't be accessed directly."
1070
1089
// Check the allowed const fn argument forms.
1071
1090
if let ( Mode :: ConstFn , & Place :: Local ( index) ) = ( self . mode , dest) {
1072
1091
if self . mir . local_kind ( index) == LocalKind :: Var &&
1073
- self . const_fn_arg_vars . insert ( index. index ( ) ) {
1092
+ self . const_fn_arg_vars . insert ( index. index ( ) ) &&
1093
+ !self . tcx . sess . features_untracked ( ) . const_let {
1074
1094
1075
1095
// Direct use of an argument is permitted.
1076
1096
match * rvalue {
@@ -1086,6 +1106,11 @@ This does not pose a problem by itself because they can't be accessed directly."
1086
1106
// Avoid a generic error for other uses of arguments.
1087
1107
if self . qualif . intersects ( Qualif :: FN_ARGUMENT ) {
1088
1108
let decl = & self . mir . local_decls [ index] ;
1109
+ if decl. source_info . span . allows_unstable ( ) {
1110
+ emit_feature_err ( & self . tcx . sess . parse_sess , "const_let" ,
1111
+ decl. source_info . span , GateIssue :: Language ,
1112
+ "locals and patterns in const fn are unstable" ) ;
1113
+ }
1089
1114
let mut err = struct_span_err ! (
1090
1115
self . tcx. sess,
1091
1116
decl. source_info. span,
0 commit comments