summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/borrowck_errors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/borrowck_errors.rs')
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs486
1 files changed, 486 insertions, 0 deletions
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
new file mode 100644
index 000000000..08ea00d71
--- /dev/null
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -0,0 +1,486 @@
+use rustc_errors::{
+ struct_span_err, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
+
+impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
+ pub(crate) fn cannot_move_when_borrowed(
+ &self,
+ span: Span,
+ desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,)
+ }
+
+ pub(crate) fn cannot_use_when_mutably_borrowed(
+ &self,
+ span: Span,
+ desc: &str,
+ borrow_span: Span,
+ borrow_desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0503,
+ "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
+ }
+
+ pub(crate) fn cannot_mutably_borrow_multiply(
+ &self,
+ new_loan_span: Span,
+ desc: &str,
+ opt_via: &str,
+ old_loan_span: Span,
+ old_opt_via: &str,
+ old_load_end_span: Option<Span>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let via =
+ |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",
+ desc,
+ via(opt_via),
+ );
+ if old_loan_span == new_loan_span {
+ // Both borrows are happening in the same place
+ // Meaning the borrow is occurring in a loop
+ err.span_label(
+ new_loan_span,
+ format!(
+ "{}{} was mutably borrowed here in the previous iteration of the loop{}",
+ desc,
+ via(opt_via),
+ opt_via,
+ ),
+ );
+ if let Some(old_load_end_span) = old_load_end_span {
+ err.span_label(old_load_end_span, "mutable borrow ends here");
+ }
+ } else {
+ err.span_label(
+ old_loan_span,
+ format!("first mutable borrow occurs here{}", via(old_opt_via)),
+ );
+ err.span_label(
+ new_loan_span,
+ format!("second mutable borrow occurs here{}", via(opt_via)),
+ );
+ if let Some(old_load_end_span) = old_load_end_span {
+ err.span_label(old_load_end_span, "first borrow ends here");
+ }
+ }
+ err
+ }
+
+ pub(crate) fn cannot_uniquely_borrow_by_two_closures(
+ &self,
+ new_loan_span: Span,
+ desc: &str,
+ old_loan_span: Span,
+ old_load_end_span: Option<Span>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0524,
+ "two closures require unique access to {} at the same time",
+ desc,
+ );
+ if old_loan_span == new_loan_span {
+ err.span_label(
+ old_loan_span,
+ "closures are constructed here in different iterations of loop",
+ );
+ } else {
+ err.span_label(old_loan_span, "first closure is constructed here");
+ err.span_label(new_loan_span, "second closure is constructed here");
+ }
+ if let Some(old_load_end_span) = old_load_end_span {
+ err.span_label(old_load_end_span, "borrow from first closure ends here");
+ }
+ err
+ }
+
+ pub(crate) fn cannot_uniquely_borrow_by_one_closure(
+ &self,
+ new_loan_span: Span,
+ container_name: &str,
+ desc_new: &str,
+ opt_via: &str,
+ old_loan_span: Span,
+ noun_old: &str,
+ old_opt_via: &str,
+ previous_end_span: Option<Span>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0500,
+ "closure requires unique access to {} but {} is already borrowed{}",
+ desc_new,
+ noun_old,
+ old_opt_via,
+ );
+ err.span_label(
+ new_loan_span,
+ format!("{} construction occurs here{}", container_name, opt_via),
+ );
+ err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
+ if let Some(previous_end_span) = previous_end_span {
+ err.span_label(previous_end_span, "borrow ends here");
+ }
+ err
+ }
+
+ pub(crate) fn cannot_reborrow_already_uniquely_borrowed(
+ &self,
+ new_loan_span: Span,
+ container_name: &str,
+ desc_new: &str,
+ opt_via: &str,
+ kind_new: &str,
+ old_loan_span: Span,
+ old_opt_via: &str,
+ previous_end_span: Option<Span>,
+ second_borrow_desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ new_loan_span,
+ E0501,
+ "cannot borrow {}{} as {} because previous closure requires unique access",
+ desc_new,
+ opt_via,
+ kind_new,
+ );
+ err.span_label(
+ new_loan_span,
+ format!("{}borrow occurs here{}", second_borrow_desc, opt_via),
+ );
+ err.span_label(
+ old_loan_span,
+ format!("{} construction occurs here{}", container_name, old_opt_via),
+ );
+ if let Some(previous_end_span) = previous_end_span {
+ err.span_label(previous_end_span, "borrow from closure ends here");
+ }
+ err
+ }
+
+ pub(crate) fn cannot_reborrow_already_borrowed(
+ &self,
+ span: Span,
+ desc_new: &str,
+ msg_new: &str,
+ kind_new: &str,
+ old_span: Span,
+ noun_old: &str,
+ kind_old: &str,
+ msg_old: &str,
+ old_load_end_span: Option<Span>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let via =
+ |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 {}{}",
+ desc_new,
+ via(msg_new),
+ kind_new,
+ noun_old,
+ kind_old,
+ via(msg_old),
+ );
+
+ if msg_new == "" {
+ // If `msg_new` is empty, then this isn't a borrow of a union field.
+ err.span_label(span, format!("{} borrow occurs here", kind_new));
+ err.span_label(old_span, format!("{} borrow occurs here", kind_old));
+ } else {
+ // If `msg_new` isn't empty, then this a borrow of a union field.
+ err.span_label(
+ span,
+ format!(
+ "{} borrow of {} -- which overlaps with {} -- occurs here",
+ kind_new, msg_new, msg_old,
+ ),
+ );
+ err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, via(msg_old)));
+ }
+
+ if let Some(old_load_end_span) = old_load_end_span {
+ err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
+ }
+ err
+ }
+
+ pub(crate) fn cannot_assign_to_borrowed(
+ &self,
+ span: Span,
+ borrow_span: Span,
+ desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0506,
+ "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
+ }
+
+ pub(crate) fn cannot_reassign_immutable(
+ &self,
+ span: Span,
+ desc: &str,
+ is_arg: bool,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
+ struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc)
+ }
+
+ pub(crate) fn cannot_assign(
+ &self,
+ span: Span,
+ desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
+ }
+
+ pub(crate) fn cannot_move_out_of(
+ &self,
+ move_from_span: Span,
+ move_from_desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,)
+ }
+
+ /// Signal an error due to an attempt to move out of the interior
+ /// of an array or slice. `is_index` is None when error origin
+ /// didn't capture whether there was an indexing operation or not.
+ pub(crate) fn cannot_move_out_of_interior_noncopy(
+ &self,
+ move_from_span: Span,
+ ty: Ty<'_>,
+ is_index: Option<bool>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let type_name = match (&ty.kind(), is_index) {
+ (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
+ (&ty::Slice(_), _) => "slice",
+ _ => span_bug!(move_from_span, "this path should not cause illegal move"),
+ };
+ let mut err = struct_span_err!(
+ self,
+ move_from_span,
+ E0508,
+ "cannot move out of type `{}`, a non-copy {}",
+ ty,
+ type_name,
+ );
+ err.span_label(move_from_span, "cannot move out of here");
+ err
+ }
+
+ pub(crate) fn cannot_move_out_of_interior_of_drop(
+ &self,
+ move_from_span: Span,
+ container_ty: Ty<'_>,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ move_from_span,
+ E0509,
+ "cannot move out of type `{}`, which implements the `Drop` trait",
+ container_ty,
+ );
+ err.span_label(move_from_span, "cannot move out of here");
+ err
+ }
+
+ pub(crate) fn cannot_act_on_moved_value(
+ &self,
+ use_span: Span,
+ verb: &str,
+ optional_adverb_for_moved: &str,
+ moved_path: Option<String>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default();
+
+ struct_span_err!(
+ self,
+ use_span,
+ E0382,
+ "{} of {}moved value{}",
+ verb,
+ optional_adverb_for_moved,
+ moved_path,
+ )
+ }
+
+ pub(crate) fn cannot_borrow_path_as_mutable_because(
+ &self,
+ span: Span,
+ path: &str,
+ reason: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
+ }
+
+ pub(crate) fn cannot_mutate_in_immutable_section(
+ &self,
+ mutate_span: Span,
+ immutable_span: Span,
+ immutable_place: &str,
+ immutable_section: &str,
+ action: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ mutate_span,
+ E0510,
+ "cannot {} {} in {}",
+ action,
+ immutable_place,
+ immutable_section,
+ );
+ err.span_label(mutate_span, format!("cannot {}", action));
+ err.span_label(immutable_span, format!("value is immutable in {}", immutable_section));
+ err
+ }
+
+ pub(crate) fn cannot_borrow_across_generator_yield(
+ &self,
+ span: Span,
+ yield_span: Span,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0626,
+ "borrow may still be in use when generator yields",
+ );
+ err.span_label(yield_span, "possible yield occurs here");
+ err
+ }
+
+ pub(crate) fn cannot_borrow_across_destructor(
+ &self,
+ borrow_span: Span,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(
+ self,
+ borrow_span,
+ E0713,
+ "borrow may still be in use when destructor runs",
+ )
+ }
+
+ pub(crate) fn path_does_not_live_long_enough(
+ &self,
+ span: Span,
+ path: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
+ }
+
+ pub(crate) fn cannot_return_reference_to_local(
+ &self,
+ span: Span,
+ return_kind: &str,
+ reference_desc: &str,
+ path_desc: &str,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ span,
+ E0515,
+ "cannot {RETURN} {REFERENCE} {LOCAL}",
+ RETURN = return_kind,
+ REFERENCE = reference_desc,
+ LOCAL = path_desc,
+ );
+
+ err.span_label(
+ span,
+ format!("{}s a {} data owned by the current function", return_kind, reference_desc),
+ );
+
+ err
+ }
+
+ pub(crate) fn cannot_capture_in_long_lived_closure(
+ &self,
+ closure_span: Span,
+ closure_kind: &str,
+ borrowed_path: &str,
+ capture_span: Span,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ let mut err = struct_span_err!(
+ self,
+ closure_span,
+ E0373,
+ "{} may outlive the current function, but it borrows {}, which is owned by the current \
+ function",
+ closure_kind,
+ borrowed_path,
+ );
+ err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
+ .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
+ err
+ }
+
+ pub(crate) fn thread_local_value_does_not_live_long_enough(
+ &self,
+ span: Span,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0712, "thread-local variable borrowed past end of function",)
+ }
+
+ pub(crate) fn temporary_value_borrowed_for_too_long(
+ &self,
+ span: Span,
+ ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
+ struct_span_err!(self, span, E0716, "temporary value dropped while borrowed",)
+ }
+
+ #[rustc_lint_diagnostics]
+ pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
+ &self,
+ sp: S,
+ msg: impl Into<DiagnosticMessage>,
+ code: DiagnosticId,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
+ }
+}
+
+pub(crate) fn borrowed_data_escapes_closure<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ escape_span: Span,
+ escapes_from: &str,
+) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ struct_span_err!(
+ tcx.sess,
+ escape_span,
+ E0521,
+ "borrowed data escapes outside of {}",
+ escapes_from,
+ )
+}