1
Fork 0

Tweak "object unsafe" errors

Fix #77598.
This commit is contained in:
Esteban Küber 2020-10-15 17:23:45 -07:00
parent 9832374f6e
commit ae0e3d0511
57 changed files with 720 additions and 442 deletions

View file

@ -2,12 +2,12 @@ use super::ObjectSafetyViolation;
use crate::infer::InferCtxt;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::Span;
use rustc_span::{MultiSpan, Span};
use std::fmt;
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
@ -57,7 +57,8 @@ pub fn report_object_safety_error(
err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
let mut reported_violations = FxHashSet::default();
let mut had_span_label = false;
let mut multi_span = vec![];
let mut messages = vec![];
for violation in violations {
if let ObjectSafetyViolation::SizedSelf(sp) = &violation {
if !sp.is_empty() {
@ -71,31 +72,37 @@ pub fn report_object_safety_error(
let msg = if trait_span.is_none() || spans.is_empty() {
format!("the trait cannot be made into an object because {}", violation.error_msg())
} else {
had_span_label = true;
format!("...because {}", violation.error_msg())
};
if spans.is_empty() {
err.note(&msg);
} else {
for span in spans {
err.span_label(span, &msg);
multi_span.push(span);
messages.push(msg.clone());
}
}
match (trait_span, violation.solution()) {
(Some(_), Some((note, None))) => {
err.help(&note);
}
(Some(_), Some((note, Some((sugg, span))))) => {
err.span_suggestion(span, &note, sugg, Applicability::MachineApplicable);
}
if trait_span.is_some() {
// Only provide the help if its a local trait, otherwise it's not actionable.
_ => {}
violation.solution(&mut err);
}
}
}
if let (Some(trait_span), true) = (trait_span, had_span_label) {
err.span_label(trait_span, "this trait cannot be made into an object...");
let has_multi_span = !multi_span.is_empty();
let mut note_span = MultiSpan::from_spans(multi_span.clone());
if let (Some(trait_span), true) = (trait_span, has_multi_span) {
note_span
.push_span_label(trait_span, "this trait cannot be made into an object...".to_string());
}
for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) {
note_span.push_span_label(span, msg);
}
err.span_note(
note_span,
"for a trait to be \"object safe\" it needs to allow building a vtable to allow the call \
to be resolvable dynamically; for more information visit \
<https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
);
if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
// Avoid emitting error caused by non-existing method (#58734)