]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_infer/src/traits/error_reporting/mod.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / compiler / rustc_infer / src / traits / error_reporting / mod.rs
1 use super::ObjectSafetyViolation;
2
3 use crate::infer::InferCtxt;
4 use rustc_data_structures::fx::FxHashSet;
5 use rustc_errors::{struct_span_err, DiagnosticBuilder};
6 use rustc_hir as hir;
7 use rustc_hir::def_id::DefId;
8 use rustc_middle::ty::TyCtxt;
9 use rustc_span::symbol::Symbol;
10 use rustc_span::{MultiSpan, Span};
11 use std::fmt;
12
13 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
14 pub fn report_extra_impl_obligation(
15 &self,
16 error_span: Span,
17 item_name: Symbol,
18 _impl_item_def_id: DefId,
19 trait_item_def_id: DefId,
20 requirement: &dyn fmt::Display,
21 ) -> DiagnosticBuilder<'tcx> {
22 let msg = "impl has stricter requirements than trait";
23 let sp = self.tcx.sess.source_map().guess_head_span(error_span);
24
25 let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
26
27 if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
28 let span = self.tcx.sess.source_map().guess_head_span(trait_item_span);
29 err.span_label(span, format!("definition of `{}` from trait", item_name));
30 }
31
32 err.span_label(sp, format!("impl has extra requirement {}", requirement));
33
34 err
35 }
36 }
37
38 pub fn report_object_safety_error(
39 tcx: TyCtxt<'tcx>,
40 span: Span,
41 trait_def_id: DefId,
42 violations: &[ObjectSafetyViolation],
43 ) -> DiagnosticBuilder<'tcx> {
44 let trait_str = tcx.def_path_str(trait_def_id);
45 let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node {
46 hir::Node::Item(item) => Some(item.ident.span),
47 _ => None,
48 });
49 let span = tcx.sess.source_map().guess_head_span(span);
50 let mut err = struct_span_err!(
51 tcx.sess,
52 span,
53 E0038,
54 "the trait `{}` cannot be made into an object",
55 trait_str
56 );
57 err.span_label(span, format!("`{}` cannot be made into an object", trait_str));
58
59 let mut reported_violations = FxHashSet::default();
60 let mut multi_span = vec![];
61 let mut messages = vec![];
62 for violation in violations {
63 if let ObjectSafetyViolation::SizedSelf(sp) = &violation {
64 if !sp.is_empty() {
65 // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
66 // with a `Span`.
67 reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
68 }
69 }
70 if reported_violations.insert(violation.clone()) {
71 let spans = violation.spans();
72 let msg = if trait_span.is_none() || spans.is_empty() {
73 format!("the trait cannot be made into an object because {}", violation.error_msg())
74 } else {
75 format!("...because {}", violation.error_msg())
76 };
77 if spans.is_empty() {
78 err.note(&msg);
79 } else {
80 for span in spans {
81 multi_span.push(span);
82 messages.push(msg.clone());
83 }
84 }
85 if trait_span.is_some() {
86 // Only provide the help if its a local trait, otherwise it's not actionable.
87 violation.solution(&mut err);
88 }
89 }
90 }
91 let has_multi_span = !multi_span.is_empty();
92 let mut note_span = MultiSpan::from_spans(multi_span.clone());
93 if let (Some(trait_span), true) = (trait_span, has_multi_span) {
94 note_span
95 .push_span_label(trait_span, "this trait cannot be made into an object...".to_string());
96 }
97 for (span, msg) in multi_span.into_iter().zip(messages.into_iter()) {
98 note_span.push_span_label(span, msg);
99 }
100 err.span_note(
101 note_span,
102 "for a trait to be \"object safe\" it needs to allow building a vtable to allow the call \
103 to be resolvable dynamically; for more information visit \
104 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
105 );
106
107 if tcx.sess.trait_methods_not_found.borrow().iter().any(|full_span| full_span.contains(span)) {
108 // Avoid emitting error caused by non-existing method (#58734)
109 err.cancel();
110 }
111
112 err
113 }