use rustc::hir::{AsyncGeneratorKind, GeneratorKind};
use rustc::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
- FakeReadCause, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef,
- ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
+ FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceBase,
+ PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
};
use rustc::ty::{self, Ty};
+use rustc::traits::error_reporting::suggest_constraining_type_param;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::vec::Idx;
use rustc_errors::{Applicability, DiagnosticBuilder};
if let ty::Param(param_ty) = ty.kind {
let tcx = self.infcx.tcx;
let generics = tcx.generics_of(self.mir_def_id);
- let def_id = generics.type_param(¶m_ty, tcx).def_id;
- if let Some(sp) = tcx.hir().span_if_local(def_id) {
- err.span_label(
- sp,
- "consider adding a `Copy` constraint to this type argument",
- );
- }
+ let param = generics.type_param(¶m_ty, tcx);
+ let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
+ suggest_constraining_type_param(
+ generics,
+ &mut err,
+ ¶m.name.as_str(),
+ "Copy",
+ tcx.sess.source_map(),
+ span,
+ );
}
let span = if let Some(local) = place.as_local() {
let decl = &self.body.local_decls[local];
location,
borrow,
None,
- ).add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", Some(borrow_span));
+ ).add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ Some(borrow_span),
+ );
err.buffer(&mut self.errors_buffer);
}
});
self.explain_why_borrow_contains_point(location, borrow, None)
- .add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ .add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err
}
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
self.body,
+ &self.local_names,
&mut err,
first_borrow_desc,
None,
projection: root_place_projection,
}, borrow_span));
+ if let PlaceBase::Local(local) = borrow.borrowed_place.base {
+ if self.body.local_decls[local].is_ref_to_thread_local() {
+ let err = self.report_thread_local_value_does_not_live_long_enough(
+ drop_span,
+ borrow_span,
+ );
+ err.buffer(&mut self.errors_buffer);
+ return;
+ }
+ };
+
if let StorageDeadOrDrop::Destructor(dropped_ty) =
self.classify_drop_access_kind(borrow.borrowed_place.as_ref())
{
explanation
);
let err = match (place_desc, explanation) {
- (Some(_), _) if self.is_place_thread_local(root_place) => {
- self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span)
- }
// If the outlives constraint comes from inside the closure,
// for example:
//
explanation.add_explanation_to_diagnostic(
self.infcx.tcx,
self.body,
+ &self.local_names,
&mut err,
"",
None,
);
explanation.add_explanation_to_diagnostic(
- self.infcx.tcx, self.body, &mut err, "", None);
+ self.infcx.tcx, self.body, &self.local_names, &mut err, "", None);
}
err
_ => {}
}
- explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ explanation.add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err.buffer(&mut self.errors_buffer);
}
}
_ => {}
}
- explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ explanation.add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
let within = if borrow_spans.for_generator() {
" by generator"
);
self.explain_why_borrow_contains_point(location, loan, None)
- .add_explanation_to_diagnostic(self.infcx.tcx, self.body, &mut err, "", None);
+ .add_explanation_to_diagnostic(
+ self.infcx.tcx,
+ self.body,
+ &self.local_names,
+ &mut err,
+ "",
+ None,
+ );
err.buffer(&mut self.errors_buffer);
}
assigned_span: Span,
err_place: &Place<'tcx>,
) {
- let (from_arg, local_decl) = if let Some(local) = err_place.as_local() {
- if let LocalKind::Arg = self.body.local_kind(local) {
- (true, Some(&self.body.local_decls[local]))
- } else {
- (false, Some(&self.body.local_decls[local]))
- }
- } else {
- (false, None)
+ let (from_arg, local_decl, local_name) = match err_place.as_local() {
+ Some(local) => (
+ self.body.local_kind(local) == LocalKind::Arg,
+ Some(&self.body.local_decls[local]),
+ self.local_names[local],
+ ),
+ None => (false, None, None),
};
// If root local is initialized immediately (everything apart from let
// place being assigned later.
let (place_description, assigned_span) = match local_decl {
Some(LocalDecl {
- is_user_variable: Some(ClearCrossCrate::Clear),
+ local_info: LocalInfo::User(ClearCrossCrate::Clear),
..
})
| Some(LocalDecl {
- is_user_variable:
- Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
- opt_match_place: None,
- ..
- }))),
+ local_info: LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+ opt_match_place: None,
+ ..
+ }))),
+ ..
+ })
+ | Some(LocalDecl {
+ local_info: LocalInfo::StaticRef { .. },
..
})
| Some(LocalDecl {
- is_user_variable: None,
+ local_info: LocalInfo::Other,
..
})
| None => (self.describe_place(place.as_ref()), assigned_span),
}
}
if let Some(decl) = local_decl {
- if let Some(name) = decl.name {
+ if let Some(name) = local_name {
if decl.can_be_made_mutable() {
err.span_suggestion(
decl.source_info.span,