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 +}