@@ -21,7 +21,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUs
2121use rustc:: middle:: lang_items;
2222use rustc:: session:: config:: nightly_options;
2323use 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 } ;
2525use syntax_pos:: { Span , DUMMY_SP } ;
2626
2727use std:: fmt;
@@ -104,7 +104,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
104104 param_env : ty:: ParamEnv < ' tcx > ,
105105 local_qualif : IndexVec < Local , Option < Qualif > > ,
106106 qualif : Qualif ,
107- const_fn_arg_vars : BitSet < Local > ,
108107 temp_promotion_state : IndexVec < Local , TempState > ,
109108 promotion_candidates : Vec < Candidate >
110109}
@@ -139,7 +138,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
139138 param_env,
140139 local_qualif,
141140 qualif : Qualif :: empty ( ) ,
142- const_fn_arg_vars : BitSet :: new_empty ( mir. local_decls . len ( ) ) ,
143141 temp_promotion_state : temps,
144142 promotion_candidates : vec ! [ ]
145143 }
@@ -168,26 +166,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
168166 }
169167 }
170168
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-
191169 /// Add the given qualification to self.qualif.
192170 fn add ( & mut self , qualif : Qualif ) {
193171 self . qualif = self . qualif | qualif;
@@ -233,80 +211,46 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
233211 return ;
234212 }
235213
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 ;
266242 }
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 ( ) ;
309243 }
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 ) ,
310254 }
311255 }
312256
@@ -347,45 +291,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
347291 TerminatorKind :: FalseUnwind { .. } => None ,
348292
349293 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-
389294 break ;
390295 }
391296 } ;
@@ -454,12 +359,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
454359 LocalKind :: ReturnPointer => {
455360 self . not_const ( ) ;
456361 }
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 => {
463363 self . add ( Qualif :: NOT_CONST ) ;
464364 }
465365 LocalKind :: Var |
@@ -569,6 +469,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
569469 }
570470 }
571471
472+ ProjectionElem :: ConstantIndex { ..} |
473+ ProjectionElem :: Subslice { ..} |
572474 ProjectionElem :: Field ( ..) |
573475 ProjectionElem :: Index ( _) => {
574476 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> {
598500 this. qualif . restrict ( ty, this. tcx , this. param_env ) ;
599501 }
600502
601- ProjectionElem :: ConstantIndex { ..} |
602- ProjectionElem :: Subslice { ..} |
603503 ProjectionElem :: Downcast ( ..) => {
604504 this. not_const ( )
605505 }
@@ -1168,46 +1068,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
11681068 debug ! ( "visit_assign: dest={:?} rvalue={:?} location={:?}" , dest, rvalue, location) ;
11691069 self . visit_rvalue ( rvalue, location) ;
11701070
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-
12111071 self . assign ( dest, location) ;
12121072 }
12131073
0 commit comments