diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 26b9e1be2f5d4..ada02ceb5cbf3 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -367,7 +367,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. // We must not return `Ok()` for unaligned pointers! - if self.check_defined(ptr, size).is_err() { + if self.is_defined(ptr, size).is_err() { // This inflates undefined bytes to the entire scalar, even if only a few // bytes are undefined. return Ok(ScalarMaybeUndef::Undef); @@ -552,13 +552,19 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Undefined bytes. -impl<'tcx, Tag, Extra> Allocation { +impl<'tcx, Tag: Copy, Extra> Allocation { + /// Checks whether the given range is entirely defined. + /// + /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte + /// at which the first undefined access begins. + fn is_defined(&self, ptr: Pointer, size: Size) -> Result<(), Size> { + self.undef_mask.is_range_defined(ptr.offset, ptr.offset + size) // `Size` addition + } + /// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes` /// error which will report the first byte which is undefined. - #[inline] fn check_defined(&self, ptr: Pointer, size: Size) -> InterpResult<'tcx> { - self.undef_mask - .is_range_defined(ptr.offset, ptr.offset + size) // `Size` addition + self.is_defined(ptr, size) .or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx))))) } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6ebcc8b075462..c129b574fd38a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -108,7 +108,9 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { ObligationCauseCode::CompareImplMethodObligation { .. } | ObligationCauseCode::MainFunctionType - | ObligationCauseCode::StartFunctionType => tcx.sess.source_map().def_span(self.span), + | ObligationCauseCode::StartFunctionType => { + tcx.sess.source_map().guess_head_span(self.span) + } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { arm_span, .. diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 69bcc93415593..c0cc119c5a125 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -388,7 +388,7 @@ impl<'tcx> TyCtxt<'tcx> { assert!(!stack.is_empty()); let fix_span = |span: Span, query: &Query<'tcx>| { - self.sess.source_map().def_span(query.default_span(self, span)) + self.sess.source_map().guess_head_span(query.default_span(self, span)) }; // Disable naming impls with types in this path, since that @@ -456,7 +456,8 @@ impl<'tcx> TyCtxt<'tcx> { query_info.info.query.describe(icx.tcx) ), ); - diag.span = icx.tcx.sess.source_map().def_span(query_info.info.span).into(); + diag.span = + icx.tcx.sess.source_map().guess_head_span(query_info.info.span).into(); handler.force_print_diagnostic(diag); current_query = query_info.job.parent; diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index b4363778094b4..c03c44fc634ce 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -402,7 +402,7 @@ impl<'a> AstValidator<'a> { fn check_defaultness(&self, span: Span, defaultness: Defaultness) { if let Defaultness::Default(def_span) = defaultness { - let span = self.session.source_map().def_span(span); + let span = self.session.source_map().guess_head_span(span); self.err_handler() .struct_span_err(span, "`default` is only allowed on items in `impl` definitions") .span_label(def_span, "`default` because of this") @@ -517,7 +517,7 @@ impl<'a> AstValidator<'a> { } fn current_extern_span(&self) -> Span { - self.session.source_map().def_span(self.extern_mod.unwrap().span) + self.session.source_map().guess_head_span(self.extern_mod.unwrap().span) } /// An `fn` in `extern { ... }` cannot have qualfiers, e.g. `async fn`. diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 364c86bd99b4e..5cd7b58e14e3a 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -257,7 +257,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!( &self, non_ascii_idents, - self.parse_sess.source_map().def_span(sp), + self.parse_sess.source_map().guess_head_span(sp), "non-ascii idents are not fully supported" ); } diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index 6540bcc415605..735de4f0a5b24 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -198,7 +198,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro_derive]` must be `pub`" }; - self.handler.span_err(self.source_map.def_span(item.span), msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -217,7 +217,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro_attribute]` must be `pub`" }; - self.handler.span_err(self.source_map.def_span(item.span), msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -236,7 +236,7 @@ impl<'a> CollectProcMacros<'a> { } else { "functions tagged with `#[proc_macro]` must be `pub`" }; - self.handler.span_err(self.source_map.def_span(item.span), msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } } @@ -247,7 +247,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) { let msg = "cannot export macro_rules! macros from a `proc-macro` crate type currently"; - self.handler.span_err(self.source_map.def_span(item.span), msg); + self.handler.span_err(self.source_map.guess_head_span(item.span), msg); } } @@ -298,7 +298,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { let attr = match found_attr { None => { - self.check_not_pub_in_root(&item.vis, self.source_map.def_span(item.span)); + self.check_not_pub_in_root(&item.vis, self.source_map.guess_head_span(item.span)); let prev_in_root = mem::replace(&mut self.in_root, false); visit::walk_item(self, item); self.in_root = prev_in_root; diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 859362b5e29d3..b9477be57ddda 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -326,7 +326,7 @@ fn generic_extension<'cx>( let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); err.span_label(span, label); if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { - err.span_label(cx.source_map().def_span(def_span), "when calling this macro"); + err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); } // Check whether there's a missing comma in this macro call, like `println!("{}" a);` diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 9c22c38583c33..129bc9e22a667 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -200,7 +200,7 @@ fn msg_span_from_early_bound_and_free_regions( }; let (prefix, span) = match *region { ty::ReEarlyBound(ref br) => { - let mut sp = sm.def_span(tcx.hir().span(node)); + let mut sp = sm.guess_head_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -209,7 +209,7 @@ fn msg_span_from_early_bound_and_free_regions( (format!("the lifetime `{}` as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => { - let mut sp = sm.def_span(tcx.hir().span(node)); + let mut sp = sm.guess_head_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) { @@ -223,7 +223,7 @@ fn msg_span_from_early_bound_and_free_regions( } _ => ( format!("the lifetime `{}` as defined on", region), - sm.def_span(tcx.hir().span(node)), + sm.guess_head_span(tcx.hir().span(node)), ), }, _ => bug!(), diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 8943ce4e6c505..47d3cdb7a4e2b 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -20,12 +20,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { requirement: &dyn fmt::Display, ) -> DiagnosticBuilder<'tcx> { let msg = "impl has stricter requirements than trait"; - let sp = self.tcx.sess.source_map().def_span(error_span); + let sp = self.tcx.sess.source_map().guess_head_span(error_span); let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let span = self.tcx.sess.source_map().def_span(trait_item_span); + let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); err.span_label(span, format!("definition of `{}` from trait", item_name)); } @@ -46,7 +46,7 @@ pub fn report_object_safety_error( hir::Node::Item(item) => Some(item.ident.span), _ => None, }); - let span = tcx.sess.source_map().def_span(span); + let span = tcx.sess.source_map().guess_head_span(span); let mut err = struct_span_err!( tcx.sess, span, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 66d9fe7e14988..906e46edfe7ff 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -76,7 +76,7 @@ impl EarlyLintPass for WhileTrue { if let ast::LitKind::Bool(true) = lit.kind { if !lit.span.from_expansion() { let msg = "denote infinite loops with `loop { ... }`"; - let condition_span = cx.sess.source_map().def_span(e.span); + let condition_span = cx.sess.source_map().guess_head_span(e.span); cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| { lint.build(msg) .span_suggestion_short( @@ -374,9 +374,13 @@ impl MissingDoc { let has_doc = attrs.iter().any(|a| has_doc(a)); if !has_doc { - cx.struct_span_lint(MISSING_DOCS, cx.tcx.sess.source_map().def_span(sp), |lint| { - lint.build(&format!("missing documentation for {} {}", article, desc)).emit() - }); + cx.struct_span_lint( + MISSING_DOCS, + cx.tcx.sess.source_map().guess_head_span(sp), + |lint| { + lint.build(&format!("missing documentation for {} {}", article, desc)).emit() + }, + ); } } } @@ -406,7 +410,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { if !has_doc { cx.struct_span_lint( MISSING_DOCS, - cx.tcx.sess.source_map().def_span(macro_def.span), + cx.tcx.sess.source_map().guess_head_span(macro_def.span), |lint| lint.build("missing documentation for macro").emit(), ); } @@ -978,7 +982,7 @@ impl UnreachablePub { if span.from_expansion() { applicability = Applicability::MaybeIncorrect; } - let def_span = cx.tcx.sess.source_map().def_span(span); + let def_span = cx.tcx.sess.source_map().guess_head_span(span); cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| { let mut err = lint.build(&format!("unreachable `pub` {}", what)); let replacement = if cx.tcx.features().crate_visibility_modifier { diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 27a8616939704..8f18fb4a30ed3 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -256,14 +256,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}", location, place, span, borrow ); - let value_msg = match self.describe_place(place.as_ref()) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - let borrow_msg = match self.describe_place(borrow.borrowed_place.as_ref()) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; + let value_msg = self.describe_any_place(place.as_ref()); + let borrow_msg = self.describe_any_place(borrow.borrowed_place.as_ref()); let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.args_or_use(); @@ -271,10 +265,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(place.as_ref(), location); let span = move_spans.args_or_use(); - let mut err = self.cannot_move_when_borrowed( - span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), - ); + let mut err = + self.cannot_move_when_borrowed(span, &self.describe_any_place(place.as_ref())); err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); @@ -314,16 +306,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_use_when_mutably_borrowed( span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &self.describe_any_place(place.as_ref()), borrow_span, - &self.describe_place(borrow.borrowed_place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &self.describe_any_place(borrow.borrowed_place.as_ref()), ); borrow_spans.var_span_label(&mut err, { let place = &borrow.borrowed_place; - let desc_place = self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()); - - format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()) + let desc_place = self.describe_any_place(place.as_ref()); + format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) }); self.explain_why_borrow_contains_point(location, borrow, None) @@ -433,7 +424,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "borrow occurs due to use of `{}`{}", + "borrow occurs due to use of {}{}", desc_place, borrow_spans.describe(), ), @@ -511,16 +502,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if issued_spans == borrow_spans { borrow_spans.var_span_label( &mut err, - format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()), + format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe()), ); } else { let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = - self.describe_place(borrow_place.as_ref()).unwrap_or_else(|| "_".to_owned()); + let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); issued_spans.var_span_label( &mut err, format!( - "first borrow occurs due to use of `{}`{}", + "first borrow occurs due to use of {}{}", borrow_place_desc, issued_spans.describe(), ), @@ -529,7 +519,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "second borrow occurs due to use of `{}`{}", + "second borrow occurs due to use of {}{}", desc_place, borrow_spans.describe(), ), @@ -538,7 +528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if union_type_name != "" { err.note(&format!( - "`{}` is a field of the union `{}`, so it overlaps the field `{}`", + "{} is a field of the union `{}`, so it overlaps the field {}", msg_place, union_type_name, msg_borrow, )); } @@ -606,7 +596,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from(place_base, place_projection, *self.body, self.infcx.tcx).ty; ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) }; - let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned()); // Start with an empty tuple, so we can use the functions on `Option` to reduce some // code duplication (particularly around returning an empty description in the failure @@ -645,30 +634,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .and_then(|(target_base, target_field)| { // With the place of a union and a field access into it, we traverse the second // borrowed place and look for a access to a different field of the same union. - let Place { local, projection } = second_borrowed_place; + let Place { local, ref projection } = *second_borrowed_place; let mut cursor = &projection[..]; while let [proj_base @ .., elem] = cursor { cursor = proj_base; if let ProjectionElem::Field(field, _) = elem { - if let Some(union_ty) = union_ty(*local, proj_base) { + if let Some(union_ty) = union_ty(local, proj_base) { if field != target_field - && *local == target_base.local + && local == target_base.local && proj_base == target_base.projection { - // FIXME when we avoid clone reuse describe_place closure - let describe_base_place = self - .describe_place(PlaceRef { - local: *local, - projection: proj_base, - }) - .unwrap_or_else(|| "_".to_owned()); - return Some(( - describe_base_place, - describe_place(first_borrowed_place.as_ref()), - describe_place(second_borrowed_place.as_ref()), + self.describe_any_place(PlaceRef { + local, + projection: proj_base, + }), + self.describe_any_place(first_borrowed_place.as_ref()), + self.describe_any_place(second_borrowed_place.as_ref()), union_ty.to_string(), )); } @@ -681,7 +665,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If we didn't find a field access into a union, or both places match, then // only return the description of the first place. ( - describe_place(first_borrowed_place.as_ref()), + self.describe_any_place(first_borrowed_place.as_ref()), "".to_string(), "".to_string(), "".to_string(), @@ -1404,12 +1388,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let loan_spans = self.retrieve_borrow_spans(loan); let loan_span = loan_spans.args_or_use(); + let descr_place = self.describe_any_place(place.as_ref()); if loan.kind == BorrowKind::Shallow { if let Some(section) = self.classify_immutable_section(&loan.assigned_place) { let mut err = self.cannot_mutate_in_immutable_section( span, loan_span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), + &descr_place, section, "assign", ); @@ -1424,11 +1409,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let mut err = self.cannot_assign_to_borrowed( - span, - loan_span, - &self.describe_place(place.as_ref()).unwrap_or_else(|| "_".to_owned()), - ); + let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); loan_spans .var_span_label(&mut err, format!("borrow occurs due to use{}", loan_spans.describe())); @@ -1482,15 +1463,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }) | Some(LocalDecl { local_info: LocalInfo::StaticRef { .. }, .. }) | Some(LocalDecl { local_info: LocalInfo::Other, .. }) - | None => (self.describe_place(place.as_ref()), assigned_span), - Some(decl) => (self.describe_place(err_place.as_ref()), decl.source_info.span), + | None => (self.describe_any_place(place.as_ref()), assigned_span), + Some(decl) => (self.describe_any_place(err_place.as_ref()), decl.source_info.span), }; - let mut err = self.cannot_reassign_immutable( - span, - place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"), - from_arg, - ); + let mut err = self.cannot_reassign_immutable(span, &place_description, from_arg); let msg = if from_arg { "cannot assign to immutable argument" } else { @@ -1498,11 +1475,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if span != assigned_span { if !from_arg { - let value_msg = match place_description { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - err.span_label(assigned_span, format!("first assignment to {}", value_msg)); + err.span_label(assigned_span, format!("first assignment to {}", place_description)); } } if let Some(decl) = local_decl { diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 7110a4a3058a6..605093d8acad2 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -137,8 +137,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - /// End-user visible description of `place` if one can be found. If the - /// place is a temporary for instance, None will be returned. + /// End-user visible description of `place` if one can be found. + /// If the place is a temporary for instance, `"value"` will be returned. + pub(super) fn describe_any_place(&self, place_ref: PlaceRef<'tcx>) -> String { + match self.describe_place(place_ref) { + Some(mut descr) => { + // Surround descr with `backticks`. + descr.reserve(2); + descr.insert_str(0, "`"); + descr.push_str("`"); + descr + } + None => "value".to_string(), + } + } + + /// End-user visible description of `place` if one can be found. + /// If the place is a temporary for instance, None will be returned. pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option { self.describe_place_with_options(place_ref, IncludingDowncast(false)) } diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 83bc9849cafe9..2cdc1ced0bbea 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -272,14 +272,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { span: Span, ) -> DiagnosticBuilder<'a> { let description = if place.projection.len() == 1 { - format!("static item `{}`", self.describe_place(place.as_ref()).unwrap()) + format!("static item {}", self.describe_any_place(place.as_ref())) } else { let base_static = PlaceRef { local: place.local, projection: &[ProjectionElem::Deref] }; format!( - "`{:?}` as `{:?}` is a static item", - self.describe_place(place.as_ref()).unwrap(), - self.describe_place(base_static).unwrap(), + "{} as {} is a static item", + self.describe_any_place(place.as_ref()), + self.describe_any_place(base_static), ) }; @@ -349,16 +349,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_name = upvar.name; let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); - let place_name = self.describe_place(move_place.as_ref()).unwrap(); + let place_name = self.describe_any_place(move_place.as_ref()); - let place_description = if self - .is_upvar_field_projection(move_place.as_ref()) - .is_some() - { - format!("`{}`, a {}", place_name, capture_description) - } else { - format!("`{}`, as `{}` is a {}", place_name, upvar_name, capture_description,) - }; + let place_description = + if self.is_upvar_field_projection(move_place.as_ref()).is_some() { + format!("{}, a {}", place_name, capture_description) + } else { + format!("{}, as `{}` is a {}", place_name, upvar_name, capture_description) + }; debug!( "report: closure_kind_ty={:?} closure_kind={:?} place_description={:?}", diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index ee654431d8892..f224041270dcc 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -169,9 +169,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { borrow_spans.var_span_label( &mut err, format!( - "mutable borrow occurs due to use of `{}` in closure", - // always Some() if the message is printed. - self.describe_place(access_place.as_ref()).unwrap_or_default(), + "mutable borrow occurs due to use of {} in closure", + self.describe_any_place(access_place.as_ref()), ), ); borrow_span diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 437a154a9b80f..3ba60e69041e7 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -565,14 +565,14 @@ fn is_enclosed( } fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id: hir::HirId) { - let span = tcx.sess.source_map().def_span(tcx.hir().span(id)); + let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { let msg = "unnecessary `unsafe` block"; let mut db = lint.build(msg); db.span_label(span, msg); if let Some((kind, id)) = is_enclosed(tcx, used_unsafe, id) { db.span_label( - tcx.sess.source_map().def_span(tcx.hir().span(id)), + tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), format!("because it's nested under this `unsafe` {}", kind), ); } diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index d8ee059f1a6b6..6e6bbabd35b3c 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -4,7 +4,7 @@ use rustc_span::{MultiSpan, Span}; impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { - struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed", desc,) + struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,) } crate fn cannot_use_when_mutably_borrowed( @@ -18,12 +18,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0503, - "cannot use `{}` because it was mutably borrowed", + "cannot use {} because it was mutably borrowed", desc, ); - err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc)); - err.span_label(span, format!("use of borrowed `{}`", borrow_desc)); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_desc)); + err.span_label(span, format!("use of borrowed {}", borrow_desc)); err } @@ -53,12 +53,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { old_load_end_span: Option, ) -> DiagnosticBuilder<'cx> { let via = - |msg: &str| if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) }; + |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( self, new_loan_span, E0499, - "cannot borrow `{}`{} as mutable more than once at a time", + "cannot borrow {}{} as mutable more than once at a time", desc, via(opt_via), ); @@ -103,7 +103,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0524, - "two closures require unique access to `{}` at the same time", + "two closures require unique access to {} at the same time", desc, ); if old_loan_span == new_loan_span { @@ -136,7 +136,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0500, - "closure requires unique access to `{}` but {} is already borrowed{}", + "closure requires unique access to {} but {} is already borrowed{}", desc_new, noun_old, old_opt_via, @@ -168,7 +168,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, new_loan_span, E0501, - "cannot borrow `{}`{} as {} because previous closure \ + "cannot borrow {}{} as {} because previous closure \ requires unique access", desc_new, opt_via, @@ -201,13 +201,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { old_load_end_span: Option, ) -> DiagnosticBuilder<'cx> { let via = - |msg: &str| if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) }; + |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; let mut err = struct_span_err!( self, span, E0502, - "cannot borrow `{}`{} as {} because {} is also borrowed \ - as {}{}", + "cannot borrow {}{} as {} because {} is also borrowed as {}{}", desc_new, via(msg_new), kind_new, @@ -225,7 +224,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { err.span_label( span, format!( - "{} borrow of `{}` -- which overlaps with `{}` -- occurs here", + "{} borrow of {} -- which overlaps with {} -- occurs here", kind_new, msg_new, msg_old, ), ); @@ -248,12 +247,12 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, span, E0506, - "cannot assign to `{}` because it is borrowed", + "cannot assign to {} because it is borrowed", desc, ); - err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc)); - err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc)); + err.span_label(borrow_span, format!("borrow of {} occurs here", desc)); + err.span_label(span, format!("assignment to borrowed {} occurs here", desc)); err } @@ -264,7 +263,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { is_arg: bool, ) -> DiagnosticBuilder<'cx> { let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" }; - struct_span_err!(self, span, E0384, "cannot assign {} `{}`", msg, desc,) + struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc) } crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { @@ -362,7 +361,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { self, mutate_span, E0510, - "cannot {} `{}` in {}", + "cannot {} {} in {}", action, immutable_place, immutable_section, diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs index 8b1ddf7461a76..3f92742261636 100644 --- a/src/librustc_mir_build/lints.rs +++ b/src/librustc_mir_build/lints.rs @@ -123,7 +123,7 @@ fn check_fn_for_unconditional_recursion<'tcx>( // recurs. if !reached_exit_without_self_call && !self_call_locations.is_empty() { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let sp = tcx.sess.source_map().def_span(tcx.hir().span(hir_id)); + let sp = tcx.sess.source_map().guess_head_span(tcx.hir().span(hir_id)); tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| { let mut db = lint.build("function cannot return without recursing"); db.span_label(sp, "cannot return without recursing"); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 87255386b9e66..c4546dedfcdd4 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -17,7 +17,6 @@ use rustc_span::symbol::kw; use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use log::{debug, trace}; -use std::mem; const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; @@ -459,9 +458,28 @@ impl<'a> Parser<'a> { err: &mut DiagnosticBuilder<'_>, inner_op: &Expr, outer_op: &Spanned, - ) { + ) -> bool /* advanced the cursor */ { if let ExprKind::Binary(op, ref l1, ref r1) = inner_op.kind { - match (op.node, &outer_op.node) { + if let ExprKind::Field(_, ident) = l1.kind { + if ident.as_str().parse::().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) { + // The parser has encountered `foo.bar Parser<'a> { self.span_to_snippet(e.span) .unwrap_or_else(|_| pprust::expr_to_string(&e)) }; - err.span_suggestion( - inner_op.span.to(outer_op.span), - "split the comparison into two...", - format!( - "{} {} {} && {} {}", - expr_to_str(&l1), - op.node.to_string(), - expr_to_str(&r1), - expr_to_str(&r1), - outer_op.node.to_ast_binop().unwrap().to_string(), - ), - Applicability::MaybeIncorrect, - ); - err.span_suggestion( - inner_op.span.to(outer_op.span), - "...or parenthesize one of the comparisons", - format!( - "({} {} {}) {}", - expr_to_str(&l1), - op.node.to_string(), - expr_to_str(&r1), - outer_op.node.to_ast_binop().unwrap().to_string(), - ), + err.span_suggestion_verbose( + inner_op.span.shrink_to_hi(), + "split the comparison into two", + format!(" && {}", expr_to_str(&r1)), Applicability::MaybeIncorrect, ); + false // Keep the current parse behavior, where the AST is `(x < y) < z`. } - _ => {} - } + // `x == y < z` + (BinOpKind::Eq, AssocOp::Less) | (BinOpKind::Eq, AssocOp::LessEqual) | + (BinOpKind::Eq, AssocOp::Greater) | (BinOpKind::Eq, AssocOp::GreaterEqual) => { + // Consume `z`/outer-op-rhs. + let snapshot = self.clone(); + match self.parse_expr() { + Ok(r2) => { + // We are sure that outer-op-rhs could be consumed, the suggestion is + // likely correct. + enclose(r1.span, r2.span); + true + } + Err(mut expr_err) => { + expr_err.cancel(); + *self = snapshot; + false + } + } + } + // `x > y == z` + (BinOpKind::Lt, AssocOp::Equal) | (BinOpKind::Le, AssocOp::Equal) | + (BinOpKind::Gt, AssocOp::Equal) | (BinOpKind::Ge, AssocOp::Equal) => { + let snapshot = self.clone(); + // At this point it is always valid to enclose the lhs in parentheses, no + // further checks are necessary. + match self.parse_expr() { + Ok(_) => { + enclose(l1.span, r1.span); + true + } + Err(mut expr_err) => { + expr_err.cancel(); + *self = snapshot; + false + } + } + } + _ => false, + }; } + false } /// Produces an error if comparison operators are chained (RFC #558). @@ -534,31 +572,26 @@ impl<'a> Parser<'a> { |this: &Self, span| Ok(Some(this.mk_expr(span, ExprKind::Err, AttrVec::new()))); match inner_op.kind { - ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // Respan to include both operators. - let op_span = op.span.to(self.prev_token.span); - let mut err = - self.struct_span_err(op_span, "comparison operators cannot be chained"); - - // If it looks like a genuine attempt to chain operators (as opposed to a - // misformatted turbofish, for instance), suggest a correct form. - self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op); + ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => { + let mut err = self.struct_span_err( + vec![op.span, self.prev_token.span], + "comparison operators cannot be chained", + ); let suggest = |err: &mut DiagnosticBuilder<'_>| { err.span_suggestion_verbose( - op_span.shrink_to_lo(), + op.span.shrink_to_lo(), TURBOFISH, "::".to_string(), Applicability::MaybeIncorrect, ); }; - if op.node == BinOpKind::Lt && - outer_op.node == AssocOp::Less || // Include `<` to provide this recommendation - outer_op.node == AssocOp::Greater - // even in a case like the following: + // Include `<` to provide this recommendation even in a case like + // `Foo>>` + if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Less + || outer_op.node == AssocOp::Greater { - // Foo>> if outer_op.node == AssocOp::Less { let snapshot = self.clone(); self.bump(); @@ -572,7 +605,7 @@ impl<'a> Parser<'a> { { // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the // parser and bail out. - mem::replace(self, snapshot.clone()); + *self = snapshot.clone(); } } return if token::ModSep == self.token.kind { @@ -597,7 +630,7 @@ impl<'a> Parser<'a> { expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. - mem::replace(self, snapshot); + *self = snapshot; Err(err) } } @@ -617,15 +650,33 @@ impl<'a> Parser<'a> { } } } else { - // All we know is that this is `foo < bar >` and *nothing* else. Try to - // be helpful, but don't attempt to recover. - err.help(TURBOFISH); - err.help("or use `(...)` if you meant to specify fn arguments"); - // These cases cause too many knock-down errors, bail out (#61329). - Err(err) + if !matches!(l1.kind, ExprKind::Lit(_)) + && !matches!(r1.kind, ExprKind::Lit(_)) + { + // All we know is that this is `foo < bar >` and *nothing* else. Try to + // be helpful, but don't attempt to recover. + err.help(TURBOFISH); + err.help("or use `(...)` if you meant to specify fn arguments"); + } + + // If it looks like a genuine attempt to chain operators (as opposed to a + // misformatted turbofish, for instance), suggest a correct form. + if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op) + { + err.emit(); + mk_err_expr(self, inner_op.span.to(self.prev_token.span)) + } else { + // These cases cause too many knock-down errors, bail out (#61329). + Err(err) + } }; } + let recover = + self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op); err.emit(); + if recover { + return mk_err_expr(self, inner_op.span.to(self.prev_token.span)); + } } _ => {} } @@ -643,7 +694,7 @@ impl<'a> Parser<'a> { if self.token.kind == token::Eof { // Not entirely sure that what we consumed were fn arguments, rollback. - mem::replace(self, snapshot); + *self = snapshot; Err(()) } else { // 99% certain that the suggestion is correct, continue parsing. diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 7a4f76804157f..cc88464d774e8 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -907,7 +907,7 @@ impl<'a> Parser<'a> { } fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option { - let span = self.sess.source_map().def_span(span); + let span = self.sess.source_map().guess_head_span(span); let msg = format!("{} is not supported in {}", kind.descr(), ctx); self.struct_span_err(span, &msg).emit(); None diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 4466dea89b0c1..2781c5c125d9f 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -590,7 +590,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { // We should probably annotate ident.span with the macro // context, but that's a larger change. if item.span.source_callee().is_some() { - self.tcx.sess.source_map().def_span(item.span) + self.tcx.sess.source_map().guess_head_span(item.span) } else { item.ident.span } @@ -663,7 +663,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } hir::ImplItemKind::Fn(_, body_id) => { if !self.symbol_is_live(impl_item.hir_id) { - let span = self.tcx.sess.source_map().def_span(impl_item.span); + let span = self.tcx.sess.source_map().guess_head_span(impl_item.span); self.warn_dead_code( impl_item.hir_id, span, diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 9cd066b629c07..78b7e256de217 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -791,12 +791,12 @@ impl<'a> Resolver<'a> { _ => Some( self.session .source_map() - .def_span(self.cstore().get_span_untracked(def_id, self.session)), + .guess_head_span(self.cstore().get_span_untracked(def_id, self.session)), ), }); if let Some(span) = def_span { err.span_label( - self.session.source_map().def_span(span), + self.session.source_map().guess_head_span(span), &format!( "similarly named {} `{}` defined here", suggestion.res.descr(), @@ -986,7 +986,7 @@ impl<'a> Resolver<'a> { which = if first { "" } else { " which" }, dots = if next_binding.is_some() { "..." } else { "" }, ); - let def_span = self.session.source_map().def_span(binding.span); + let def_span = self.session.source_map().guess_head_span(binding.span); let mut note_span = MultiSpan::from_span(def_span); if !first && binding.vis == ty::Visibility::Public { note_span.push_span_label(def_span, "consider importing it directly".into()); diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index d375ae4a447a3..8c7ab8f5b1a5a 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1441,7 +1441,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let enum_resolution = resolutions.get(&key).expect("resolution should exist"); let enum_span = enum_resolution.borrow().binding.expect("binding should exist").span; - let enum_def_span = this.session.source_map().def_span(enum_span); + let enum_def_span = this.session.source_map().guess_head_span(enum_span); let enum_def_snippet = this .session .source_map() diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ed304572a0621..9d5121cbad562 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2517,7 +2517,8 @@ impl<'a> Resolver<'a> { false => "defined", }; - let (name, span) = (ident.name, self.session.source_map().def_span(new_binding.span)); + let (name, span) = + (ident.name, self.session.source_map().guess_head_span(new_binding.span)); if let Some(s) = self.name_already_seen.get(&name) { if s == &span { @@ -2558,7 +2559,7 @@ impl<'a> Resolver<'a> { err.span_label(span, format!("`{}` re{} here", name, new_participle)); err.span_label( - self.session.source_map().def_span(old_binding.span), + self.session.source_map().guess_head_span(old_binding.span), format!("previous {} of the {} `{}` here", old_noun, old_kind, name), ); diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index fa5baffbe48da..57e68320f3fbb 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -733,7 +733,14 @@ impl SourceMap { } } - pub fn def_span(&self, sp: Span) -> Span { + /// Given a `Span`, return a span ending in the closest `{`. This is useful when you have a + /// `Span` enclosing a whole item but we need to point at only the head (usually the first + /// line) of that item. + /// + /// *Only suitable for diagnostics.* + pub fn guess_head_span(&self, sp: Span) -> Span { + // FIXME: extend the AST items to have a head span, or replace callers with pointing at + // the item's ident when appropriate. self.span_until_char(sp, '{') } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index b9ee991aa0226..12939519fc28f 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -482,11 +482,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { let found_kind = self.closure_kind(closure_substs).unwrap(); - let closure_span = self - .tcx - .sess - .source_map() - .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap()); + let closure_span = + self.tcx.sess.source_map().guess_head_span( + self.tcx.hir().span_if_local(closure_def_id).unwrap(), + ); let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap(); let mut err = struct_span_err!( self.tcx.sess, @@ -580,7 +579,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let found_span = found_did .and_then(|did| self.tcx.hir().span_if_local(did)) - .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def + .map(|sp| self.tcx.sess.source_map().guess_head_span(sp)); // the sp could be an fn def if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { // We check closures twice, with obligations flowing in different directions, @@ -680,7 +679,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), .. }) => ( - self.tcx.sess.source_map().def_span(span), + self.tcx.sess.source_map().guess_head_span(span), self.tcx .hir() .body(id) @@ -723,7 +722,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { kind: hir::TraitItemKind::Fn(ref sig, _), .. }) => ( - self.tcx.sess.source_map().def_span(span), + self.tcx.sess.source_map().guess_head_span(span), sig.decl .inputs .iter() @@ -741,7 +740,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .ctor_hir_id() .map(|hir_id| self.tcx.hir().span(hir_id)) .unwrap_or(DUMMY_SP); - let span = self.tcx.sess.source_map().def_span(span); + let span = self.tcx.sess.source_map().guess_head_span(span); (span, vec![ArgKind::empty(); variant_data.fields().len()]) } @@ -1624,7 +1623,7 @@ pub fn recursive_type_with_infinite_size_error( ) -> DiagnosticBuilder<'tcx> { assert!(type_def_id.is_local()); let span = tcx.hir().span_if_local(type_def_id).unwrap(); - let span = tcx.sess.source_map().def_span(span); + let span = tcx.sess.source_map().guess_head_span(span); let mut err = struct_span_err!( tcx.sess, span, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 22b8d0583966b..a4be70df122d7 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1381,7 +1381,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!("required by `{}`", item_name); if let Some(sp) = tcx.hir().span_if_local(item_def_id) { - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); err.span_label(sp, &msg); } else { err.note(&msg); diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index b763851b86ef6..0cc5032d74e8e 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -325,7 +325,7 @@ pub(super) fn specialization_graph_provider( if let Some(overlap) = overlap { let impl_span = - tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()); + tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()); // Work to be done after we've built the DiagnosticBuilder. We have to define it // now because the struct_lint methods don't return back the DiagnosticBuilder @@ -347,7 +347,7 @@ pub(super) fn specialization_graph_provider( match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { err.span_label( - tcx.sess.source_map().def_span(span), + tcx.sess.source_map().guess_head_span(span), "first implementation here".to_string(), ); diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index ac2da006df35d..aa129d2b81c53 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { _ => (None, None), }; - let item_span = item.map(|i| tcx.sess.source_map().def_span(i.span)); + let item_span = item.map(|i| tcx.sess.source_map().guess_head_span(i.span)); match pred { ty::Predicate::Projection(proj) => { // The obligation comes not from the current `impl` nor the `trait` being diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3bf144e9643f0..54c646b855777 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2269,7 +2269,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if let Some(sp) = tcx.hir().span_if_local(adt_def.did) { - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); err.span_label(sp, format!("variant `{}` not found here", assoc_ident)); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 20737b44e7c17..a34389b7d8968 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -332,7 +332,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // | |_____^ expected integer, found `()` // ``` if outer_sp.is_some() { - outer_sp = Some(self.tcx.sess.source_map().def_span(span)); + outer_sp = Some(self.tcx.sess.source_map().guess_head_span(span)); } else_expr.span } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index f666ef72d5278..412f687b43ec6 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -35,7 +35,7 @@ crate fn compare_impl_method<'tcx>( ) { debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); - let impl_m_span = tcx.sess.source_map().def_span(impl_m_span); + let impl_m_span = tcx.sess.source_map().guess_head_span(impl_m_span); if let Err(ErrorReported) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) { @@ -363,7 +363,7 @@ fn check_region_bounds_on_impl_item<'tcx>( // the moment, give a kind of vague error message. if trait_params != impl_params { let item_kind = assoc_item_kind_str(impl_m); - let def_span = tcx.sess.source_map().def_span(span); + let def_span = tcx.sess.source_map().guess_head_span(span); let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span); let mut err = struct_span_err!( tcx.sess, @@ -375,7 +375,7 @@ fn check_region_bounds_on_impl_item<'tcx>( ); err.span_label(span, &format!("lifetimes do not match {} in trait", item_kind)); if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) { - let def_sp = tcx.sess.source_map().def_span(sp); + let def_sp = tcx.sess.source_map().guess_head_span(sp); let sp = tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp); err.span_label( sp, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 68996f5aaf973..e940ecce0b9fb 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(note_span) = note_span { // We have a span pointing to the method. Show note with snippet. err.span_note( - self.tcx.sess.source_map().def_span(note_span), + self.tcx.sess.source_map().guess_head_span(note_span), ¬e_str, ); } else { @@ -189,8 +189,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(item) => item, None => continue, }; - let item_span = - self.tcx.sess.source_map().def_span(self.tcx.def_span(item.def_id)); + let item_span = self + .tcx + .sess + .source_map() + .guess_head_span(self.tcx.def_span(item.def_id)); let idx = if sources.len() > 1 { let msg = &format!( "candidate #{} is defined in the trait `{}`", @@ -397,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { - let def_sp = tcx.sess.source_map().def_span(full_sp); + let def_sp = tcx.sess.source_map().guess_head_span(full_sp); err.span_label( def_sp, format!( @@ -537,8 +540,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut restrict_type_params = false; if !unsatisfied_predicates.is_empty() { - let def_span = - |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); + let def_span = |def_id| { + self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id)) + }; let mut type_params = FxHashMap::default(); let mut bound_spans = vec![]; let mut collect_type_param_suggestions = @@ -1117,7 +1121,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [trait_info] = &candidates[..] { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { err.span_note( - self.tcx.sess.source_map().def_span(span), + self.tcx.sess.source_map().guess_head_span(span), &format!( "`{}` defines an item `{}`, perhaps you need to {} it", self.tcx.def_path_str(trait_info.def_id), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 085510452c47e..e7ba00ac24507 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1479,7 +1479,7 @@ fn check_fn<'a, 'tcx>( } } } else { - let span = sess.source_map().def_span(span); + let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); } } else { @@ -1520,7 +1520,7 @@ fn check_fn<'a, 'tcx>( } } } else { - let span = sess.source_map().def_span(span); + let span = sess.source_map().guess_head_span(span); sess.span_err(span, "function should have one argument"); } } else { @@ -1962,7 +1962,7 @@ fn check_impl_items_against_trait<'tcx>( impl_trait_ref: ty::TraitRef<'tcx>, impl_item_refs: &[hir::ImplItemRef<'_>], ) { - let impl_span = tcx.sess.source_map().def_span(full_impl_span); + let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` @@ -2508,7 +2508,7 @@ fn check_transparent(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { if !adt.repr.transparent() { return; } - let sp = tcx.sess.source_map().def_span(sp); + let sp = tcx.sess.source_map().guess_head_span(sp); if adt.is_union() && !tcx.features().transparent_unions { feature_err( @@ -3875,7 +3875,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().def_span(sp)) { + if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().guess_head_span(sp)) { err.span_label(def_s, "defined here"); } if sugg_unit { @@ -4966,7 +4966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&found.kind, self.suggest_fn_call(err, expr, expected, found)) { if let Some(sp) = self.tcx.hir().span_if_local(*def_id) { - let sp = self.sess().source_map().def_span(sp); + let sp = self.sess().source_map().guess_head_span(sp); err.span_label(sp, &format!("{} defined here", found)); } } else if !self.check_for_cast(err, expr, found, expected) { diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 0d38fa98bd7f8..0c4a05e61814d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -835,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { on_error(); return tcx.types.err; } - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => { + Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => { report_unexpected_res(res); return tcx.types.err; } @@ -1020,7 +1020,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Adt(adt, substs) => (substs, adt), _ => span_bug!(pat.span, "struct pattern is not an ADT"), }; - let kind_name = adt.variant_descr(); // Index the struct fields' types. let field_map = variant @@ -1074,7 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !inexistent_fields.is_empty() && !variant.recovered { self.error_inexistent_fields( - kind_name, + adt.variant_descr(), &inexistent_fields, &mut unmentioned_fields, variant, @@ -1083,18 +1082,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Require `..` if struct has non_exhaustive attribute. if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { - struct_span_err!( - tcx.sess, - pat.span, - E0638, - "`..` required with {} marked as non-exhaustive", - kind_name - ) - .emit(); + self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } // Report an error if incorrect number of the fields were specified. - if kind_name == "union" { + if adt.is_union() { if fields.len() != 1 { tcx.sess .struct_span_err(pat.span, "union patterns should have exactly one field") @@ -1109,6 +1101,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_field_errors } + fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) { + let sess = self.tcx.sess; + let sm = sess.source_map(); + let sp_brace = sm.end_point(pat.span); + let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi())); + let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" }; + + let mut err = struct_span_err!( + sess, + pat.span, + E0638, + "`..` required with {} marked as non-exhaustive", + descr + ); + err.span_suggestion_verbose( + sp_comma, + "add `..` at the end of the field list to ignore all other fields", + sugg.to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + fn error_field_already_bound(&self, span: Span, ident: ast::Ident, other_field: Span) { struct_span_err!( self.tcx.sess, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 27b2c19499ccd..6ed4f62c4bea2 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -20,7 +20,7 @@ mod unsafety; /// Obtains the span of just the impl header of `impl_def_id`. fn impl_header_span(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Span { - tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap()) + tcx.sess.source_map().guess_head_span(tcx.span_of_impl(impl_def_id).unwrap()) } fn check_impl(tcx: TyCtxt<'_>, impl_def_id: DefId, trait_ref: ty::TraitRef<'_>) { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index fc77aad8688c6..cc0ad364177a0 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -34,7 +34,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; let sm = self.tcx.sess.source_map(); - let sp = sm.def_span(item.span); + let sp = sm.guess_head_span(item.span); match traits::orphan_check(self.tcx, def_id) { Ok(()) => {} Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => { diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index f952136a7bfe3..10972697f9fcd 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -2,16 +2,8 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:2:20 | LL | (0..13).collect>(); - | ^^^^^ + | ^ ^ | -help: split the comparison into two... - | -LL | (0..13).collect < Vec && Vec >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | ((0..13).collect < Vec) >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); @@ -21,7 +13,7 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:4:8 | LL | Vec::new(); - | ^^^^^ + | ^ ^ | help: use `::<...>` instead of `<...>` to specify type arguments | @@ -32,16 +24,8 @@ error: comparison operators cannot be chained --> $DIR/issue-40396.rs:6:20 | LL | (0..13).collect(); - | ^^^^^ - | -help: split the comparison into two... - | -LL | (0..13).collect < Vec && Vec (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^ ^ | -LL | ((0..13).collect < Vec) (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); diff --git a/src/test/ui/parser/chained-comparison-suggestion.rs b/src/test/ui/parser/chained-comparison-suggestion.rs index 0431196f1744e..bbd46082c9f90 100644 --- a/src/test/ui/parser/chained-comparison-suggestion.rs +++ b/src/test/ui/parser/chained-comparison-suggestion.rs @@ -37,4 +37,17 @@ fn comp8() { //~^ ERROR mismatched types } +fn comp9() { + 1 == 2 < 3; //~ ERROR comparison operators cannot be chained +} + +fn comp10() { + 1 > 2 == false; //~ ERROR comparison operators cannot be chained +} + +fn comp11() { + 1 == 2 == 3; //~ ERROR comparison operators cannot be chained + //~^ ERROR mismatched types +} + fn main() {} diff --git a/src/test/ui/parser/chained-comparison-suggestion.stderr b/src/test/ui/parser/chained-comparison-suggestion.stderr index 5c10a4599dd03..067920d12f486 100644 --- a/src/test/ui/parser/chained-comparison-suggestion.stderr +++ b/src/test/ui/parser/chained-comparison-suggestion.stderr @@ -2,127 +2,122 @@ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:4:7 | LL | 1 < 2 <= 3; - | ^^^^^^ + | ^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 < 2 && 2 <= 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 < 2) <= 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:9:7 | LL | 1 < 2 < 3; - | ^^^^^ + | ^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 < 2 && 2 < 3; - | ^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 < 2) < 3; - | ^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:13:7 | LL | 1 <= 2 < 3; - | ^^^^^^ + | ^^ ^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 <= 2 && 2 < 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 <= 2) < 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:18:7 | LL | 1 <= 2 <= 3; - | ^^^^^^^ + | ^^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 <= 2 && 2 <= 3; - | ^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 <= 2) <= 3; - | ^^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:23:7 | LL | 1 > 2 >= 3; - | ^^^^^^ + | ^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 > 2 && 2 >= 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 > 2) >= 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:28:7 | LL | 1 > 2 > 3; - | ^^^^^ + | ^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 > 2 && 2 > 3; - | ^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 > 2) > 3; - | ^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:32:7 | LL | 1 >= 2 > 3; - | ^^^^^^ + | ^^ ^ | - = help: use `::<...>` instead of `<...>` to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments -help: split the comparison into two... +help: split the comparison into two | LL | 1 >= 2 && 2 > 3; - | ^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons - | -LL | (1 >= 2) > 3; - | ^^^^^^^^^^ + | ^^^^ error: comparison operators cannot be chained --> $DIR/chained-comparison-suggestion.rs:36:7 | LL | 1 >= 2 >= 3; - | ^^^^^^^ + | ^^ ^^ | -help: split the comparison into two... +help: split the comparison into two | LL | 1 >= 2 && 2 >= 3; - | ^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^^^^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:41:7 + | +LL | 1 == 2 < 3; + | ^^ ^ | -LL | (1 >= 2) >= 3; - | ^^^^^^^^^^^ +help: parenthesize the comparison + | +LL | 1 == (2 < 3); + | ^ ^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:45:7 + | +LL | 1 > 2 == false; + | ^ ^^ + | +help: parenthesize the comparison + | +LL | (1 > 2) == false; + | ^ ^ + +error: comparison operators cannot be chained + --> $DIR/chained-comparison-suggestion.rs:49:7 + | +LL | 1 == 2 == 3; + | ^^ ^^ + | +help: split the comparison into two + | +LL | 1 == 2 && 2 == 3; + | ^^^^ error[E0308]: mismatched types --> $DIR/chained-comparison-suggestion.rs:4:14 @@ -154,6 +149,12 @@ error[E0308]: mismatched types LL | 1 >= 2 >= 3; | ^ expected `bool`, found integer -error: aborting due to 13 previous errors +error[E0308]: mismatched types + --> $DIR/chained-comparison-suggestion.rs:49:15 + | +LL | 1 == 2 == 3; + | ^ expected `bool`, found integer + +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index e27b03dddc5be..4e97904ed6d5f 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -4,11 +4,11 @@ struct X; fn main() { false == false == false; //~^ ERROR comparison operators cannot be chained + //~| HELP split the comparison into two false == 0 < 2; //~^ ERROR comparison operators cannot be chained - //~| ERROR mismatched types - //~| ERROR mismatched types + //~| HELP parenthesize the comparison f(); //~^ ERROR comparison operators cannot be chained @@ -16,8 +16,6 @@ fn main() { f, Option>>(1, 2); //~^ ERROR comparison operators cannot be chained - //~| HELP split the comparison into two... - //~| ...or parenthesize one of the comparisons //~| HELP use `::<...>` instead of `<...>` to specify type arguments use std::convert::identity; diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 44edf2de7f8de..7001aa8e8a1d8 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -2,19 +2,29 @@ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:5:11 | LL | false == false == false; - | ^^^^^^^^^^^ + | ^^ ^^ + | +help: split the comparison into two + | +LL | false == false && false == false; + | ^^^^^^^^ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:8:11 + --> $DIR/require-parens-for-chained-comparison.rs:9:11 | LL | false == 0 < 2; - | ^^^^^^ + | ^^ ^ + | +help: parenthesize the comparison + | +LL | false == (0 < 2); + | ^ ^ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:13:6 | LL | f(); - | ^^^ + | ^ ^ | help: use `::<...>` instead of `<...>` to specify type arguments | @@ -25,42 +35,21 @@ error: comparison operators cannot be chained --> $DIR/require-parens-for-chained-comparison.rs:17:6 | LL | f, Option>>(1, 2); - | ^^^^^^^^ - | -help: split the comparison into two... - | -LL | f < Result && Result , Option>>(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^ -help: ...or parenthesize one of the comparisons + | ^ ^ | -LL | (f < Result) , Option>>(1, 2); - | ^^^^^^^^^^^^^^ help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:24:21 + --> $DIR/require-parens-for-chained-comparison.rs:22:21 | LL | let _ = identity; - | ^^^^ + | ^ ^ | = help: use `::<...>` instead of `<...>` to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error[E0308]: mismatched types - --> $DIR/require-parens-for-chained-comparison.rs:8:14 - | -LL | false == 0 < 2; - | ^ expected `bool`, found integer - -error[E0308]: mismatched types - --> $DIR/require-parens-for-chained-comparison.rs:8:18 - | -LL | false == 0 < 2; - | ^ expected `bool`, found integer - -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs index 32c638bcbcca3..f1680e9e8884e 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs @@ -45,19 +45,19 @@ fn main() { *b = NC; let ref a @ box ref mut b = Box::new(NC); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = NC; drop(a); let ref mut a @ box ref b = Box::new(NC); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); fn f5(ref mut a @ box ref b: Box) { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); } @@ -65,7 +65,7 @@ fn main() { match Box::new(nc()) { ref mut a @ box ref b => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr index 5534d0a75e63d..5ce546f08bf6f 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -99,7 +99,7 @@ LL | a @ box b => {} | | value used here after move | value moved here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-at-and-box.rs:46:21 | LL | let ref a @ box ref mut b = Box::new(NC); @@ -111,7 +111,7 @@ LL | let ref a @ box ref mut b = Box::new(NC); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:52:25 | LL | let ref mut a @ box ref b = Box::new(NC); @@ -123,7 +123,7 @@ LL | let ref mut a @ box ref b = Box::new(NC); LL | *a = Box::new(NC); | -- mutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:66:25 | LL | ref mut a @ box ref b => { @@ -155,7 +155,7 @@ LL | fn f2(a @ box b: Box) {} | value moved here | move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-at-and-box.rs:58:27 | LL | fn f5(ref mut a @ box ref b: Box) { diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 58d4a9b018cee..2b5e339c6396e 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -10,7 +10,7 @@ fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable **z = None; println!("{}", *a); } @@ -47,12 +47,12 @@ fn main() { let ref mut a @ ref b = u(); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = u(); drop(b); let ref a @ ref mut b = u(); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = u(); drop(a); @@ -78,8 +78,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; drop(a); } @@ -123,15 +123,15 @@ fn main() { let ref a @ (ref mut b, ref mut c) = (U, U); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; drop(a); let ref a @ (ref mut b, ref mut c) = (U, U); //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable - *b = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable - *c = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable + *b = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + *c = U; //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable drop(a); let ref mut a @ (ref b, ref c) = (U, U); //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 8c6ca888e0762..b161054414a30 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -294,7 +294,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value moved into `c` here | value borrowed, by `b`, here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31 | LL | ref mut z @ &mut Some(ref a) => { @@ -306,7 +306,7 @@ LL | ref mut z @ &mut Some(ref a) => { LL | **z = None; | ---------- mutable borrow later used here -error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21 | LL | let ref mut a @ ref b = u(); @@ -318,7 +318,7 @@ LL | let ref mut a @ ref b = u(); LL | *a = u(); | -------- mutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17 | LL | let ref a @ ref mut b = u(); @@ -330,7 +330,7 @@ LL | let ref a @ ref mut b = u(); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { @@ -342,7 +342,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { @@ -402,7 +402,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -414,7 +414,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -426,7 +426,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); @@ -438,7 +438,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index f5c39a7ac5276..a208d0087ff53 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -27,7 +27,7 @@ fn main() { let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time drop(a); let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time @@ -37,7 +37,7 @@ fn main() { let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *a = U; let ref mut a @ ref mut b = U; //~^ ERROR cannot borrow value as mutable more than once at a time @@ -95,11 +95,11 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *a = Err(U); - // FIXME: The binding name `_` used above makes for problematic diagnostics. + // FIXME: The binding name value used above makes for problematic diagnostics. // Resolve that somehow... } } @@ -107,8 +107,8 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time - //~| ERROR cannot borrow `_` as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time drop(a); } } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index e74f227b5e48c..ae7c8f38e1eb4 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -258,7 +258,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} | | value moved into `c` here | value borrowed, by `b`, here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:28:21 | LL | let ref mut a @ ref mut b = U; @@ -270,7 +270,7 @@ LL | let ref mut a @ ref mut b = U; LL | drop(a); | - first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:38:21 | LL | let ref mut a @ ref mut b = U; @@ -318,7 +318,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | | value borrowed here after move | value moved here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:95:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -330,7 +330,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | *a = Err(U); | ----------- first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:95:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -342,7 +342,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | *a = Err(U); | ----------- first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:107:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { @@ -354,7 +354,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | drop(a); | - first borrow later used here -error[E0499]: cannot borrow `_` as mutable more than once at a time +error[E0499]: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:107:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs index b40c3e3358aa3..a45497229ac9e 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs @@ -29,7 +29,7 @@ fn main() { let _a: &NotCopy = a; let _b: NotCopy = b; let ref mut a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed - //~^ ERROR cannot move out of `_` because it is borrowed + //~^ ERROR cannot move out of value because it is borrowed let _a: &NotCopy = a; let _b: NotCopy = b; match Ok(NotCopy) { diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index 19e815a1ae8ad..141d667c7460c 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -44,7 +44,7 @@ LL | ref a @ b => { | | value moved into `b` here | value borrowed, by `a`, here -error[E0505]: cannot move out of `_` because it is borrowed +error[E0505]: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:31:21 | LL | let ref mut a @ b = NotCopy; diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 4e91e7bff34b2..3bc38830537cf 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -62,18 +62,33 @@ error[E0638]: `..` required with struct marked as non-exhaustive | LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let NormalStruct { first_field, second_field , .. } = ns; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:26:9 | LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:35:9 | LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | let UnitStruct { .. } = us; + | ^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index ae4f6aff11a02..fbdbb0c9930a6 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -69,12 +69,22 @@ error[E0638]: `..` required with variant marked as non-exhaustive | LL | NonExhaustiveVariants::Struct { field } => "" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | NonExhaustiveVariants::Struct { field , .. } => "" + | ^^^^^^ error[E0638]: `..` required with variant marked as non-exhaustive --> $DIR/variant.rs:30:12 | LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list to ignore all other fields + | +LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { + | ^^^^^^ error: aborting due to 8 previous errors diff --git a/src/tools/cargo b/src/tools/cargo index 7019b3ed3d539..8a0d4d9c9abc7 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 7019b3ed3d539db7429d10a343b69be8c426b576 +Subproject commit 8a0d4d9c9abc74fd670353094387d62028b40ae9