use rustc::ty::{self, Ty, TyCtxt}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; use syntax_pos::{MultiSpan, Span}; pub(crate) trait BorrowckErrors<'cx>: Sized + Copy { fn struct_span_err_with_code>( self, sp: S, msg: &str, code: DiagnosticId, ) -> DiagnosticBuilder<'cx>; fn struct_span_err>(self, sp: S, msg: &str) -> DiagnosticBuilder<'cx>; 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, ) } fn cannot_use_when_mutably_borrowed( self, span: Span, desc: &str, borrow_span: Span, borrow_desc: &str, ) -> DiagnosticBuilder<'cx> { 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 } fn cannot_act_on_uninitialized_variable( self, span: Span, verb: &str, desc: &str, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, span, E0381, "{} of possibly uninitialized variable: `{}`", verb, desc, ) } 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, ) -> DiagnosticBuilder<'cx> { let via = |msg: &str| if msg.is_empty() { msg.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!( "mutable borrow starts here in previous \ iteration of loop{}", 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 } fn cannot_uniquely_borrow_by_two_closures( self, new_loan_span: Span, desc: &str, old_loan_span: Span, old_load_end_span: Option, ) -> DiagnosticBuilder<'cx> { 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 } 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, ) -> DiagnosticBuilder<'cx> { 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 } 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, second_borrow_desc: &str, ) -> DiagnosticBuilder<'cx> { 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 } 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, ) -> DiagnosticBuilder<'cx> { let via = |msg: &str| if msg.is_empty() { msg.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 } fn cannot_assign_to_borrowed( self, span: Span, borrow_span: Span, desc: &str, ) -> DiagnosticBuilder<'cx> { 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 } fn cannot_reassign_immutable( self, span: Span, desc: &str, 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, ) } fn cannot_assign(self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> { struct_span_err!(self, span, E0594, "cannot assign to {}", desc) } fn cannot_move_out_of( self, move_from_span: Span, move_from_desc: &str, ) -> DiagnosticBuilder<'cx> { 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. fn cannot_move_out_of_interior_noncopy( self, move_from_span: Span, ty: Ty<'_>, is_index: Option, ) -> DiagnosticBuilder<'cx> { let type_name = match (&ty.sty, 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 } fn cannot_move_out_of_interior_of_drop( self, move_from_span: Span, container_ty: Ty<'_>, ) -> DiagnosticBuilder<'cx> { 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 } fn cannot_act_on_moved_value( self, use_span: Span, verb: &str, optional_adverb_for_moved: &str, moved_path: Option, ) -> DiagnosticBuilder<'cx> { 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, ) } fn cannot_borrow_path_as_mutable_because( self, span: Span, path: &str, reason: &str, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, span, E0596, "cannot borrow {} as mutable{}", path, reason, ) } fn cannot_mutate_in_match_guard( self, mutate_span: Span, match_span: Span, match_place: &str, action: &str, ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, mutate_span, E0510, "cannot {} `{}` in match guard", action, match_place, ); err.span_label(mutate_span, format!("cannot {}", action)); err.span_label(match_span, String::from("value is immutable in match guard")); err } fn cannot_borrow_across_generator_yield( self, span: Span, yield_span: Span, ) -> DiagnosticBuilder<'cx> { 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 } fn cannot_borrow_across_destructor( self, borrow_span: Span, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, borrow_span, E0713, "borrow may still be in use when destructor runs", ) } fn path_does_not_live_long_enough( self, span: Span, path: &str, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, span, E0597, "{} does not live long enough", path, ) } fn cannot_return_reference_to_local( self, span: Span, return_kind: &str, reference_desc: &str, path_desc: &str, ) -> DiagnosticBuilder<'cx> { 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 } fn cannot_capture_in_long_lived_closure( self, closure_span: Span, borrowed_path: &str, capture_span: Span, ) -> DiagnosticBuilder<'cx> { let mut err = struct_span_err!( self, closure_span, E0373, "closure may outlive the current function, \ but it borrows {}, \ which is owned by the current function", 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 } fn borrowed_data_escapes_closure( self, escape_span: Span, escapes_from: &str, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, escape_span, E0521, "borrowed data escapes outside of {}", escapes_from, ) } fn thread_local_value_does_not_live_long_enough( self, span: Span, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, span, E0712, "thread-local variable borrowed past end of function", ) } fn temporary_value_borrowed_for_too_long( self, span: Span, ) -> DiagnosticBuilder<'cx> { struct_span_err!( self, span, E0716, "temporary value dropped while borrowed", ) } } impl BorrowckErrors<'tcx> for TyCtxt<'tcx> { fn struct_span_err_with_code>( self, sp: S, msg: &str, code: DiagnosticId, ) -> DiagnosticBuilder<'tcx> { self.sess.struct_span_err_with_code(sp, msg, code) } fn struct_span_err>(self, sp: S, msg: &str) -> DiagnosticBuilder<'tcx> { self.sess.struct_span_err(sp, msg) } }