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