Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 07faca9

Browse files
author
Meade Kincke
committedJul 14, 2018
Removed the promotable field from CheckCrateVisitor and replaced it with the structs Promotable and NotPromotable.
1 parent f629eb3 commit 07faca9

File tree

2 files changed

+213
-129
lines changed

2 files changed

+213
-129
lines changed
 

‎src/librustc_passes/rvalue_promotion.rs

Lines changed: 196 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ use rustc_data_structures::sync::Lrc;
4040
use syntax::ast;
4141
use syntax::attr;
4242
use syntax_pos::{Span, DUMMY_SP};
43+
use self::Promotability::*;
44+
use std::ops::{BitAnd, BitOr};
45+
4346

4447
pub fn provide(providers: &mut Providers) {
4548
*providers = Providers {
@@ -84,7 +87,6 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
8487
tables: &ty::TypeckTables::empty(None),
8588
in_fn: false,
8689
in_static: false,
87-
promotable: false,
8890
mut_rvalue_borrows: NodeSet(),
8991
param_env: ty::ParamEnv::empty(),
9092
identity_substs: Substs::empty(),
@@ -95,7 +97,7 @@ fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
9597
let node_id = tcx.hir.as_local_node_id(def_id)
9698
.expect("rvalue_promotable_map invoked with non-local def-id");
9799
let body_id = tcx.hir.body_owned_by(node_id);
98-
visitor.visit_nested_body(body_id);
100+
let _ = visitor.check_nested_body(body_id);
99101

100102
Lrc::new(visitor.result)
101103
}
@@ -104,38 +106,83 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
104106
tcx: TyCtxt<'a, 'tcx, 'tcx>,
105107
in_fn: bool,
106108
in_static: bool,
107-
promotable: bool,
108109
mut_rvalue_borrows: NodeSet,
109110
param_env: ty::ParamEnv<'tcx>,
110111
identity_substs: &'tcx Substs<'tcx>,
111112
tables: &'a ty::TypeckTables<'tcx>,
112113
result: ItemLocalSet,
113114
}
114115

116+
#[must_use]
117+
#[derive(Debug, PartialEq)]
118+
enum Promotability {
119+
Promotable,
120+
NotPromotable
121+
}
122+
123+
impl BitAnd for Promotability {
124+
type Output = Self;
125+
126+
fn bitand(self, rhs: Self) -> Self {
127+
match (self, rhs) {
128+
(Promotable, NotPromotable) => NotPromotable,
129+
(NotPromotable, Promotable) => NotPromotable,
130+
(NotPromotable, NotPromotable) => NotPromotable,
131+
(Promotable, Promotable) => Promotable,
132+
}
133+
}
134+
}
135+
136+
impl BitOr for Promotability {
137+
type Output = Self;
138+
139+
fn bitor(self, rhs: Self) -> Self {
140+
match (self, rhs) {
141+
(Promotable, NotPromotable) => Promotable,
142+
(NotPromotable, Promotable) => Promotable,
143+
(NotPromotable, NotPromotable) => NotPromotable,
144+
(Promotable, Promotable) => Promotable,
145+
}
146+
}
147+
}
148+
115149
impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
116150
// Returns true iff all the values of the type are promotable.
117-
fn type_has_only_promotable_values(&mut self, ty: Ty<'gcx>) -> bool {
118-
ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) &&
119-
!ty.needs_drop(self.tcx, self.param_env)
151+
fn type_promotability(&mut self, ty: Ty<'gcx>) -> Promotability {
152+
debug!("type_promotability({})", ty);
153+
154+
if ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) &&
155+
!ty.needs_drop(self.tcx, self.param_env) {
156+
Promotable
157+
} else {
158+
NotPromotable
159+
}
120160
}
121161

122-
fn handle_const_fn_call(&mut self, def_id: DefId, ret_ty: Ty<'gcx>, span: Span) {
123-
self.promotable &= self.type_has_only_promotable_values(ret_ty);
162+
fn handle_const_fn_call(&mut self, def_id: DefId,
163+
ret_ty: Ty<'gcx>, span: Span) -> Promotability {
164+
if let NotPromotable = self.type_promotability(ret_ty) {
165+
return NotPromotable;
166+
}
124167

125-
self.promotable &= if let Some(fn_id) = self.tcx.hir.as_local_node_id(def_id) {
168+
let node_check = if let Some(fn_id) = self.tcx.hir.as_local_node_id(def_id) {
126169
FnLikeNode::from_node(self.tcx.hir.get(fn_id)).map_or(false, |fn_like| {
127170
fn_like.constness() == hir::Constness::Const
128171
})
129172
} else {
130173
self.tcx.is_const_fn(def_id)
131174
};
132175

176+
if !node_check {
177+
return NotPromotable
178+
}
179+
133180
if let Some(&attr::Stability {
134181
rustc_const_unstable: Some(attr::RustcConstUnstable {
135182
feature: ref feature_name
136183
}),
137184
.. }) = self.tcx.lookup_stability(def_id) {
138-
self.promotable &=
185+
let stable_check =
139186
// feature-gate is enabled,
140187
self.tcx.features()
141188
.declared_lib_features
@@ -147,7 +194,11 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
147194

148195
// this comes from a macro that has #[allow_internal_unstable]
149196
span.allows_unstable();
150-
}
197+
if !stable_check {
198+
return NotPromotable
199+
}
200+
};
201+
Promotable
151202
}
152203

153204
/// While the `ExprUseVisitor` walks, we will identify which
@@ -169,7 +220,7 @@ impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> {
169220
}
170221

171222
impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
172-
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
223+
fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability {
173224
let item_id = self.tcx.hir.body_owner(body_id);
174225
let item_def_id = self.tcx.hir.local_def_id(item_id);
175226

@@ -200,68 +251,67 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
200251
euv::ExprUseVisitor::new(self, tcx, param_env, &region_scope_tree, self.tables, None)
201252
.consume_body(body);
202253

203-
self.visit_expr(&body.value);
254+
let body_promotable = self.check_expr(&body.value);
204255
self.in_fn = outer_in_fn;
205256
self.tables = outer_tables;
206257
self.param_env = outer_param_env;
207258
self.identity_substs = outer_identity_substs;
259+
body_promotable
208260
}
209261

210-
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt) {
262+
fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability {
211263
match stmt.node {
212264
hir::StmtDecl(ref decl, _node_id) => {
213265
match &decl.node {
214266
hir::DeclLocal(local) => {
215-
self.promotable = false;
216267
if self.remove_mut_rvalue_borrow(&local.pat) {
217268
if let Some(init) = &local.init {
218269
self.mut_rvalue_borrows.insert(init.id);
219270
}
220271
}
221272

222273
match local.init {
223-
Some(ref expr) => self.visit_expr(&expr),
274+
Some(ref expr) => { let _ = self.check_expr(&expr); },
224275
None => {},
225276
}
277+
NotPromotable
226278
}
227279
// Item statements are allowed
228-
hir::DeclItem(_) => {}
280+
hir::DeclItem(_) => Promotable
229281
}
230282
}
231283
hir::StmtExpr(ref box_expr, _node_id) |
232284
hir::StmtSemi(ref box_expr, _node_id) => {
233-
self.visit_expr(box_expr);
234-
self.promotable = false;
285+
let _ = self.check_expr(box_expr);
286+
NotPromotable
235287
}
236288
}
237289
}
238290

239-
fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
240-
let outer = self.promotable;
241-
self.promotable = true;
242-
291+
fn check_expr(&mut self, ex: &'tcx hir::Expr) -> Promotability {
243292
let node_ty = self.tables.node_id_to_type(ex.hir_id);
244-
check_expr(self, ex, node_ty);
245-
check_adjustments(self, ex);
293+
let mut outer = check_expr_kind(self, ex, node_ty);
294+
outer = outer & check_adjustments(self, ex);
246295

247296
// Handle borrows on (or inside the autorefs of) this expression.
248297
if self.mut_rvalue_borrows.remove(&ex.id) {
249-
self.promotable = false;
298+
outer = NotPromotable
250299
}
251300

252-
if self.promotable {
301+
if outer == Promotable {
253302
self.result.insert(ex.hir_id.local_id);
254303
}
255-
self.promotable &= outer;
304+
outer
256305
}
257306

258-
fn visit_block(&mut self, block: &'tcx hir::Block) {
307+
fn check_block(&mut self, block: &'tcx hir::Block) -> Promotability {
308+
let mut iter_result = Promotable;
259309
for index in block.stmts.iter() {
260-
self.visit_stmt(index)
310+
iter_result = iter_result & self.check_stmt(index);
261311
}
262312
match block.expr {
263-
Some(ref box_expr) => { self.visit_expr(&*box_expr) },
264-
None => {},
313+
Some(ref box_expr) => iter_result & self.check_expr(&*box_expr),
314+
None => iter_result,
265315
}
266316
}
267317
}
@@ -272,63 +322,68 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
272322
/// every nested expression. If the expression is not part
273323
/// of a const/static item, it is qualified for promotion
274324
/// instead of producing errors.
275-
fn check_expr<'a, 'tcx>(
325+
fn check_expr_kind<'a, 'tcx>(
276326
v: &mut CheckCrateVisitor<'a, 'tcx>,
277-
e: &'tcx hir::Expr, node_ty: Ty<'tcx>) {
278-
match node_ty.sty {
327+
e: &'tcx hir::Expr, node_ty: Ty<'tcx>) -> Promotability {
328+
329+
let ty_result = match node_ty.sty {
279330
ty::TyAdt(def, _) if def.has_dtor(v.tcx) => {
280-
v.promotable = false;
331+
NotPromotable
281332
}
282-
_ => {}
283-
}
333+
_ => Promotable
334+
};
284335

285-
match e.node {
336+
let node_result = match e.node {
286337
hir::ExprBox(ref expr) => {
287-
v.visit_expr(&expr);
288-
v.promotable = false;
338+
let _ = v.check_expr(&expr);
339+
NotPromotable
289340
}
290341
hir::ExprUnary(op, ref expr) => {
342+
let expr_promotability = v.check_expr(expr);
291343
if v.tables.is_method_call(e) {
292-
v.promotable = false;
344+
return NotPromotable;
293345
}
294346
if op == hir::UnDeref {
295-
v.promotable = false;
347+
return NotPromotable;
296348
}
297-
v.visit_expr(expr);
349+
expr_promotability
298350
}
299351
hir::ExprBinary(op, ref lhs, ref rhs) => {
352+
let lefty = v.check_expr(lhs);
353+
let righty = v.check_expr(rhs);
300354
if v.tables.is_method_call(e) {
301-
v.promotable = false;
355+
return NotPromotable;
302356
}
303-
v.visit_expr(lhs);
304-
v.visit_expr(rhs);
305357
match v.tables.node_id_to_type(lhs.hir_id).sty {
306358
ty::TyRawPtr(_) => {
307359
assert!(op.node == hir::BiEq || op.node == hir::BiNe ||
308360
op.node == hir::BiLe || op.node == hir::BiLt ||
309361
op.node == hir::BiGe || op.node == hir::BiGt);
310362

311-
v.promotable = false;
363+
NotPromotable
312364
}
313-
_ => {}
365+
_ => lefty & righty
314366
}
315367
}
316368
hir::ExprCast(ref from, _) => {
317-
v.visit_expr(from);
369+
let expr_promotability = v.check_expr(from);
318370
debug!("Checking const cast(id={})", from.id);
319371
match v.tables.cast_kinds().get(from.hir_id) {
320-
None => v.tcx.sess.delay_span_bug(e.span, "no kind for cast"),
372+
None => {
373+
v.tcx.sess.delay_span_bug(e.span, "no kind for cast");
374+
NotPromotable
375+
},
321376
Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
322-
v.promotable = false;
377+
NotPromotable
323378
}
324-
_ => {}
379+
_ => expr_promotability
325380
}
326381
}
327382
hir::ExprPath(ref qpath) => {
328383
let def = v.tables.qpath_def(qpath, e.hir_id);
329384
match def {
330385
Def::VariantCtor(..) | Def::StructCtor(..) |
331-
Def::Fn(..) | Def::Method(..) => {}
386+
Def::Fn(..) | Def::Method(..) => Promotable,
332387

333388
// References to a static that are themselves within a static
334389
// are inherently promotable with the exception
@@ -337,25 +392,18 @@ fn check_expr<'a, 'tcx>(
337392
Def::Static(did, _) => {
338393

339394
if v.in_static {
340-
let mut thread_local = false;
341-
342395
for attr in &v.tcx.get_attrs(did)[..] {
343396
if attr.check_name("thread_local") {
344397
debug!("Reference to Static(id={:?}) is unpromotable \
345398
due to a #[thread_local] attribute", did);
346-
v.promotable = false;
347-
thread_local = true;
348-
break;
399+
return NotPromotable;
349400
}
350401
}
351-
352-
if !thread_local {
353-
debug!("Allowing promotion of reference to Static(id={:?})", did);
354-
}
402+
Promotable
355403
} else {
356404
debug!("Reference to Static(id={:?}) is unpromotable as it is not \
357405
referenced from a static", did);
358-
v.promotable = false;
406+
NotPromotable
359407

360408
}
361409
}
@@ -364,26 +412,24 @@ fn check_expr<'a, 'tcx>(
364412
Def::AssociatedConst(did) => {
365413
let promotable = if v.tcx.trait_of_item(did).is_some() {
366414
// Don't peek inside trait associated constants.
367-
false
415+
NotPromotable
416+
} else if v.tcx.at(e.span).const_is_rvalue_promotable_to_static(did) {
417+
Promotable
368418
} else {
369-
v.tcx.at(e.span).const_is_rvalue_promotable_to_static(did)
419+
NotPromotable
370420
};
371-
372421
// Just in case the type is more specific than the definition,
373422
// e.g. impl associated const with type parameters, check it.
374423
// Also, trait associated consts are relaxed by this.
375-
v.promotable &= promotable || v.type_has_only_promotable_values(node_ty);
376-
}
377-
378-
_ => {
379-
v.promotable = false;
424+
promotable | v.type_promotability(node_ty)
380425
}
426+
_ => NotPromotable
381427
}
382428
}
383429
hir::ExprCall(ref callee, ref hirvec) => {
384-
v.visit_expr(callee);
430+
let mut call_result = v.check_expr(callee);
385431
for index in hirvec.iter() {
386-
v.visit_expr(index)
432+
call_result = call_result & v.check_expr(index);
387433
}
388434
let mut callee = &**callee;
389435
loop {
@@ -401,9 +447,9 @@ fn check_expr<'a, 'tcx>(
401447
} else {
402448
Def::Err
403449
};
404-
match def {
450+
let def_result = match def {
405451
Def::StructCtor(_, CtorKind::Fn) |
406-
Def::VariantCtor(_, CtorKind::Fn) => {}
452+
Def::VariantCtor(_, CtorKind::Fn) => Promotable,
407453
Def::Fn(did) => {
408454
v.handle_const_fn_call(did, node_ty, e.span)
409455
}
@@ -412,94 +458,110 @@ fn check_expr<'a, 'tcx>(
412458
ty::ImplContainer(_) => {
413459
v.handle_const_fn_call(did, node_ty, e.span)
414460
}
415-
ty::TraitContainer(_) => v.promotable = false
461+
ty::TraitContainer(_) => NotPromotable,
416462
}
417463
}
418-
_ => v.promotable = false
419-
}
464+
_ => NotPromotable,
465+
};
466+
def_result & call_result
420467
}
421468
hir::ExprMethodCall(ref _pathsegment, ref _span, ref hirvec) => {
469+
let mut method_call_result = Promotable;
422470
for index in hirvec.iter() {
423-
v.visit_expr(index)
471+
method_call_result = method_call_result & v.check_expr(index);
424472
}
425473
if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) {
426474
let def_id = def.def_id();
427475
match v.tcx.associated_item(def_id).container {
428-
ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty, e.span),
429-
ty::TraitContainer(_) => v.promotable = false
430-
}
476+
ty::ImplContainer(_) => {
477+
method_call_result = method_call_result
478+
& v.handle_const_fn_call(def_id, node_ty, e.span);
479+
}
480+
ty::TraitContainer(_) => return NotPromotable,
481+
};
431482
} else {
432483
v.tcx.sess.delay_span_bug(e.span, "no type-dependent def for method call");
433484
}
485+
method_call_result
434486
}
435487
hir::ExprStruct(ref _qpath, ref hirvec, ref option_expr) => {
488+
let mut struct_result = Promotable;
436489
for index in hirvec.iter() {
437-
v.visit_expr(&index.expr);
490+
struct_result = struct_result & v.check_expr(&index.expr);
438491
}
439492
match *option_expr {
440-
Some(ref expr) => { v.visit_expr(&expr) },
493+
Some(ref expr) => { struct_result = struct_result & v.check_expr(&expr); },
441494
None => {},
442495
}
443496
if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty {
444497
// unsafe_cell_type doesn't necessarily exist with no_core
445498
if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() {
446-
v.promotable = false;
499+
return NotPromotable;
447500
}
448501
}
502+
struct_result
449503
}
450504

451-
hir::ExprLit(_) => {}
505+
hir::ExprLit(_) => Promotable,
452506

453507
hir::ExprAddrOf(_, ref expr) |
454508
hir::ExprRepeat(ref expr, _) => {
455-
v.visit_expr(expr);
509+
v.check_expr(&expr)
456510
}
457511

458512
hir::ExprClosure(_capture_clause, ref _box_fn_decl,
459513
body_id, _span, _option_generator_movability) => {
460-
v.visit_nested_body(body_id);
514+
let nested_body_promotable = v.check_nested_body(body_id);
461515
// Paths in constant contexts cannot refer to local variables,
462516
// as there are none, and thus closures can't have upvars there.
463517
if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
464-
v.promotable = false;
518+
NotPromotable
519+
} else {
520+
nested_body_promotable
465521
}
466522
}
467523

468524
hir::ExprField(ref expr, _ident) => {
469-
v.visit_expr(expr);
525+
let expr_promotability = v.check_expr(&expr);
470526
if let Some(def) = v.tables.expr_ty(expr).ty_adt_def() {
471527
if def.is_union() {
472-
v.promotable = false
528+
return NotPromotable;
473529
}
474530
}
531+
expr_promotability
475532
}
476533

477534
hir::ExprBlock(ref box_block, ref _option_label) => {
478-
v.visit_block(box_block);
535+
v.check_block(box_block)
479536
}
480537

481538
hir::ExprIndex(ref lhs, ref rhs) => {
539+
let lefty = v.check_expr(lhs);
540+
let righty = v.check_expr(rhs);
482541
if v.tables.is_method_call(e) {
483-
v.promotable = false;
542+
return NotPromotable;
484543
}
485-
v.visit_expr(lhs);
486-
v.visit_expr(rhs);
544+
lefty & righty
487545
}
488546

489547
hir::ExprArray(ref hirvec) => {
548+
let mut array_result = Promotable;
490549
for index in hirvec.iter() {
491-
v.visit_expr(index)
550+
array_result = array_result & v.check_expr(index);
492551
}
552+
array_result
493553
}
494554

495555
hir::ExprType(ref expr, ref _ty) => {
496-
v.visit_expr(expr);
556+
v.check_expr(&expr)
497557
}
498558

499559
hir::ExprTup(ref hirvec) => {
560+
let mut tup_result = Promotable;
500561
for index in hirvec.iter() {
501-
v.visit_expr(index)
562+
tup_result = tup_result & v.check_expr(index);
502563
}
564+
tup_result
503565
}
504566

505567

@@ -515,79 +577,84 @@ fn check_expr<'a, 'tcx>(
515577
v.mut_rvalue_borrows.insert(expr.id);
516578
}
517579

518-
v.visit_expr(expr);
580+
let _ = v.check_expr(expr);
519581
for index in hirvec_arm.iter() {
520-
v.visit_expr(&*index.body);
582+
let _ = v.check_expr(&*index.body);
521583
match index.guard {
522-
Some(ref expr) => v.visit_expr(&expr),
584+
Some(ref expr) => {
585+
let _ = v.check_expr(&expr);
586+
},
523587
None => {},
524-
}
588+
};
525589
}
526-
v.promotable = false;
590+
NotPromotable
527591
}
528592

529593
hir::ExprIf(ref lhs, ref rhs, ref option_expr) => {
530-
v.visit_expr(lhs);
531-
v.visit_expr(rhs);
594+
let _ = v.check_expr(lhs);
595+
let _ = v.check_expr(rhs);
532596
match option_expr {
533-
Some(ref expr) => v.visit_expr(&expr),
597+
Some(ref expr) => { let _ = v.check_expr(&expr); },
534598
None => {},
535-
}
536-
v.promotable = false;
599+
};
600+
NotPromotable
537601
}
538602

539603
// Loops (not very meaningful in constants).
540604
hir::ExprWhile(ref expr, ref box_block, ref _option_label) => {
541-
v.visit_expr(expr);
542-
v.visit_block(box_block);
543-
v.promotable = false;
605+
let _ = v.check_expr(expr);
606+
let _ = v.check_block(box_block);
607+
NotPromotable
544608
}
545609

546610
hir::ExprLoop(ref box_block, ref _option_label, ref _loop_source) => {
547-
v.visit_block(box_block);
548-
v.promotable = false;
611+
let _ = v.check_block(box_block);
612+
NotPromotable
549613
}
550614

551615
// More control flow (also not very meaningful).
552616
hir::ExprBreak(_, ref option_expr) | hir::ExprRet(ref option_expr) => {
553617
match *option_expr {
554-
Some(ref expr) => { v.visit_expr(&expr) },
618+
Some(ref expr) => { let _ = v.check_expr(&expr); },
555619
None => {},
556620
}
557-
v.promotable = false;
621+
NotPromotable
558622
}
559623

560624
hir::ExprContinue(_) => {
561-
v.promotable = false;
625+
NotPromotable
562626
}
563627

564628
// Generator expressions
565629
hir::ExprYield(ref expr) => {
566-
v.visit_expr(&expr);
567-
v.promotable = false;
630+
let _ = v.check_expr(&expr);
631+
NotPromotable
568632
}
569633

570634
// Expressions with side-effects.
571635
hir::ExprAssignOp(_, ref lhs, ref rhs) | hir::ExprAssign(ref lhs, ref rhs) => {
572-
v.visit_expr(lhs);
573-
v.visit_expr(rhs);
574-
v.promotable = false;
636+
let _ = v.check_expr(lhs);
637+
let _ = v.check_expr(rhs);
638+
NotPromotable
575639
}
576640

577641
hir::ExprInlineAsm(ref _inline_asm, ref hirvec_lhs, ref hirvec_rhs) => {
578642
for index in hirvec_lhs.iter() {
579-
v.visit_expr(index)
643+
let _ = v.check_expr(index);
580644
}
581645
for index in hirvec_rhs.iter() {
582-
v.visit_expr(index)
646+
let _ = v.check_expr(index);
583647
}
584-
v.promotable = false;
648+
NotPromotable
585649
}
586-
}
650+
};
651+
ty_result & node_result
587652
}
588653

589654
/// Check the adjustments of an expression
590-
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
655+
fn check_adjustments<'a, 'tcx>(
656+
v: &mut CheckCrateVisitor<'a, 'tcx>,
657+
e: &hir::Expr) -> Promotability {
591658
use rustc::ty::adjustment::*;
592659

593660
let mut adjustments = v.tables.expr_adjustments(e).iter().peekable();
@@ -607,11 +674,11 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
607674
continue;
608675
}
609676
}
610-
v.promotable = false;
611-
break;
677+
return NotPromotable;
612678
}
613679
}
614680
}
681+
Promotable
615682
}
616683

617684
impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![allow(const_err)]
12+
13+
// nll successfully compiles this. It is a bug.
14+
// See https://github.com/rust-lang/rust/issues/52384
15+
fn main() {
16+
let x: &'static _ = &|| { let z = 3; z }; //~ ERROR does not live long enough
17+
}

0 commit comments

Comments
 (0)
Please sign in to comment.