mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Simplify for loop desugar
This commit is contained in:
parent
3bfde2f1f4
commit
9c83f8c4d1
@ -13,7 +13,7 @@ use rustc_session::parse::feature_err;
|
|||||||
use rustc_span::hygiene::ExpnId;
|
use rustc_span::hygiene::ExpnId;
|
||||||
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP};
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
impl<'hir> LoweringContext<'_, 'hir> {
|
impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
|
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
|
||||||
@ -1308,16 +1308,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
|
/// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// {
|
/// {
|
||||||
/// let result = match ::std::iter::IntoIterator::into_iter(<head>) {
|
/// let result = match IntoIterator::into_iter(<head>) {
|
||||||
/// mut iter => {
|
/// mut iter => {
|
||||||
/// [opt_ident]: loop {
|
/// [opt_ident]: loop {
|
||||||
/// let mut __next;
|
/// match Iterator::next(&mut iter) {
|
||||||
/// match ::std::iter::Iterator::next(&mut iter) {
|
/// None => break,
|
||||||
/// ::std::option::Option::Some(val) => __next = val,
|
/// Some(<pat>) => <body>,
|
||||||
/// ::std::option::Option::None => break
|
|
||||||
/// };
|
/// };
|
||||||
/// let <pat> = __next;
|
|
||||||
/// StmtKind::Expr(<body>);
|
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// };
|
/// };
|
||||||
@ -1332,133 +1329,75 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
body: &Block,
|
body: &Block,
|
||||||
opt_label: Option<Label>,
|
opt_label: Option<Label>,
|
||||||
) -> hir::Expr<'hir> {
|
) -> hir::Expr<'hir> {
|
||||||
// expand <head>
|
|
||||||
let head = self.lower_expr_mut(head);
|
let head = self.lower_expr_mut(head);
|
||||||
let desugared_span =
|
let pat = self.lower_pat(pat);
|
||||||
self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), head.span, None);
|
let for_span =
|
||||||
let e_span = self.lower_span(e.span);
|
self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None);
|
||||||
|
let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
|
||||||
|
let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None);
|
||||||
|
|
||||||
let iter = Ident::with_dummy_span(sym::iter);
|
// `None => break`
|
||||||
|
let none_arm = {
|
||||||
let next_ident = Ident::with_dummy_span(sym::__next);
|
|
||||||
let (next_pat, next_pat_hid) = self.pat_ident_binding_mode(
|
|
||||||
desugared_span,
|
|
||||||
next_ident,
|
|
||||||
hir::BindingAnnotation::Mutable,
|
|
||||||
);
|
|
||||||
|
|
||||||
// `::std::option::Option::Some(val) => __next = val`
|
|
||||||
let pat_arm = {
|
|
||||||
let val_ident = Ident::with_dummy_span(sym::val);
|
|
||||||
let pat_span = self.lower_span(pat.span);
|
|
||||||
let (val_pat, val_pat_hid) = self.pat_ident(pat_span, val_ident);
|
|
||||||
let val_expr = self.expr_ident(pat_span, val_ident, val_pat_hid);
|
|
||||||
let next_expr = self.expr_ident(pat_span, next_ident, next_pat_hid);
|
|
||||||
let assign = self.arena.alloc(self.expr(
|
|
||||||
pat_span,
|
|
||||||
hir::ExprKind::Assign(next_expr, val_expr, self.lower_span(pat_span)),
|
|
||||||
ThinVec::new(),
|
|
||||||
));
|
|
||||||
let some_pat = self.pat_some(pat_span, val_pat);
|
|
||||||
self.arm(some_pat, assign)
|
|
||||||
};
|
|
||||||
|
|
||||||
// `::std::option::Option::None => break`
|
|
||||||
let break_arm = {
|
|
||||||
let break_expr =
|
let break_expr =
|
||||||
self.with_loop_scope(e.id, |this| this.expr_break_alloc(e_span, ThinVec::new()));
|
self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new()));
|
||||||
let pat = self.pat_none(e_span);
|
let pat = self.pat_none(for_span);
|
||||||
self.arm(pat, break_expr)
|
self.arm(pat, break_expr)
|
||||||
};
|
};
|
||||||
|
|
||||||
// `mut iter`
|
// Some(<pat>) => <body>,
|
||||||
let (iter_pat, iter_pat_nid) =
|
let some_arm = {
|
||||||
self.pat_ident_binding_mode(desugared_span, iter, hir::BindingAnnotation::Mutable);
|
let some_pat = self.pat_some(pat_span, pat);
|
||||||
|
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
|
||||||
|
let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new()));
|
||||||
|
self.arm(some_pat, body_expr)
|
||||||
|
};
|
||||||
|
|
||||||
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
|
// `mut iter`
|
||||||
|
let iter = Ident::with_dummy_span(sym::iter);
|
||||||
|
let (iter_pat, iter_pat_nid) =
|
||||||
|
self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::Mutable);
|
||||||
|
|
||||||
|
// `match Iterator::next(&mut iter) { ... }`
|
||||||
let match_expr = {
|
let match_expr = {
|
||||||
let iter = self.expr_ident(desugared_span, iter, iter_pat_nid);
|
let iter = self.expr_ident(head_span, iter, iter_pat_nid);
|
||||||
let ref_mut_iter = self.expr_mut_addr_of(desugared_span, iter);
|
let ref_mut_iter = self.expr_mut_addr_of(head_span, iter);
|
||||||
let next_expr = self.expr_call_lang_item_fn(
|
let next_expr = self.expr_call_lang_item_fn(
|
||||||
desugared_span,
|
head_span,
|
||||||
hir::LangItem::IteratorNext,
|
hir::LangItem::IteratorNext,
|
||||||
arena_vec![self; ref_mut_iter],
|
arena_vec![self; ref_mut_iter],
|
||||||
);
|
);
|
||||||
let arms = arena_vec![self; pat_arm, break_arm];
|
let arms = arena_vec![self; none_arm, some_arm];
|
||||||
|
|
||||||
self.expr_match(desugared_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar)
|
||||||
};
|
};
|
||||||
let match_stmt = self.stmt_expr(desugared_span, match_expr);
|
let match_stmt = self.stmt_expr(for_span, match_expr);
|
||||||
|
|
||||||
let next_expr = self.expr_ident(desugared_span, next_ident, next_pat_hid);
|
let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None);
|
||||||
|
|
||||||
// `let mut __next`
|
|
||||||
let next_let = self.stmt_let_pat(
|
|
||||||
None,
|
|
||||||
desugared_span,
|
|
||||||
None,
|
|
||||||
next_pat,
|
|
||||||
hir::LocalSource::ForLoopDesugar,
|
|
||||||
);
|
|
||||||
|
|
||||||
// `let <pat> = __next`
|
|
||||||
let pat = self.lower_pat(pat);
|
|
||||||
let pat_let = self.stmt_let_pat(
|
|
||||||
None,
|
|
||||||
desugared_span,
|
|
||||||
Some(next_expr),
|
|
||||||
pat,
|
|
||||||
hir::LocalSource::ForLoopDesugar,
|
|
||||||
);
|
|
||||||
|
|
||||||
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
|
|
||||||
let body_expr = self.expr_block(body_block, ThinVec::new());
|
|
||||||
let body_stmt = self.stmt_expr(body_block.span, body_expr);
|
|
||||||
|
|
||||||
let loop_block = self.block_all(
|
|
||||||
e_span,
|
|
||||||
arena_vec![self; next_let, match_stmt, pat_let, body_stmt],
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
// `[opt_ident]: loop { ... }`
|
// `[opt_ident]: loop { ... }`
|
||||||
let kind = hir::ExprKind::Loop(
|
let kind = hir::ExprKind::Loop(
|
||||||
loop_block,
|
loop_block,
|
||||||
self.lower_label(opt_label),
|
self.lower_label(opt_label),
|
||||||
hir::LoopSource::ForLoop,
|
hir::LoopSource::ForLoop,
|
||||||
self.lower_span(e_span.with_hi(head.span.hi())),
|
self.lower_span(for_span.with_hi(head.span.hi())),
|
||||||
);
|
);
|
||||||
let loop_expr = self.arena.alloc(hir::Expr {
|
let loop_expr =
|
||||||
hir_id: self.lower_node_id(e.id),
|
self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span });
|
||||||
kind,
|
|
||||||
span: self.lower_span(e.span),
|
|
||||||
});
|
|
||||||
|
|
||||||
// `mut iter => { ... }`
|
// `mut iter => { ... }`
|
||||||
let iter_arm = self.arm(iter_pat, loop_expr);
|
let iter_arm = self.arm(iter_pat, loop_expr);
|
||||||
|
|
||||||
let into_iter_span = self.mark_span_with_reason(
|
|
||||||
DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
|
|
||||||
head.span,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
|
||||||
let into_iter_expr = {
|
let into_iter_expr = {
|
||||||
self.expr_call_lang_item_fn(
|
self.expr_call_lang_item_fn(
|
||||||
into_iter_span,
|
head_span,
|
||||||
hir::LangItem::IntoIterIntoIter,
|
hir::LangItem::IntoIterIntoIter,
|
||||||
arena_vec![self; head],
|
arena_vec![self; head],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
// #82462: to correctly diagnose borrow errors, the block that contains
|
|
||||||
// the iter expr needs to have a span that covers the loop body.
|
|
||||||
let desugared_full_span =
|
|
||||||
self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e_span, None);
|
|
||||||
|
|
||||||
let match_expr = self.arena.alloc(self.expr_match(
|
let match_expr = self.arena.alloc(self.expr_match(
|
||||||
desugared_full_span,
|
for_span,
|
||||||
into_iter_expr,
|
into_iter_expr,
|
||||||
arena_vec![self; iter_arm],
|
arena_vec![self; iter_arm],
|
||||||
hir::MatchSource::ForLoopDesugar,
|
hir::MatchSource::ForLoopDesugar,
|
||||||
@ -1472,7 +1411,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// surrounding scope of the `match` since the `match` is not a terminating scope.
|
// surrounding scope of the `match` since the `match` is not a terminating scope.
|
||||||
//
|
//
|
||||||
// Also, add the attributes to the outer returned expr node.
|
// Also, add the attributes to the outer returned expr node.
|
||||||
self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
|
self.expr_drop_temps_mut(for_span, match_expr, attrs.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Desugar `ExprKind::Try` from: `<expr>?` into:
|
/// Desugar `ExprKind::Try` from: `<expr>?` into:
|
||||||
|
@ -13,7 +13,7 @@ use rustc_middle::mir::{
|
|||||||
use rustc_middle::ty::adjustment::PointerCast;
|
use rustc_middle::ty::adjustment::PointerCast;
|
||||||
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_span::Span;
|
use rustc_span::{sym, DesugaringKind, Span};
|
||||||
|
|
||||||
use crate::region_infer::BlameConstraint;
|
use crate::region_infer::BlameConstraint;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -135,7 +135,16 @@ impl BorrowExplanation {
|
|||||||
should_note_order,
|
should_note_order,
|
||||||
} => {
|
} => {
|
||||||
let local_decl = &body.local_decls[dropped_local];
|
let local_decl = &body.local_decls[dropped_local];
|
||||||
let (dtor_desc, type_desc) = match local_decl.ty.kind() {
|
let mut ty = local_decl.ty;
|
||||||
|
if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
|
||||||
|
if let ty::Adt(adt, substs) = local_decl.ty.kind() {
|
||||||
|
if tcx.is_diagnostic_item(sym::Option, adt.did) {
|
||||||
|
// in for loop desugaring, only look at the `Some(..)` inner type
|
||||||
|
ty = substs.type_at(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (dtor_desc, type_desc) = match ty.kind() {
|
||||||
// If type is an ADT that implements Drop, then
|
// If type is an ADT that implements Drop, then
|
||||||
// simplify output by reporting just the ADT name.
|
// simplify output by reporting just the ADT name.
|
||||||
ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => {
|
ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => {
|
||||||
|
@ -13,11 +13,7 @@ use rustc_middle::mir::{
|
|||||||
use rustc_middle::ty::print::Print;
|
use rustc_middle::ty::print::Print;
|
||||||
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
|
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
|
||||||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||||
use rustc_span::{
|
use rustc_span::{hygiene::DesugaringKind, symbol::sym, Span};
|
||||||
hygiene::{DesugaringKind, ForLoopLoc},
|
|
||||||
symbol::sym,
|
|
||||||
Span,
|
|
||||||
};
|
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
|
|
||||||
use super::borrow_set::BorrowData;
|
use super::borrow_set::BorrowData;
|
||||||
@ -955,10 +951,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let kind = kind.unwrap_or_else(|| {
|
let kind = kind.unwrap_or_else(|| {
|
||||||
// This isn't a 'special' use of `self`
|
// This isn't a 'special' use of `self`
|
||||||
debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
|
debug!("move_spans: method_did={:?}, fn_call_span={:?}", method_did, fn_call_span);
|
||||||
let implicit_into_iter = matches!(
|
let implicit_into_iter = Some(method_did) == tcx.lang_items().into_iter_fn()
|
||||||
fn_call_span.desugaring_kind(),
|
&& fn_call_span.desugaring_kind() == Some(DesugaringKind::ForLoop);
|
||||||
Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
|
|
||||||
);
|
|
||||||
let parent_self_ty = parent
|
let parent_self_ty = parent
|
||||||
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
|
.filter(|did| tcx.def_kind(*did) == rustc_hir::def::DefKind::Impl)
|
||||||
.and_then(|did| match tcx.type_of(did).kind() {
|
.and_then(|did| match tcx.type_of(did).kind() {
|
||||||
|
@ -445,15 +445,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
))) => {
|
))) => {
|
||||||
// check if the RHS is from desugaring
|
// check if the RHS is from desugaring
|
||||||
let locations = self.body.find_assignments(local);
|
let opt_assignment_rhs_span =
|
||||||
let opt_assignment_rhs_span = locations
|
self.body.find_assignments(local).first().map(|&location| {
|
||||||
.first()
|
let stmt = &self.body[location.block].statements
|
||||||
.map(|&location| self.body.source_info(location).span);
|
[location.statement_index];
|
||||||
let opt_desugaring_kind =
|
match stmt.kind {
|
||||||
opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
|
mir::StatementKind::Assign(box (
|
||||||
match opt_desugaring_kind {
|
_,
|
||||||
|
mir::Rvalue::Use(mir::Operand::Copy(place)),
|
||||||
|
)) => {
|
||||||
|
self.body.local_decls[place.local].source_info.span
|
||||||
|
}
|
||||||
|
_ => self.body.source_info(location).span,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
match opt_assignment_rhs_span.and_then(|s| s.desugaring_kind()) {
|
||||||
// on for loops, RHS points to the iterator part
|
// on for loops, RHS points to the iterator part
|
||||||
Some(DesugaringKind::ForLoop(_)) => {
|
Some(DesugaringKind::ForLoop) => {
|
||||||
self.suggest_similar_mut_method_for_for_loop(&mut err);
|
self.suggest_similar_mut_method_for_for_loop(&mut err);
|
||||||
Some((
|
Some((
|
||||||
false,
|
false,
|
||||||
|
@ -1821,8 +1821,6 @@ impl<'hir> QPath<'hir> {
|
|||||||
pub enum LocalSource {
|
pub enum LocalSource {
|
||||||
/// A `match _ { .. }`.
|
/// A `match _ { .. }`.
|
||||||
Normal,
|
Normal,
|
||||||
/// A desugared `for _ in _ { .. }` loop.
|
|
||||||
ForLoopDesugar,
|
|
||||||
/// When lowering async functions, we create locals within the `async move` so that
|
/// When lowering async functions, we create locals within the `async move` so that
|
||||||
/// all parameters are dropped after the future is polled.
|
/// all parameters are dropped after the future is polled.
|
||||||
///
|
///
|
||||||
|
@ -2,6 +2,7 @@ use crate::def::{CtorOf, DefKind, Res};
|
|||||||
use crate::def_id::DefId;
|
use crate::def_id::DefId;
|
||||||
use crate::hir::{self, HirId, PatKind};
|
use crate::hir::{self, HirId, PatKind};
|
||||||
use rustc_data_structures::stable_set::FxHashSet;
|
use rustc_data_structures::stable_set::FxHashSet;
|
||||||
|
use rustc_span::hygiene::DesugaringKind;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
@ -143,4 +144,14 @@ impl hir::Pat<'_> {
|
|||||||
});
|
});
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the pattern is `Some(<pat>)` from a desugared for loop, returns the inner pattern
|
||||||
|
pub fn for_loop_some(&self) -> Option<&Self> {
|
||||||
|
if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
|
||||||
|
if let hir::PatKind::Struct(_, [pat_field], _) = self.kind {
|
||||||
|
return Some(pat_field.pat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,12 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def::{DefKind, Namespace};
|
use rustc_hir::def::{DefKind, Namespace};
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
|
||||||
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
|
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat};
|
||||||
use rustc_middle::hir::map::Map;
|
use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
|
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
|
||||||
use rustc_middle::ty::print::Print;
|
use rustc_middle::ty::print::Print;
|
||||||
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
|
||||||
use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt};
|
use rustc_middle::ty::{self, DefIdTree, InferConst, Ty, TyCtxt};
|
||||||
use rustc_span::source_map::DesugaringKind;
|
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
@ -26,6 +25,7 @@ struct FindHirNodeVisitor<'a, 'tcx> {
|
|||||||
found_closure: Option<&'tcx Expr<'tcx>>,
|
found_closure: Option<&'tcx Expr<'tcx>>,
|
||||||
found_method_call: Option<&'tcx Expr<'tcx>>,
|
found_method_call: Option<&'tcx Expr<'tcx>>,
|
||||||
found_exact_method_call: Option<&'tcx Expr<'tcx>>,
|
found_exact_method_call: Option<&'tcx Expr<'tcx>>,
|
||||||
|
found_for_loop_iter: Option<&'tcx Expr<'tcx>>,
|
||||||
found_use_diagnostic: Option<UseDiagnostic<'tcx>>,
|
found_use_diagnostic: Option<UseDiagnostic<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +41,7 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
|
|||||||
found_closure: None,
|
found_closure: None,
|
||||||
found_method_call: None,
|
found_method_call: None,
|
||||||
found_exact_method_call: None,
|
found_exact_method_call: None,
|
||||||
|
found_for_loop_iter: None,
|
||||||
found_use_diagnostic: None,
|
found_use_diagnostic: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +112,15 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
||||||
|
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind {
|
||||||
|
if let Some(pat) = arm.pat.for_loop_some() {
|
||||||
|
if let Some(ty) = self.node_ty_contains_target(pat.hir_id) {
|
||||||
|
self.found_for_loop_iter = Some(scrutinee);
|
||||||
|
self.found_node_ty = Some(ty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
|
if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
|
||||||
if call_span == self.target_span
|
if call_span == self.target_span
|
||||||
&& Some(self.target)
|
&& Some(self.target)
|
||||||
@ -643,10 +653,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
let msg = if let Some(simple_ident) = pattern.simple_ident() {
|
let msg = if let Some(simple_ident) = pattern.simple_ident() {
|
||||||
match pattern.span.desugaring_kind() {
|
match pattern.span.desugaring_kind() {
|
||||||
None => format!("consider giving `{}` {}", simple_ident, suffix),
|
None => format!("consider giving `{}` {}", simple_ident, suffix),
|
||||||
Some(DesugaringKind::ForLoop(_)) => {
|
Some(_) => format!("this needs {}", suffix),
|
||||||
"the element type for this iterator is not specified".to_string()
|
|
||||||
}
|
|
||||||
_ => format!("this needs {}", suffix),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("consider giving this pattern {}", suffix)
|
format!("consider giving this pattern {}", suffix)
|
||||||
@ -719,6 +726,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||||||
// = note: type must be known at this point
|
// = note: type must be known at this point
|
||||||
self.annotate_method_call(segment, e, &mut err);
|
self.annotate_method_call(segment, e, &mut err);
|
||||||
}
|
}
|
||||||
|
} else if let Some(scrutinee) = local_visitor.found_for_loop_iter {
|
||||||
|
err.span_label(
|
||||||
|
scrutinee.span,
|
||||||
|
"the element type for this iterator is not specified".to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Instead of the following:
|
// Instead of the following:
|
||||||
// error[E0282]: type annotations needed
|
// error[E0282]: type annotations needed
|
||||||
|
@ -395,7 +395,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
|
|||||||
match expn_data.kind {
|
match expn_data.kind {
|
||||||
ExpnKind::Inlined
|
ExpnKind::Inlined
|
||||||
| ExpnKind::Root
|
| ExpnKind::Root
|
||||||
| ExpnKind::Desugaring(DesugaringKind::ForLoop(_) | DesugaringKind::WhileLoop) => false,
|
| ExpnKind::Desugaring(DesugaringKind::ForLoop | DesugaringKind::WhileLoop) => false,
|
||||||
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
|
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
|
||||||
ExpnKind::Macro(MacroKind::Bang, _) => {
|
ExpnKind::Macro(MacroKind::Bang, _) => {
|
||||||
// Dummy span for the `def_site` means it's an external macro.
|
// Dummy span for the `def_site` means it's an external macro.
|
||||||
|
@ -74,19 +74,16 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
|
|||||||
|
|
||||||
let (msg, sp) = match loc.source {
|
let (msg, sp) = match loc.source {
|
||||||
hir::LocalSource::Normal => ("local binding", Some(loc.span)),
|
hir::LocalSource::Normal => ("local binding", Some(loc.span)),
|
||||||
hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None),
|
|
||||||
hir::LocalSource::AsyncFn => ("async fn binding", None),
|
hir::LocalSource::AsyncFn => ("async fn binding", None),
|
||||||
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
|
hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
|
||||||
hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None),
|
hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None),
|
||||||
};
|
};
|
||||||
self.check_irrefutable(&loc.pat, msg, sp);
|
self.check_irrefutable(&loc.pat, msg, sp);
|
||||||
self.check_patterns(&loc.pat, Irrefutable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
|
||||||
intravisit::walk_param(self, param);
|
intravisit::walk_param(self, param);
|
||||||
self.check_irrefutable(¶m.pat, "function argument", None);
|
self.check_irrefutable(¶m.pat, "function argument", None);
|
||||||
self.check_patterns(¶m.pat, Irrefutable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,12 +158,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
fn check_match(
|
fn check_match(
|
||||||
&mut self,
|
&mut self,
|
||||||
scrut: &hir::Expr<'_>,
|
scrut: &hir::Expr<'_>,
|
||||||
arms: &'tcx [hir::Arm<'tcx>],
|
hir_arms: &'tcx [hir::Arm<'tcx>],
|
||||||
source: hir::MatchSource,
|
source: hir::MatchSource,
|
||||||
) {
|
) {
|
||||||
let mut cx = self.new_cx(scrut.hir_id);
|
let mut cx = self.new_cx(scrut.hir_id);
|
||||||
|
|
||||||
for arm in arms {
|
for arm in hir_arms {
|
||||||
// Check the arm for some things unrelated to exhaustiveness.
|
// Check the arm for some things unrelated to exhaustiveness.
|
||||||
self.check_patterns(&arm.pat, Refutable);
|
self.check_patterns(&arm.pat, Refutable);
|
||||||
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
if let Some(hir::Guard::IfLet(ref pat, _)) = arm.guard {
|
||||||
@ -178,7 +175,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
|
|
||||||
let mut have_errors = false;
|
let mut have_errors = false;
|
||||||
|
|
||||||
let arms: Vec<_> = arms
|
let arms: Vec<_> = hir_arms
|
||||||
.iter()
|
.iter()
|
||||||
.map(|hir::Arm { pat, guard, .. }| MatchArm {
|
.map(|hir::Arm { pat, guard, .. }| MatchArm {
|
||||||
pat: self.lower_pattern(&mut cx, pat, &mut have_errors),
|
pat: self.lower_pattern(&mut cx, pat, &mut have_errors),
|
||||||
@ -196,6 +193,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty);
|
let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty);
|
||||||
|
|
||||||
match source {
|
match source {
|
||||||
|
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
|
||||||
|
// when the iterator is an uninhabited type. unreachable_code will trigger instead.
|
||||||
|
hir::MatchSource::ForLoopDesugar if arms.len() == 1 => {}
|
||||||
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
|
hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => {
|
||||||
report_arm_reachability(&cx, &report)
|
report_arm_reachability(&cx, &report)
|
||||||
}
|
}
|
||||||
@ -208,7 +208,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
let is_empty_match = arms.is_empty();
|
let is_empty_match = arms.is_empty();
|
||||||
let witnesses = report.non_exhaustiveness_witnesses;
|
let witnesses = report.non_exhaustiveness_witnesses;
|
||||||
if !witnesses.is_empty() {
|
if !witnesses.is_empty() {
|
||||||
non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match);
|
if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 {
|
||||||
|
// the for loop pattern is not irrefutable
|
||||||
|
let pat = hir_arms[1].pat.for_loop_some().unwrap();
|
||||||
|
self.check_irrefutable(pat, "`for` loop binding", None);
|
||||||
|
} else {
|
||||||
|
non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, is_empty_match);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,6 +231,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
|
|||||||
let witnesses = report.non_exhaustiveness_witnesses;
|
let witnesses = report.non_exhaustiveness_witnesses;
|
||||||
if witnesses.is_empty() {
|
if witnesses.is_empty() {
|
||||||
// The pattern is irrefutable.
|
// The pattern is irrefutable.
|
||||||
|
self.check_patterns(pat, Irrefutable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,18 +1099,11 @@ pub enum DesugaringKind {
|
|||||||
OpaqueTy,
|
OpaqueTy,
|
||||||
Async,
|
Async,
|
||||||
Await,
|
Await,
|
||||||
ForLoop(ForLoopLoc),
|
ForLoop,
|
||||||
LetElse,
|
LetElse,
|
||||||
WhileLoop,
|
WhileLoop,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A location in the desugaring of a `for` loop
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
|
|
||||||
pub enum ForLoopLoc {
|
|
||||||
Head,
|
|
||||||
IntoIter,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DesugaringKind {
|
impl DesugaringKind {
|
||||||
/// The description wording should combine well with "desugaring of {}".
|
/// The description wording should combine well with "desugaring of {}".
|
||||||
pub fn descr(self) -> &'static str {
|
pub fn descr(self) -> &'static str {
|
||||||
@ -1121,7 +1114,7 @@ impl DesugaringKind {
|
|||||||
DesugaringKind::QuestionMark => "operator `?`",
|
DesugaringKind::QuestionMark => "operator `?`",
|
||||||
DesugaringKind::TryBlock => "`try` block",
|
DesugaringKind::TryBlock => "`try` block",
|
||||||
DesugaringKind::OpaqueTy => "`impl Trait`",
|
DesugaringKind::OpaqueTy => "`impl Trait`",
|
||||||
DesugaringKind::ForLoop(_) => "`for` loop",
|
DesugaringKind::ForLoop => "`for` loop",
|
||||||
DesugaringKind::LetElse => "`let...else`",
|
DesugaringKind::LetElse => "`let...else`",
|
||||||
DesugaringKind::WhileLoop => "`while` loop",
|
DesugaringKind::WhileLoop => "`while` loop",
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ pub mod edition;
|
|||||||
use edition::Edition;
|
use edition::Edition;
|
||||||
pub mod hygiene;
|
pub mod hygiene;
|
||||||
use hygiene::Transparency;
|
use hygiene::Transparency;
|
||||||
pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
|
pub use hygiene::{DesugaringKind, ExpnKind, MacroKind};
|
||||||
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
|
pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
|
||||||
pub mod def_id;
|
pub mod def_id;
|
||||||
use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
|
use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
|
||||||
|
@ -269,7 +269,6 @@ symbols! {
|
|||||||
__D,
|
__D,
|
||||||
__H,
|
__H,
|
||||||
__S,
|
__S,
|
||||||
__next,
|
|
||||||
__try_var,
|
__try_var,
|
||||||
_args,
|
_args,
|
||||||
_d,
|
_d,
|
||||||
|
@ -27,7 +27,7 @@ use rustc_middle::ty::{TypeAndMut, TypeckResults};
|
|||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP};
|
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MultiSpan, Span, DUMMY_SP};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@ -685,7 +685,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
&obligation.cause.code
|
&obligation.cause.code
|
||||||
{
|
{
|
||||||
parent_code.clone()
|
parent_code.clone()
|
||||||
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) =
|
} else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
|
||||||
span.ctxt().outer_expn_data().kind
|
span.ctxt().outer_expn_data().kind
|
||||||
{
|
{
|
||||||
Lrc::new(obligation.cause.code.clone())
|
Lrc::new(obligation.cause.code.clone())
|
||||||
@ -765,8 +765,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
// This if is to prevent a special edge-case
|
// This if is to prevent a special edge-case
|
||||||
if matches!(
|
if matches!(
|
||||||
span.ctxt().outer_expn_data().kind,
|
span.ctxt().outer_expn_data().kind,
|
||||||
ExpnKind::Root
|
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
|
||||||
| ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
|
|
||||||
) {
|
) {
|
||||||
// We don't want a borrowing suggestion on the fields in structs,
|
// We don't want a borrowing suggestion on the fields in structs,
|
||||||
// ```
|
// ```
|
||||||
|
@ -549,13 +549,10 @@ mod fn_keyword {}
|
|||||||
/// {
|
/// {
|
||||||
/// let result = match IntoIterator::into_iter(iterator) {
|
/// let result = match IntoIterator::into_iter(iterator) {
|
||||||
/// mut iter => loop {
|
/// mut iter => loop {
|
||||||
/// let next;
|
|
||||||
/// match iter.next() {
|
/// match iter.next() {
|
||||||
/// Some(val) => next = val,
|
|
||||||
/// None => break,
|
/// None => break,
|
||||||
|
/// Some(loop_variable) => { code(); },
|
||||||
/// };
|
/// };
|
||||||
/// let loop_variable = next;
|
|
||||||
/// let () = { code(); };
|
|
||||||
/// },
|
/// },
|
||||||
/// };
|
/// };
|
||||||
/// result
|
/// result
|
||||||
|
@ -183,7 +183,7 @@ pub fn add_loop_label_to_break() {
|
|||||||
#[cfg(not(any(cfail1,cfail4)))]
|
#[cfg(not(any(cfail1,cfail4)))]
|
||||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
||||||
#[rustc_clean(cfg="cfail3")]
|
#[rustc_clean(cfg="cfail3")]
|
||||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
|
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
|
||||||
#[rustc_clean(cfg="cfail6")]
|
#[rustc_clean(cfg="cfail6")]
|
||||||
pub fn add_loop_label_to_break() {
|
pub fn add_loop_label_to_break() {
|
||||||
let mut _x = 0;
|
let mut _x = 0;
|
||||||
|
@ -7,39 +7,29 @@
|
|||||||
let mut _2: std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _2: std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _3: std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _3: std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _5: (); // in scope 0 at $DIR/remove_storage_markers.rs:6:1: 11:2
|
let mut _5: (); // in scope 0 at $DIR/remove_storage_markers.rs:6:1: 11:2
|
||||||
let _7: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let _6: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _8: std::option::Option<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _7: std::option::Option<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
|
let mut _8: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _9: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _9: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _10: &mut std::ops::Range<i32>; // in scope 0 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _10: isize; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
||||||
let mut _11: isize; // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
let mut _11: !; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
||||||
let mut _13: i32; // in scope 0 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
let mut _13: i32; // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
||||||
let mut _14: !; // in scope 0 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
|
||||||
let _16: (); // in scope 0 at $DIR/remove_storage_markers.rs:8:20: 10:6
|
|
||||||
let mut _17: i32; // in scope 0 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
|
||||||
scope 1 {
|
scope 1 {
|
||||||
debug sum => _1; // in scope 1 at $DIR/remove_storage_markers.rs:7:9: 7:16
|
debug sum => _1; // in scope 1 at $DIR/remove_storage_markers.rs:7:9: 7:16
|
||||||
let mut _4: std::ops::Range<i32>; // in scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let mut _4: std::ops::Range<i32>; // in scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
scope 2 {
|
scope 2 {
|
||||||
debug iter => _4; // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
debug iter => _4; // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
let mut _6: i32; // in scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
let _12: i32; // in scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
||||||
scope 3 {
|
scope 3 {
|
||||||
debug __next => _6; // in scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
debug i => _12; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
||||||
let _12: i32; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
}
|
||||||
let _15: i32; // in scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<i32>>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
scope 4 {
|
debug self => _8; // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
debug val => _12; // in scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
let mut _14: &mut std::ops::Range<i32>; // in scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
}
|
|
||||||
scope 5 {
|
|
||||||
debug i => _15; // in scope 5 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
}
|
|
||||||
scope 7 (inlined iter::range::<impl Iterator for std::ops::Range<i32>>::next) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
|
|
||||||
debug self => _9; // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
|
||||||
let mut _18: &mut std::ops::Range<i32>; // in scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scope 6 (inlined <std::ops::Range<i32> as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
|
scope 4 (inlined <std::ops::Range<i32> as IntoIterator>::into_iter) { // at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
debug self => _3; // in scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
debug self => _3; // in scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +40,7 @@
|
|||||||
- StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
(_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
(_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
(_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
(_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_2 = move _3; // scope 6 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_2 = move _3; // scope 4 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageDead(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
- StorageDead(_3); // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
||||||
- StorageLive(_4); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_4); // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_4 = move _2; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_4 = move _2; // scope 1 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
@ -59,25 +49,39 @@
|
|||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
- StorageLive(_6); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_6); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageLive(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_7); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageLive(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_8); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageLive(_9); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_9); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageLive(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_9 = &mut _4; // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_10 = &mut _4; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_8 = &mut (*_9); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_9 = &mut (*_10); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageLive(_14); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageLive(_18); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_14 = &mut (*_8); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_18 = &mut (*_9); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_7 = <std::ops::Range<i32> as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
_8 = <std::ops::Range<i32> as iter::range::RangeIteratorImpl>::spec_next(move _18) -> bb4; // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/remove_storage_markers.rs:8:14: 8:19
|
// + span: $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
// + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range<i32>) -> std::option::Option<<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::Item> {<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar(<ZST>)) }
|
// + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range<i32>) -> std::option::Option<<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::Item> {<std::ops::Range<i32> as std::iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar(<ZST>)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
_0 = const (); // scope 3 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
- StorageLive(_12); // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
||||||
- StorageDead(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
_12 = ((_7 as Some).0: i32); // scope 2 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
||||||
- StorageDead(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
- StorageLive(_13); // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
||||||
- StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
_13 = _12; // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
||||||
|
_1 = Add(_1, move _13); // scope 3 at $DIR/remove_storage_markers.rs:9:9: 9:17
|
||||||
|
- StorageDead(_13); // scope 3 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
||||||
|
_6 = const (); // scope 3 at $DIR/remove_storage_markers.rs:8:20: 10:6
|
||||||
|
- StorageDead(_12); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
|
- StorageDead(_9); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
|
- StorageDead(_7); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
|
- StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
|
_5 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
||||||
|
goto -> bb1; // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
_0 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
||||||
|
- StorageDead(_9); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
|
- StorageDead(_7); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
- StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
- StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
- StorageDead(_4); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
- StorageDead(_4); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
- StorageDead(_2); // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
||||||
@ -85,38 +89,11 @@
|
|||||||
return; // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
|
return; // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
|
||||||
}
|
}
|
||||||
|
|
||||||
bb3: {
|
|
||||||
- StorageLive(_12); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
_12 = ((_8 as Some).0: i32); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
- StorageLive(_13); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
_13 = _12; // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
_6 = move _13; // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
_7 = const (); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
- StorageDead(_13); // scope 4 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
- StorageDead(_12); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
- StorageDead(_10); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
|
||||||
- StorageDead(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
|
||||||
- StorageDead(_7); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
|
||||||
- StorageLive(_15); // scope 3 at $DIR/remove_storage_markers.rs:8:9: 8:10
|
|
||||||
_15 = _6; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
|
||||||
- StorageLive(_16); // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6
|
|
||||||
- StorageLive(_17); // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
|
||||||
_17 = _15; // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
|
||||||
_1 = Add(_1, move _17); // scope 5 at $DIR/remove_storage_markers.rs:9:9: 9:17
|
|
||||||
- StorageDead(_17); // scope 5 at $DIR/remove_storage_markers.rs:9:16: 9:17
|
|
||||||
_16 = const (); // scope 5 at $DIR/remove_storage_markers.rs:8:20: 10:6
|
|
||||||
- StorageDead(_16); // scope 5 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
|
||||||
_5 = const (); // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
|
||||||
- StorageDead(_15); // scope 3 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
|
||||||
- StorageDead(_6); // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
|
|
||||||
goto -> bb1; // scope 2 at $DIR/remove_storage_markers.rs:8:5: 10:6
|
|
||||||
}
|
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
- StorageDead(_18); // scope 7 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
- StorageDead(_14); // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
- StorageDead(_9); // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
- StorageDead(_8); // scope 2 at $DIR/remove_storage_markers.rs:8:18: 8:19
|
||||||
_11 = discriminant(_8); // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
_10 = discriminant(_7); // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
switchInt(move _11) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
switchInt(move _10) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/remove_storage_markers.rs:8:14: 8:19
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ where
|
|||||||
let key = f(x);
|
let key = f(x);
|
||||||
result.entry(key).or_insert(Vec::new()).push(x);
|
result.entry(key).or_insert(Vec::new()).push(x);
|
||||||
}
|
}
|
||||||
result //~ ERROR cannot return value referencing local binding
|
result //~ ERROR cannot return value referencing temporary value
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0515]: cannot return value referencing local binding
|
error[E0515]: cannot return value referencing temporary value
|
||||||
--> $DIR/return-local-binding-from-desugaring.rs:30:5
|
--> $DIR/return-local-binding-from-desugaring.rs:30:5
|
||||||
|
|
|
|
||||||
LL | for ref x in xs {
|
LL | for ref x in xs {
|
||||||
| -- local binding introduced here
|
| -- temporary value created here
|
||||||
...
|
...
|
||||||
LL | result
|
LL | result
|
||||||
| ^^^^^^ returns a value referencing data owned by the current function
|
| ^^^^^^ returns a value referencing data owned by the current function
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
error[E0282]: type annotations needed
|
error[E0282]: type annotations needed
|
||||||
--> $DIR/for-loop-unconstrained-element-type.rs:8:14
|
--> $DIR/for-loop-unconstrained-element-type.rs:8:9
|
||||||
|
|
|
|
||||||
LL | for i in Vec::new() { }
|
LL | for i in Vec::new() { }
|
||||||
| ^^^^^^^^^^ the element type for this iterator is not specified
|
| ^ ---------- the element type for this iterator is not specified
|
||||||
|
| |
|
||||||
|
| cannot infer type
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error[E0282]: type annotations needed for `&(_,)`
|
error[E0282]: type annotations needed for `(_,)`
|
||||||
--> $DIR/issue-20261.rs:4:11
|
--> $DIR/issue-20261.rs:4:11
|
||||||
|
|
|
|
||||||
LL | for (ref i,) in [].iter() {
|
LL | for (ref i,) in [].iter() {
|
||||||
| --------- the element type for this iterator is not specified
|
| --------- this method call resolves to `std::slice::Iter<'_, T>`
|
||||||
LL | i.clone();
|
LL | i.clone();
|
||||||
| ^^^^^ cannot infer type
|
| ^^^^^ cannot infer type
|
||||||
|
|
|
|
||||||
|
@ -3,5 +3,4 @@ use std::collections::HashMap;
|
|||||||
fn main() {
|
fn main() {
|
||||||
for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
|
for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
|
||||||
//~^ ERROR type mismatch
|
//~^ ERROR type mismatch
|
||||||
//~| ERROR type mismatch
|
|
||||||
}
|
}
|
||||||
|
@ -23,16 +23,6 @@ LL | for _ in HashMap::new().iter().cloned() {}
|
|||||||
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
||||||
= note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
= note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
||||||
|
|
||||||
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as Iterator>::Item == &_`
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/issue-33941.rs:4:14
|
|
||||||
|
|
|
||||||
LL | for _ in HashMap::new().iter().cloned() {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found tuple
|
|
||||||
|
|
|
||||||
= note: expected reference `&_`
|
|
||||||
found tuple `(&_, &_)`
|
|
||||||
= note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
|
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0271`.
|
For more information about this error, try `rustc --explain E0271`.
|
||||||
|
@ -2,7 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
|
|||||||
--> $DIR/dont-print-desugared.rs:4:10
|
--> $DIR/dont-print-desugared.rs:4:10
|
||||||
|
|
|
|
||||||
LL | for &ref mut x in s {}
|
LL | for &ref mut x in s {}
|
||||||
| ^^^^^^^^^ cannot borrow as mutable through `&` reference
|
| ^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
||||||
error[E0597]: `y` does not live long enough
|
error[E0597]: `y` does not live long enough
|
||||||
--> $DIR/dont-print-desugared.rs:17:16
|
--> $DIR/dont-print-desugared.rs:17:16
|
||||||
|
@ -2,12 +2,10 @@ error[E0713]: borrow may still be in use when destructor runs
|
|||||||
--> $DIR/issue-53773.rs:41:22
|
--> $DIR/issue-53773.rs:41:22
|
||||||
|
|
|
|
||||||
LL | members.push(child.raw);
|
LL | members.push(child.raw);
|
||||||
| ^^^^^^^^^
|
| -------------^^^^^^^^^- borrow later used here
|
||||||
LL |
|
LL |
|
||||||
LL | }
|
LL | }
|
||||||
| - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait
|
| - here, drop of `child` needs exclusive access to `*child.raw`, because the type `C<'_>` implements the `Drop` trait
|
||||||
LL | members.len();
|
|
||||||
| ------------- borrow later used here
|
|
||||||
|
|
|
|
||||||
= note: consider using a `let` binding to create a longer lived value
|
= note: consider using a `let` binding to create a longer lived value
|
||||||
|
|
||||||
|
@ -17,5 +17,4 @@ impl Iterator for Void {
|
|||||||
fn main() {
|
fn main() {
|
||||||
for _ in unimplemented!() as Void {}
|
for _ in unimplemented!() as Void {}
|
||||||
//~^ ERROR unreachable pattern
|
//~^ ERROR unreachable pattern
|
||||||
//~^^ ERROR unreachable pattern
|
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,5 @@ note: the lint level is defined here
|
|||||||
LL | #![deny(unreachable_patterns)]
|
LL | #![deny(unreachable_patterns)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: unreachable pattern
|
error: aborting due to previous error
|
||||||
--> $DIR/unreachable-loop-patterns.rs:18:14
|
|
||||||
|
|
|
||||||
LL | for _ in unimplemented!() as Void {}
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user