mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Auto merge of #70415 - Centril:rollup-1zttfvl, r=Centril
Rollup of 6 pull requests Successful merges: - #69866 (Rename `def_span` to `guess_head_span`) - #69878 (Tweak chained operators diagnostic) - #70375 (avoid catching InterpError) - #70386 (typeck: minor pattern typing improvements) - #70389 (borrowck: prefer "value" over "`_`" in diagnostics) - #70395 (Update cargo.) Failed merges: r? @ghost
This commit is contained in:
commit
a17dd36084
@ -367,7 +367,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
|
||||
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<Tag, Extra> {
|
||||
}
|
||||
|
||||
/// Undefined bytes.
|
||||
impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
|
||||
impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
|
||||
/// 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<Tag>, 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<Tag>, 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)))))
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
..
|
||||
|
@ -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;
|
||||
|
@ -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`.
|
||||
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);`
|
||||
|
@ -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!(),
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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<String> {
|
||||
self.describe_place_with_options(place_ref, IncludingDowncast(false))
|
||||
}
|
||||
|
@ -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={:?}",
|
||||
|
@ -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
|
||||
|
@ -565,14 +565,14 @@ fn is_enclosed(
|
||||
}
|
||||
|
||||
fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet<hir::HirId>, 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),
|
||||
);
|
||||
}
|
||||
|
@ -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<Span>,
|
||||
) -> 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<Span>,
|
||||
) -> 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,
|
||||
|
@ -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");
|
||||
|
@ -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<AssocOp>,
|
||||
) {
|
||||
) -> 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::<i32>().is_err() && !matches!(r1.kind, ExprKind::Lit(_)) {
|
||||
// The parser has encountered `foo.bar<baz`, the likelihood of the turbofish
|
||||
// suggestion being the only one to apply is high.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let mut enclose = |left: Span, right: Span| {
|
||||
err.multipart_suggestion(
|
||||
"parenthesize the comparison",
|
||||
vec![
|
||||
(left.shrink_to_lo(), "(".to_string()),
|
||||
(right.shrink_to_hi(), ")".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
return match (op.node, &outer_op.node) {
|
||||
// `x == y == z`
|
||||
(BinOpKind::Eq, AssocOp::Equal) |
|
||||
// `x < y < z` and friends.
|
||||
(BinOpKind::Lt, AssocOp::Less) | (BinOpKind::Lt, AssocOp::LessEqual) |
|
||||
(BinOpKind::Le, AssocOp::LessEqual) | (BinOpKind::Le, AssocOp::Less) |
|
||||
@ -472,35 +490,55 @@ impl<'a> 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<Bar<Baz<Qux, ()>>>`
|
||||
if op.node == BinOpKind::Lt && outer_op.node == AssocOp::Less
|
||||
|| outer_op.node == AssocOp::Greater
|
||||
{
|
||||
// Foo<Bar<Baz<Qux, ()>>>
|
||||
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.
|
||||
|
@ -907,7 +907,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
fn error_bad_item_kind<T>(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option<T> {
|
||||
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
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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()
|
||||
|
@ -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),
|
||||
);
|
||||
|
||||
|
@ -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, '{')
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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<'_>) {
|
||||
|
@ -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)) => {
|
||||
|
@ -2,16 +2,8 @@ error: comparison operators cannot be chained
|
||||
--> $DIR/issue-40396.rs:2:20
|
||||
|
|
||||
LL | (0..13).collect<Vec<i32>>();
|
||||
| ^^^^^
|
||||
| ^ ^
|
||||
|
|
||||
help: split the comparison into two...
|
||||
|
|
||||
LL | (0..13).collect < Vec && Vec <i32>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: ...or parenthesize one of the comparisons
|
||||
|
|
||||
LL | ((0..13).collect < Vec) <i32>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use `::<...>` instead of `<...>` to specify type arguments
|
||||
|
|
||||
LL | (0..13).collect::<Vec<i32>>();
|
||||
@ -21,7 +13,7 @@ error: comparison operators cannot be chained
|
||||
--> $DIR/issue-40396.rs:4:8
|
||||
|
|
||||
LL | Vec<i32>::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<Vec<i32>();
|
||||
| ^^^^^
|
||||
| ^ ^
|
||||
|
|
||||
help: split the comparison into two...
|
||||
|
|
||||
LL | (0..13).collect < Vec && Vec <i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: ...or parenthesize one of the comparisons
|
||||
|
|
||||
LL | ((0..13).collect < Vec) <i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use `::<...>` instead of `<...>` to specify type arguments
|
||||
|
|
||||
LL | (0..13).collect::<Vec<i32>();
|
||||
|
@ -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() {}
|
||||
|
@ -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`.
|
||||
|
@ -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<X>();
|
||||
//~^ ERROR comparison operators cannot be chained
|
||||
@ -16,8 +16,6 @@ fn main() {
|
||||
|
||||
f<Result<Option<X>, Option<Option<X>>>(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;
|
||||
|
@ -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<X>();
|
||||
| ^^^
|
||||
| ^ ^
|
||||
|
|
||||
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<Result<Option<X>, Option<Option<X>>>(1, 2);
|
||||
| ^^^^^^^^
|
||||
| ^ ^
|
||||
|
|
||||
help: split the comparison into two...
|
||||
|
|
||||
LL | f < Result && Result <Option<X>, Option<Option<X>>>(1, 2);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: ...or parenthesize one of the comparisons
|
||||
|
|
||||
LL | (f < Result) <Option<X>, Option<Option<X>>>(1, 2);
|
||||
| ^^^^^^^^^^^^^^
|
||||
help: use `::<...>` instead of `<...>` to specify type arguments
|
||||
|
|
||||
LL | f::<Result<Option<X>, Option<Option<X>>>(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<u8>;
|
||||
| ^^^^
|
||||
| ^ ^
|
||||
|
|
||||
= 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: aborting due to 5 previous errors
|
||||
|
||||
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
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -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<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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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<C>) {}
|
||||
| value moved here
|
||||
| move occurs because value has type `std::boxed::Box<C>`, 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<NC>) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7019b3ed3d539db7429d10a343b69be8c426b576
|
||||
Subproject commit 8a0d4d9c9abc74fd670353094387d62028b40ae9
|
Loading…
Reference in New Issue
Block a user