1 use super::ObjectSafetyViolation
;
3 use crate::infer
::InferCtxt
;
4 use rustc_data_structures
::fx
::FxHashSet
;
5 use rustc_errors
::{struct_span_err, DiagnosticBuilder}
;
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}
;
13 impl<'a
, 'tcx
> InferCtxt
<'a
, 'tcx
> {
14 pub fn report_extra_impl_obligation(
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
);
25 let mut err
= struct_span_err
!(self.tcx
.sess
, sp
, E0276
, "{}", msg
);
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
));
32 err
.span_label(sp
, format
!("impl has extra requirement {}", requirement
));
38 pub fn report_object_safety_error(
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
),
49 let span
= tcx
.sess
.source_map().guess_head_span(span
);
50 let mut err
= struct_span_err
!(
54 "the trait `{}` cannot be made into an object",
57 err
.span_label(span
, format
!("`{}` cannot be made into an object", trait_str
));
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
{
65 // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
67 reported_violations
.insert(ObjectSafetyViolation
::SizedSelf(vec
![].into()));
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())
75 format
!("...because {}", violation
.error_msg())
81 multi_span
.push(span
);
82 messages
.push(msg
.clone());
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
);
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
) {
95 .push_span_label(trait_span
, "this trait cannot be made into an object...".to_string());
97 for (span
, msg
) in multi_span
.into_iter().zip(messages
.into_iter()) {
98 note_span
.push_span_label(span
, msg
);
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>",
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)