diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index bd8770abb135c..bf421da61e443 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -4058,16 +4058,16 @@ impl<'a> LoweringContext<'a> {
// expand
let head = self.lower_expr(head);
let head_sp = head.span;
+ let desugared_span = self.allow_internal_unstable(
+ CompilerDesugaringKind::ForLoop,
+ head_sp,
+ );
let iter = self.str_to_ident("iter");
let next_ident = self.str_to_ident("__next");
- let next_sp = self.allow_internal_unstable(
- CompilerDesugaringKind::ForLoop,
- head_sp,
- );
let next_pat = self.pat_ident_binding_mode(
- next_sp,
+ desugared_span,
next_ident,
hir::BindingAnnotation::Mutable,
);
@@ -4096,8 +4096,11 @@ impl<'a> LoweringContext<'a> {
};
// `mut iter`
- let iter_pat =
- self.pat_ident_binding_mode(head_sp, iter, hir::BindingAnnotation::Mutable);
+ let iter_pat = self.pat_ident_binding_mode(
+ desugared_span,
+ iter,
+ hir::BindingAnnotation::Mutable
+ );
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
@@ -4126,8 +4129,12 @@ impl<'a> LoweringContext<'a> {
let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
// `let mut __next`
- let next_let =
- self.stmt_let_pat(head_sp, None, next_pat, hir::LocalSource::ForLoopDesugar);
+ let next_let = self.stmt_let_pat(
+ desugared_span,
+ None,
+ next_pat,
+ hir::LocalSource::ForLoopDesugar,
+ );
// `let = __next`
let pat = self.lower_pat(pat);
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 6fb5acde72c49..3ba31e229e13a 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -46,7 +46,7 @@ use ty::subst::Subst;
use ty::SubtypePredicate;
use util::nodemap::{FxHashMap, FxHashSet};
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat};
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn report_fulfillment_errors(&self,
@@ -68,18 +68,30 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}).collect();
for (index, error) in errors.iter().enumerate() {
- error_map.entry(error.obligation.cause.span).or_default().push(
+ // We want to ignore desugarings here: spans are equivalent even
+ // if one is the result of a desugaring and the other is not.
+ let mut span = error.obligation.cause.span;
+ if let Some(ExpnInfo {
+ format: ExpnFormat::CompilerDesugaring(_),
+ def_site: Some(def_span),
+ ..
+ }) = span.ctxt().outer().expn_info() {
+ span = def_span;
+ }
+
+ error_map.entry(span).or_default().push(
ErrorDescriptor {
predicate: error.obligation.predicate.clone(),
index: Some(index)
- });
+ }
+ );
self.reported_trait_errors.borrow_mut()
- .entry(error.obligation.cause.span).or_default()
+ .entry(span).or_default()
.push(error.obligation.predicate.clone());
}
- // We do this in 2 passes because we want to display errors in order, tho
+ // We do this in 2 passes because we want to display errors in order, though
// maybe it *is* better to sort errors by span or something.
let mut is_suppressed = vec![false; errors.len()];
for (_, error_set) in error_map.iter() {
diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs
index f10361cb076bd..b1f89ce33fcfa 100644
--- a/src/librustc_borrowck/borrowck/unused.rs
+++ b/src/librustc_borrowck/borrowck/unused.rs
@@ -76,10 +76,14 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> {
}
let (hir_id, span) = ids[0];
- let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+ if span.compiler_desugaring_kind().is_some() {
+ // If the `mut` arises as part of a desugaring, we should ignore it.
+ continue;
+ }
// Ok, every name wasn't used mutably, so issue a warning that this
// didn't need to be mutable.
+ let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
tcx.struct_span_lint_hir(UNUSED_MUT,
hir_id,
span,
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 06394ee44ccbe..67170017a12b8 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -316,7 +316,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
}
let span = local_decl.source_info.span;
- let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+ if span.compiler_desugaring_kind().is_some() {
+ // If the `mut` arises as part of a desugaring, we should ignore it.
+ continue;
+ }
let mut err = tcx.struct_span_lint_node(
UNUSED_MUT,
@@ -324,6 +327,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
span,
"variable does not need to be mutable",
);
+ let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
err.span_suggestion_short_with_applicability(
mut_span,
"remove this `mut`",
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index a6c0397568578..288bc7f4814b0 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -140,7 +140,8 @@ enum CallKind {
fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span };
LocalDecl {
- mutability, ty,
+ mutability,
+ ty,
user_ty: None,
name: None,
source_info,
diff --git a/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs
new file mode 100644
index 0000000000000..419d580419f42
--- /dev/null
+++ b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#![deny(unused_mut)]
+#![allow(unreachable_code)]
+
+fn main() {
+ for _ in { return (); 0..3 } {} // ok
+}