1 use rustc_ast
::TraitObjectSyntax
;
2 use rustc_errors
::{Diagnostic, StashKey}
;
4 use rustc_lint_defs
::{builtin::BARE_TRAIT_OBJECTS, Applicability}
;
5 use rustc_trait_selection
::traits
::error_reporting
::suggestions
::NextTypeParamName
;
9 impl<'o
, 'tcx
> dyn AstConv
<'tcx
> + 'o
{
10 /// Make sure that we are in the condition to suggest the blanket implementation.
11 pub(super) fn maybe_lint_blanket_trait_impl(
13 self_ty
: &hir
::Ty
<'_
>,
14 diag
: &mut Diagnostic
,
17 let parent_id
= tcx
.hir().get_parent_item(self_ty
.hir_id
).def_id
;
18 if let hir
::Node
::Item(hir
::Item
{
20 hir
::ItemKind
::Impl(hir
::Impl
{
21 self_ty
: impl_self_ty
, of_trait
: Some(of_trait_ref
), generics
, ..
24 }) = tcx
.hir().get_by_def_id(parent_id
) && self_ty
.hir_id
== impl_self_ty
.hir_id
26 if !of_trait_ref
.trait_def_id().is_some_and(|def_id
| def_id
.is_local()) {
29 let of_trait_span
= of_trait_ref
.path
.span
;
30 // make sure that we are not calling unwrap to abort during the compilation
31 let Ok(impl_trait_name
) = tcx
.sess
.source_map().span_to_snippet(self_ty
.span
) else { return; }
;
32 let Ok(of_trait_name
) = tcx
.sess
.source_map().span_to_snippet(of_trait_span
) else { return; }
;
33 // check if the trait has generics, to make a correct suggestion
34 let param_name
= generics
.params
.next_type_param_name(None
);
36 let add_generic_sugg
= if let Some(span
) = generics
.span_for_param_suggestion() {
37 (span
, format
!(", {param_name}: {impl_trait_name}"))
39 (generics
.span
, format
!("<{param_name}: {impl_trait_name}>"))
41 diag
.multipart_suggestion(
42 format
!("alternatively use a blanket \
43 implementation to implement `{of_trait_name}` for \
44 all types that also implement `{impl_trait_name}`"),
46 (self_ty
.span
, param_name
),
49 Applicability
::MaybeIncorrect
,
54 pub(super) fn maybe_lint_bare_trait(&self, self_ty
: &hir
::Ty
<'_
>, in_path
: bool
) {
56 if let hir
::TyKind
::TraitObject([poly_trait_ref
, ..], _
, TraitObjectSyntax
::None
) =
59 let needs_bracket
= in_path
63 .span_to_prev_source(self_ty
.span
)
65 .is_some_and(|s
| s
.trim_end().ends_with('
<'
));
67 let is_global
= poly_trait_ref
.trait_ref
.path
.is_global();
69 let mut sugg
= Vec
::from_iter([(
70 self_ty
.span
.shrink_to_lo(),
73 if needs_bracket { "<" }
else { "" }
,
74 if is_global { "(" }
else { "" }
,
78 if is_global
|| needs_bracket
{
80 self_ty
.span
.shrink_to_hi(),
83 if is_global { ")" }
else { "" }
,
84 if needs_bracket { ">" }
else { "" }
,
89 if self_ty
.span
.edition().at_least_rust_2021() {
90 let msg
= "trait objects must include the `dyn` keyword";
91 let label
= "add `dyn` keyword before this trait";
93 rustc_errors
::struct_span_err
!(tcx
.sess
, self_ty
.span
, E0782
, "{}", msg
);
94 if self_ty
.span
.can_be_used_for_suggestions() {
95 diag
.multipart_suggestion_verbose(
98 Applicability
::MachineApplicable
,
101 // check if the impl trait that we are considering is a impl of a local trait
102 self.maybe_lint_blanket_trait_impl(&self_ty
, &mut diag
);
103 diag
.stash(self_ty
.span
, StashKey
::TraitMissingMethod
);
105 let msg
= "trait objects without an explicit `dyn` are deprecated";
106 tcx
.struct_span_lint_hir(
112 lint
.multipart_suggestion_verbose(
115 Applicability
::MachineApplicable
,
117 self.maybe_lint_blanket_trait_impl(&self_ty
, lint
);