]>
Commit | Line | Data |
---|---|---|
ba9703b0 | 1 | use super::ObjectSafetyViolation; |
dfeec247 | 2 | |
ba9703b0 | 3 | use crate::infer::InferCtxt; |
ba9703b0 | 4 | use rustc_data_structures::fx::FxHashSet; |
5e7ed085 | 5 | use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed}; |
dfeec247 | 6 | use rustc_hir as hir; |
5e7ed085 | 7 | use rustc_hir::def_id::{DefId, LocalDefId}; |
ba9703b0 | 8 | use rustc_middle::ty::TyCtxt; |
29967ef6 | 9 | use rustc_span::{MultiSpan, Span}; |
dfeec247 | 10 | use std::fmt; |
cdc7bbd5 | 11 | use std::iter; |
dfeec247 XL |
12 | |
13 | impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
dfeec247 XL |
14 | pub fn report_extra_impl_obligation( |
15 | &self, | |
16 | error_span: Span, | |
5e7ed085 | 17 | impl_item_def_id: LocalDefId, |
dfeec247 XL |
18 | trait_item_def_id: DefId, |
19 | requirement: &dyn fmt::Display, | |
5e7ed085 | 20 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
dfeec247 | 21 | let msg = "impl has stricter requirements than trait"; |
ba9703b0 | 22 | let sp = self.tcx.sess.source_map().guess_head_span(error_span); |
dfeec247 XL |
23 | |
24 | let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); | |
25 | ||
26 | if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { | |
ba9703b0 | 27 | let span = self.tcx.sess.source_map().guess_head_span(trait_item_span); |
5e7ed085 | 28 | let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); |
dfeec247 XL |
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 | } | |
dfeec247 XL |
36 | } |
37 | ||
a2a8927a | 38 | pub fn report_object_safety_error<'tcx>( |
dfeec247 XL |
39 | tcx: TyCtxt<'tcx>, |
40 | span: Span, | |
41 | trait_def_id: DefId, | |
ba9703b0 | 42 | violations: &[ObjectSafetyViolation], |
5e7ed085 | 43 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { |
dfeec247 | 44 | let trait_str = tcx.def_path_str(trait_def_id); |
74b04a01 XL |
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 | }); | |
ba9703b0 | 49 | let span = tcx.sess.source_map().guess_head_span(span); |
dfeec247 XL |
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 | ); | |
29967ef6 | 57 | err.span_label(span, format!("`{}` cannot be made into an object", trait_str)); |
dfeec247 XL |
58 | |
59 | let mut reported_violations = FxHashSet::default(); | |
29967ef6 XL |
60 | let mut multi_span = vec![]; |
61 | let mut messages = vec![]; | |
dfeec247 | 62 | for violation in violations { |
5e7ed085 FG |
63 | if let ObjectSafetyViolation::SizedSelf(sp) = &violation && !sp.is_empty() { |
64 | // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations | |
65 | // with a `Span`. | |
66 | reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into())); | |
74b04a01 | 67 | } |
dfeec247 | 68 | if reported_violations.insert(violation.clone()) { |
74b04a01 XL |
69 | let spans = violation.spans(); |
70 | let msg = if trait_span.is_none() || spans.is_empty() { | |
71 | format!("the trait cannot be made into an object because {}", violation.error_msg()) | |
72 | } else { | |
74b04a01 | 73 | format!("...because {}", violation.error_msg()) |
dfeec247 | 74 | }; |
74b04a01 XL |
75 | if spans.is_empty() { |
76 | err.note(&msg); | |
77 | } else { | |
78 | for span in spans { | |
29967ef6 XL |
79 | multi_span.push(span); |
80 | messages.push(msg.clone()); | |
74b04a01 XL |
81 | } |
82 | } | |
dfeec247 XL |
83 | } |
84 | } | |
29967ef6 XL |
85 | let has_multi_span = !multi_span.is_empty(); |
86 | let mut note_span = MultiSpan::from_spans(multi_span.clone()); | |
87 | if let (Some(trait_span), true) = (trait_span, has_multi_span) { | |
88 | note_span | |
89 | .push_span_label(trait_span, "this trait cannot be made into an object...".to_string()); | |
74b04a01 | 90 | } |
cdc7bbd5 | 91 | for (span, msg) in iter::zip(multi_span, messages) { |
29967ef6 XL |
92 | note_span.push_span_label(span, msg); |
93 | } | |
94 | err.span_note( | |
95 | note_span, | |
96 | "for a trait to be \"object safe\" it needs to allow building a vtable to allow the call \ | |
97 | to be resolvable dynamically; for more information visit \ | |
98 | <https://doc.rust-lang.org/reference/items/traits.html#object-safety>", | |
99 | ); | |
c295e0f8 XL |
100 | if trait_span.is_some() { |
101 | let mut reported_violations: Vec<_> = reported_violations.into_iter().collect(); | |
102 | reported_violations.sort(); | |
103 | for violation in reported_violations { | |
104 | // Only provide the help if its a local trait, otherwise it's not actionable. | |
105 | violation.solution(&mut err); | |
106 | } | |
107 | } | |
dfeec247 XL |
108 | err |
109 | } |