Skip to content

Commit 69b9e1e

Browse files
committed
Auto merge of #51967 - varkor:const-body-break-continue, r=estebank
Fix various issues with control-flow statements inside anonymous constants Fixes #51761. Fixes #51963 (and the host of other reported issues there). (Might be easiest to review per commit, as they should be standalone.) r? @estebank
2 parents 6fc21e5 + adf4ef7 commit 69b9e1e

20 files changed

+288
-156
lines changed

src/librustc/hir/lowering.rs

+35-25
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pub struct LoweringContext<'a> {
103103
loop_scopes: Vec<NodeId>,
104104
is_in_loop_condition: bool,
105105
is_in_trait_impl: bool,
106+
is_in_anon_const: bool,
106107

107108
/// What to do when we encounter either an "anonymous lifetime
108109
/// reference". The term "anonymous" is meant to encompass both
@@ -230,6 +231,7 @@ pub fn lower_crate(
230231
node_id_to_hir_id: IndexVec::new(),
231232
is_generator: false,
232233
is_in_trait_impl: false,
234+
is_in_anon_const: false,
233235
lifetimes_to_define: Vec::new(),
234236
is_collecting_in_band_lifetimes: false,
235237
in_scope_lifetimes: Vec::new(),
@@ -968,31 +970,30 @@ impl<'a> LoweringContext<'a> {
968970
}
969971

970972
fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination {
971-
match destination {
972-
Some((id, label)) => {
973-
let target_id = if let Def::Label(loop_id) = self.expect_full_def(id) {
974-
Ok(self.lower_node_id(loop_id).node_id)
975-
} else {
976-
Err(hir::LoopIdError::UnresolvedLabel)
977-
};
978-
hir::Destination {
979-
label: self.lower_label(Some(label)),
980-
target_id,
973+
let target_id = if self.is_in_anon_const {
974+
Err(hir::LoopIdError::OutsideLoopScope)
975+
} else {
976+
match destination {
977+
Some((id, _)) => {
978+
if let Def::Label(loop_id) = self.expect_full_def(id) {
979+
Ok(self.lower_node_id(loop_id).node_id)
980+
} else {
981+
Err(hir::LoopIdError::UnresolvedLabel)
982+
}
981983
}
982-
}
983-
None => {
984-
let target_id = self.loop_scopes
985-
.last()
986-
.map(|innermost_loop_id| *innermost_loop_id)
987-
.map(|id| Ok(self.lower_node_id(id).node_id))
988-
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
989-
.into();
990-
991-
hir::Destination {
992-
label: None,
993-
target_id,
984+
None => {
985+
self.loop_scopes
986+
.last()
987+
.map(|innermost_loop_id| *innermost_loop_id)
988+
.map(|id| Ok(self.lower_node_id(id).node_id))
989+
.unwrap_or(Err(hir::LoopIdError::OutsideLoopScope))
990+
.into()
994991
}
995992
}
993+
};
994+
hir::Destination {
995+
label: self.lower_label(destination.map(|(_, label)| label)),
996+
target_id,
996997
}
997998
}
998999

@@ -3447,13 +3448,22 @@ impl<'a> LoweringContext<'a> {
34473448
}
34483449

34493450
fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
3450-
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
3451+
let was_in_loop_condition = self.is_in_loop_condition;
3452+
self.is_in_loop_condition = false;
3453+
let was_in_anon_const = self.is_in_anon_const;
3454+
self.is_in_anon_const = true;
34513455

3452-
hir::AnonConst {
3456+
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(c.id);
3457+
let anon_const = hir::AnonConst {
34533458
id: node_id,
34543459
hir_id,
34553460
body: self.lower_body(None, |this| this.lower_expr(&c.value)),
3456-
}
3461+
};
3462+
3463+
self.is_in_anon_const = was_in_anon_const;
3464+
self.is_in_loop_condition = was_in_loop_condition;
3465+
3466+
anon_const
34573467
}
34583468

34593469
fn lower_expr(&mut self, e: &Expr) -> hir::Expr {

src/librustc/middle/expr_use_visitor.rs

+28-25
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
840840
fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
841841
debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat);
842842

843+
let tcx = self.tcx();
843844
let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
844845
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
845846
if let PatKind::Binding(_, canonical_id, ..) = pat.node {
@@ -849,34 +850,36 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
849850
pat,
850851
match_mode,
851852
);
852-
let bm = *mc.tables.pat_binding_modes().get(pat.hir_id)
853-
.expect("missing binding mode");
854-
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
855-
856-
// pat_ty: the type of the binding being produced.
857-
let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
858-
debug!("walk_pat: pat_ty={:?}", pat_ty);
859-
860-
// Each match binding is effectively an assignment to the
861-
// binding being produced.
862-
let def = Def::Local(canonical_id);
863-
if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) {
864-
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
865-
}
853+
if let Some(&bm) = mc.tables.pat_binding_modes().get(pat.hir_id) {
854+
debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
855+
856+
// pat_ty: the type of the binding being produced.
857+
let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
858+
debug!("walk_pat: pat_ty={:?}", pat_ty);
859+
860+
// Each match binding is effectively an assignment to the
861+
// binding being produced.
862+
let def = Def::Local(canonical_id);
863+
if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) {
864+
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
865+
}
866866

867-
// It is also a borrow or copy/move of the value being matched.
868-
match bm {
869-
ty::BindByReference(m) => {
870-
if let ty::TyRef(r, _, _) = pat_ty.sty {
871-
let bk = ty::BorrowKind::from_mutbl(m);
872-
delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding);
867+
// It is also a borrow or copy/move of the value being matched.
868+
match bm {
869+
ty::BindByReference(m) => {
870+
if let ty::TyRef(r, _, _) = pat_ty.sty {
871+
let bk = ty::BorrowKind::from_mutbl(m);
872+
delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding);
873+
}
874+
}
875+
ty::BindByValue(..) => {
876+
let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove);
877+
debug!("walk_pat binding consuming pat");
878+
delegate.consume_pat(pat, &cmt_pat, mode);
873879
}
874880
}
875-
ty::BindByValue(..) => {
876-
let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove);
877-
debug!("walk_pat binding consuming pat");
878-
delegate.consume_pat(pat, &cmt_pat, mode);
879-
}
881+
} else {
882+
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
880883
}
881884
}
882885
}));

src/librustc/ty/layout.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1115,12 +1115,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
11151115
}
11161116
tcx.layout_raw(param_env.and(normalized))?
11171117
}
1118-
ty::TyParam(_) => {
1119-
return Err(LayoutError::Unknown(ty));
1120-
}
1121-
ty::TyGeneratorWitness(..) | ty::TyInfer(_) | ty::TyError => {
1118+
ty::TyGeneratorWitness(..) | ty::TyInfer(_) => {
11221119
bug!("LayoutDetails::compute: unexpected type `{}`", ty)
11231120
}
1121+
ty::TyParam(_) | ty::TyError => {
1122+
return Err(LayoutError::Unknown(ty));
1123+
}
11241124
})
11251125
}
11261126

src/librustc_borrowck/borrowck/unused.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,16 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
5454

5555
// Skip anything that looks like `&foo` or `&mut foo`, only look
5656
// for by-value bindings
57-
let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) {
58-
Some(&bm) => bm,
59-
None => span_bug!(span, "missing binding mode"),
60-
};
61-
match bm {
62-
ty::BindByValue(hir::MutMutable) => {}
63-
_ => return,
57+
if let Some(&bm) = self.bccx.tables.pat_binding_modes().get(hir_id) {
58+
match bm {
59+
ty::BindByValue(hir::MutMutable) => {}
60+
_ => return,
61+
}
62+
63+
mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span));
64+
} else {
65+
tcx.sess.delay_span_bug(span, "missing binding mode");
6466
}
65-
66-
mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span));
6767
});
6868
}
6969

src/librustc_mir/build/mod.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -541,13 +541,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
541541
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
542542
decl.debug_name = ident.name;
543543

544-
let bm = *hir.tables.pat_binding_modes()
545-
.get(pat.hir_id)
546-
.expect("missing binding mode");
547-
if bm == ty::BindByValue(hir::MutMutable) {
548-
decl.mutability = Mutability::Mut;
544+
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
545+
if bm == ty::BindByValue(hir::MutMutable) {
546+
decl.mutability = Mutability::Mut;
547+
} else {
548+
decl.mutability = Mutability::Not;
549+
}
549550
} else {
550-
decl.mutability = Mutability::Not;
551+
tcx.sess.delay_span_bug(pat.span, "missing binding mode");
551552
}
552553
}
553554
}

src/librustc_mir/build/scope.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
541541
/// Finds the breakable scope for a given label. This is used for
542542
/// resolving `break` and `continue`.
543543
pub fn find_breakable_scope(&self,
544-
span: Span,
545-
label: region::Scope)
546-
-> &BreakableScope<'tcx> {
544+
span: Span,
545+
label: region::Scope)
546+
-> &BreakableScope<'tcx> {
547547
// find the loop-scope with the correct id
548548
self.breakable_scopes.iter()
549549
.rev()

src/librustc_mir/hair/pattern/check_match.rs

+41-42
Original file line numberDiff line numberDiff line change
@@ -309,33 +309,32 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
309309
fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) {
310310
pat.walk(|p| {
311311
if let PatKind::Binding(_, _, ident, None) = p.node {
312-
let bm = *cx.tables
313-
.pat_binding_modes()
314-
.get(p.hir_id)
315-
.expect("missing binding mode");
316-
317-
if bm != ty::BindByValue(hir::MutImmutable) {
318-
// Nothing to check.
319-
return true;
320-
}
321-
let pat_ty = cx.tables.pat_ty(p);
322-
if let ty::TyAdt(edef, _) = pat_ty.sty {
323-
if edef.is_enum() && edef.variants.iter().any(|variant| {
324-
variant.name == ident.name && variant.ctor_kind == CtorKind::Const
325-
}) {
326-
let ty_path = cx.tcx.item_path_str(edef.did);
327-
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
328-
"pattern binding `{}` is named the same as one \
329-
of the variants of the type `{}`",
330-
ident, ty_path);
331-
err.span_suggestion_with_applicability(
332-
p.span,
333-
"to match on the variant, qualify the path",
334-
format!("{}::{}", ty_path, ident),
335-
Applicability::MachineApplicable
336-
);
337-
err.emit();
312+
if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) {
313+
if bm != ty::BindByValue(hir::MutImmutable) {
314+
// Nothing to check.
315+
return true;
338316
}
317+
let pat_ty = cx.tables.pat_ty(p);
318+
if let ty::TyAdt(edef, _) = pat_ty.sty {
319+
if edef.is_enum() && edef.variants.iter().any(|variant| {
320+
variant.name == ident.name && variant.ctor_kind == CtorKind::Const
321+
}) {
322+
let ty_path = cx.tcx.item_path_str(edef.did);
323+
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
324+
"pattern binding `{}` is named the same as one \
325+
of the variants of the type `{}`",
326+
ident, ty_path);
327+
err.span_suggestion_with_applicability(
328+
p.span,
329+
"to match on the variant, qualify the path",
330+
format!("{}::{}", ty_path, ident),
331+
Applicability::MachineApplicable
332+
);
333+
err.emit();
334+
}
335+
}
336+
} else {
337+
cx.tcx.sess.delay_span_bug(p.span, "missing binding mode");
339338
}
340339
}
341340
true
@@ -517,12 +516,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
517516
let mut by_ref_span = None;
518517
for pat in pats {
519518
pat.each_binding(|_, hir_id, span, _path| {
520-
let bm = *cx.tables
521-
.pat_binding_modes()
522-
.get(hir_id)
523-
.expect("missing binding mode");
524-
if let ty::BindByReference(..) = bm {
525-
by_ref_span = Some(span);
519+
if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) {
520+
if let ty::BindByReference(..) = bm {
521+
by_ref_span = Some(span);
522+
}
523+
} else {
524+
cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
526525
}
527526
})
528527
}
@@ -553,18 +552,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
553552
for pat in pats {
554553
pat.walk(|p| {
555554
if let PatKind::Binding(_, _, _, ref sub) = p.node {
556-
let bm = *cx.tables
557-
.pat_binding_modes()
558-
.get(p.hir_id)
559-
.expect("missing binding mode");
560-
match bm {
561-
ty::BindByValue(..) => {
562-
let pat_ty = cx.tables.node_id_to_type(p.hir_id);
563-
if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
564-
check_move(p, sub.as_ref().map(|p| &**p));
555+
if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) {
556+
match bm {
557+
ty::BindByValue(..) => {
558+
let pat_ty = cx.tables.node_id_to_type(p.hir_id);
559+
if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
560+
check_move(p, sub.as_ref().map(|p| &**p));
561+
}
565562
}
563+
_ => {}
566564
}
567-
_ => {}
565+
} else {
566+
cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode");
568567
}
569568
}
570569
true

0 commit comments

Comments
 (0)