Skip to content

Commit 9d739ca

Browse files
committed
lowering: extract lower_expr_for
1 parent c817596 commit 9d739ca

File tree

1 file changed

+163
-153
lines changed

1 file changed

+163
-153
lines changed

src/librustc/hir/lowering/expr.rs

Lines changed: 163 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -533,174 +533,184 @@ impl LoweringContext<'_> {
533533
// Desugar `ExprForLoop`
534534
// from: `[opt_ident]: for <pat> in <head> <body>`
535535
ExprKind::ForLoop(ref pat, ref head, ref body, opt_label) => {
536-
// to:
537-
//
538-
// {
539-
// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
540-
// mut iter => {
541-
// [opt_ident]: loop {
542-
// let mut __next;
543-
// match ::std::iter::Iterator::next(&mut iter) {
544-
// ::std::option::Option::Some(val) => __next = val,
545-
// ::std::option::Option::None => break
546-
// };
547-
// let <pat> = __next;
548-
// StmtKind::Expr(<body>);
549-
// }
550-
// }
551-
// };
552-
// result
553-
// }
554-
555-
// expand <head>
556-
let mut head = self.lower_expr(head);
557-
let head_sp = head.span;
558-
let desugared_span = self.mark_span_with_reason(
559-
DesugaringKind::ForLoop,
560-
head_sp,
561-
None,
562-
);
563-
head.span = desugared_span;
564-
565-
let iter = Ident::with_empty_ctxt(sym::iter);
566-
567-
let next_ident = Ident::with_empty_ctxt(sym::__next);
568-
let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
569-
desugared_span,
570-
next_ident,
571-
hir::BindingAnnotation::Mutable,
572-
);
573-
574-
// `::std::option::Option::Some(val) => __next = val`
575-
let pat_arm = {
576-
let val_ident = Ident::with_empty_ctxt(sym::val);
577-
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
578-
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
579-
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
580-
let assign = P(self.expr(
581-
pat.span,
582-
hir::ExprKind::Assign(next_expr, val_expr),
583-
ThinVec::new(),
584-
));
585-
let some_pat = self.pat_some(pat.span, val_pat);
586-
self.arm(hir_vec![some_pat], assign)
587-
};
536+
return self.lower_expr_for(e, pat, head, body, opt_label);
537+
}
538+
ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
539+
ExprKind::Mac(_) => panic!("Shouldn't exist here"),
540+
};
588541

589-
// `::std::option::Option::None => break`
590-
let break_arm = {
591-
let break_expr =
592-
self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new()));
593-
let pat = self.pat_none(e.span);
594-
self.arm(hir_vec![pat], break_expr)
595-
};
542+
hir::Expr {
543+
hir_id: self.lower_node_id(e.id),
544+
node: kind,
545+
span: e.span,
546+
attrs: e.attrs.clone(),
547+
}
548+
}
596549

597-
// `mut iter`
598-
let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode(
599-
desugared_span,
600-
iter,
601-
hir::BindingAnnotation::Mutable
602-
);
550+
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
551+
/// ```rust
552+
/// {
553+
/// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
554+
/// mut iter => {
555+
/// [opt_ident]: loop {
556+
/// let mut __next;
557+
/// match ::std::iter::Iterator::next(&mut iter) {
558+
/// ::std::option::Option::Some(val) => __next = val,
559+
/// ::std::option::Option::None => break
560+
/// };
561+
/// let <pat> = __next;
562+
/// StmtKind::Expr(<body>);
563+
/// }
564+
/// }
565+
/// };
566+
/// result
567+
/// }
568+
/// ```
569+
fn lower_expr_for(
570+
&mut self,
571+
e: &Expr,
572+
pat: &Pat,
573+
head: &Expr,
574+
body: &Block,
575+
opt_label: Option<Label>,
576+
) -> hir::Expr {
577+
// expand <head>
578+
let mut head = self.lower_expr(head);
579+
let head_sp = head.span;
580+
let desugared_span = self.mark_span_with_reason(
581+
DesugaringKind::ForLoop,
582+
head_sp,
583+
None,
584+
);
585+
head.span = desugared_span;
603586

604-
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
605-
let match_expr = {
606-
let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid));
607-
let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
608-
let next_path = &[sym::iter, sym::Iterator, sym::next];
609-
let next_expr = P(self.expr_call_std_path(
610-
head_sp,
611-
next_path,
612-
hir_vec![ref_mut_iter],
613-
));
614-
let arms = hir_vec![pat_arm, break_arm];
615-
616-
self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar)
617-
};
618-
let match_stmt = self.stmt_expr(head_sp, match_expr);
587+
let iter = Ident::with_empty_ctxt(sym::iter);
619588

620-
let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));
589+
let next_ident = Ident::with_empty_ctxt(sym::__next);
590+
let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
591+
desugared_span,
592+
next_ident,
593+
hir::BindingAnnotation::Mutable,
594+
);
621595

622-
// `let mut __next`
623-
let next_let = self.stmt_let_pat(
624-
ThinVec::new(),
625-
desugared_span,
626-
None,
627-
next_pat,
628-
hir::LocalSource::ForLoopDesugar,
629-
);
596+
// `::std::option::Option::Some(val) => __next = val`
597+
let pat_arm = {
598+
let val_ident = Ident::with_empty_ctxt(sym::val);
599+
let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident);
600+
let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid));
601+
let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid));
602+
let assign = P(self.expr(
603+
pat.span,
604+
hir::ExprKind::Assign(next_expr, val_expr),
605+
ThinVec::new(),
606+
));
607+
let some_pat = self.pat_some(pat.span, val_pat);
608+
self.arm(hir_vec![some_pat], assign)
609+
};
630610

631-
// `let <pat> = __next`
632-
let pat = self.lower_pat(pat);
633-
let pat_let = self.stmt_let_pat(
634-
ThinVec::new(),
635-
head_sp,
636-
Some(next_expr),
637-
pat,
638-
hir::LocalSource::ForLoopDesugar,
639-
);
611+
// `::std::option::Option::None => break`
612+
let break_arm = {
613+
let break_expr =
614+
self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new()));
615+
let pat = self.pat_none(e.span);
616+
self.arm(hir_vec![pat], break_expr)
617+
};
640618

641-
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
642-
let body_expr = self.expr_block(body_block, ThinVec::new());
643-
let body_stmt = self.stmt_expr(body.span, body_expr);
619+
// `mut iter`
620+
let (iter_pat, iter_pat_nid) = self.pat_ident_binding_mode(
621+
desugared_span,
622+
iter,
623+
hir::BindingAnnotation::Mutable
624+
);
644625

645-
let loop_block = P(self.block_all(
646-
e.span,
647-
hir_vec![next_let, match_stmt, pat_let, body_stmt],
648-
None,
649-
));
626+
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
627+
let match_expr = {
628+
let iter = P(self.expr_ident(head_sp, iter, iter_pat_nid));
629+
let ref_mut_iter = self.expr_mut_addr_of(head_sp, iter);
630+
let next_path = &[sym::iter, sym::Iterator, sym::next];
631+
let next_expr = P(self.expr_call_std_path(
632+
head_sp,
633+
next_path,
634+
hir_vec![ref_mut_iter],
635+
));
636+
let arms = hir_vec![pat_arm, break_arm];
650637

651-
// `[opt_ident]: loop { ... }`
652-
let loop_expr = hir::ExprKind::Loop(
653-
loop_block,
654-
self.lower_label(opt_label),
655-
hir::LoopSource::ForLoop,
656-
);
657-
let loop_expr = P(hir::Expr {
658-
hir_id: self.lower_node_id(e.id),
659-
node: loop_expr,
660-
span: e.span,
661-
attrs: ThinVec::new(),
662-
});
663-
664-
// `mut iter => { ... }`
665-
let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
666-
667-
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
668-
let into_iter_expr = {
669-
let into_iter_path =
670-
&[sym::iter, sym::IntoIterator, sym::into_iter];
671-
P(self.expr_call_std_path(
672-
head_sp,
673-
into_iter_path,
674-
hir_vec![head],
675-
))
676-
};
638+
self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar)
639+
};
640+
let match_stmt = self.stmt_expr(head_sp, match_expr);
677641

678-
let match_expr = P(self.expr_match(
679-
head_sp,
680-
into_iter_expr,
681-
hir_vec![iter_arm],
682-
hir::MatchSource::ForLoopDesugar,
683-
));
642+
let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));
684643

685-
// This is effectively `{ let _result = ...; _result }`.
686-
// The construct was introduced in #21984 and is necessary to make sure that
687-
// temporaries in the `head` expression are dropped and do not leak to the
688-
// surrounding scope of the `match` since the `match` is not a terminating scope.
689-
//
690-
// Also, add the attributes to the outer returned expr node.
691-
return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone())
692-
}
644+
// `let mut __next`
645+
let next_let = self.stmt_let_pat(
646+
ThinVec::new(),
647+
desugared_span,
648+
None,
649+
next_pat,
650+
hir::LocalSource::ForLoopDesugar,
651+
);
693652

694-
ExprKind::Try(ref sub_expr) => self.lower_expr_try(e.span, sub_expr),
695-
ExprKind::Mac(_) => panic!("Shouldn't exist here"),
696-
};
653+
// `let <pat> = __next`
654+
let pat = self.lower_pat(pat);
655+
let pat_let = self.stmt_let_pat(
656+
ThinVec::new(),
657+
head_sp,
658+
Some(next_expr),
659+
pat,
660+
hir::LocalSource::ForLoopDesugar,
661+
);
697662

698-
hir::Expr {
663+
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
664+
let body_expr = self.expr_block(body_block, ThinVec::new());
665+
let body_stmt = self.stmt_expr(body.span, body_expr);
666+
667+
let loop_block = P(self.block_all(
668+
e.span,
669+
hir_vec![next_let, match_stmt, pat_let, body_stmt],
670+
None,
671+
));
672+
673+
// `[opt_ident]: loop { ... }`
674+
let loop_expr = hir::ExprKind::Loop(
675+
loop_block,
676+
self.lower_label(opt_label),
677+
hir::LoopSource::ForLoop,
678+
);
679+
let loop_expr = P(hir::Expr {
699680
hir_id: self.lower_node_id(e.id),
700-
node: kind,
681+
node: loop_expr,
701682
span: e.span,
702-
attrs: e.attrs.clone(),
703-
}
683+
attrs: ThinVec::new(),
684+
});
685+
686+
// `mut iter => { ... }`
687+
let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
688+
689+
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
690+
let into_iter_expr = {
691+
let into_iter_path =
692+
&[sym::iter, sym::IntoIterator, sym::into_iter];
693+
P(self.expr_call_std_path(
694+
head_sp,
695+
into_iter_path,
696+
hir_vec![head],
697+
))
698+
};
699+
700+
let match_expr = P(self.expr_match(
701+
head_sp,
702+
into_iter_expr,
703+
hir_vec![iter_arm],
704+
hir::MatchSource::ForLoopDesugar,
705+
));
706+
707+
// This is effectively `{ let _result = ...; _result }`.
708+
// The construct was introduced in #21984 and is necessary to make sure that
709+
// temporaries in the `head` expression are dropped and do not leak to the
710+
// surrounding scope of the `match` since the `match` is not a terminating scope.
711+
//
712+
// Also, add the attributes to the outer returned expr node.
713+
self.expr_drop_temps(head_sp, match_expr, e.attrs.clone())
704714
}
705715

706716
/// Desugar `ExprKind::Try` from: `<expr>?` into:

0 commit comments

Comments
 (0)