Skip to content

Commit 6b85f07

Browse files
committed
Small tweaks to the linting code for bare trait object types
1 parent b3df0d7 commit 6b85f07

File tree

2 files changed

+79
-72
lines changed

2 files changed

+79
-72
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

+77-70
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,83 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa
99
use super::HirTyLowerer;
1010

1111
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12+
/// Prohibit or lint against *bare* trait object types depending on the edition.
13+
///
14+
/// *Bare* trait object types are ones that aren't preceeded by the keyword `dyn`.
15+
/// In edition 2021 and onward we emit a hard error for them.
16+
pub(super) fn prohibit_or_lint_bare_trait_object_ty(
17+
&self,
18+
self_ty: &hir::Ty<'_>,
19+
in_path: bool,
20+
) {
21+
let tcx = self.tcx();
22+
23+
let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
24+
self_ty.kind
25+
else {
26+
return;
27+
};
28+
29+
let needs_bracket = in_path
30+
&& !tcx
31+
.sess
32+
.source_map()
33+
.span_to_prev_source(self_ty.span)
34+
.ok()
35+
.is_some_and(|s| s.trim_end().ends_with('<'));
36+
37+
let is_global = poly_trait_ref.trait_ref.path.is_global();
38+
39+
let mut sugg = vec![(
40+
self_ty.span.shrink_to_lo(),
41+
format!(
42+
"{}dyn {}",
43+
if needs_bracket { "<" } else { "" },
44+
if is_global { "(" } else { "" },
45+
),
46+
)];
47+
48+
if is_global || needs_bracket {
49+
sugg.push((
50+
self_ty.span.shrink_to_hi(),
51+
format!(
52+
"{}{}",
53+
if is_global { ")" } else { "" },
54+
if needs_bracket { ">" } else { "" },
55+
),
56+
));
57+
}
58+
59+
if self_ty.span.edition().at_least_rust_2021() {
60+
let msg = "trait objects must include the `dyn` keyword";
61+
let label = "add `dyn` keyword before this trait";
62+
let mut diag =
63+
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
64+
if self_ty.span.can_be_used_for_suggestions()
65+
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
66+
{
67+
diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable);
68+
}
69+
// Check if the impl trait that we are considering is an impl of a local trait.
70+
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
71+
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
72+
} else {
73+
let msg = "trait objects without an explicit `dyn` are deprecated";
74+
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
75+
if self_ty.span.can_be_used_for_suggestions() {
76+
lint.multipart_suggestion_verbose(
77+
"if this is an object-safe trait, use `dyn`",
78+
sugg,
79+
Applicability::MachineApplicable,
80+
);
81+
}
82+
self.maybe_suggest_blanket_trait_impl(self_ty, lint);
83+
});
84+
}
85+
}
86+
1287
/// Make sure that we are in the condition to suggest the blanket implementation.
13-
pub(super) fn maybe_lint_blanket_trait_impl<G: EmissionGuarantee>(
88+
fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
1489
&self,
1590
self_ty: &hir::Ty<'_>,
1691
diag: &mut Diag<'_, G>,
@@ -75,7 +150,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
75150
}
76151

77152
/// Make sure that we are in the condition to suggest `impl Trait`.
78-
fn maybe_lint_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
153+
fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool {
79154
let tcx = self.tcx();
80155
let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
81156
let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) {
@@ -185,72 +260,4 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
185260
}
186261
false
187262
}
188-
189-
pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) {
190-
let tcx = self.tcx();
191-
if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) =
192-
self_ty.kind
193-
{
194-
let needs_bracket = in_path
195-
&& !tcx
196-
.sess
197-
.source_map()
198-
.span_to_prev_source(self_ty.span)
199-
.ok()
200-
.is_some_and(|s| s.trim_end().ends_with('<'));
201-
202-
let is_global = poly_trait_ref.trait_ref.path.is_global();
203-
204-
let mut sugg = Vec::from_iter([(
205-
self_ty.span.shrink_to_lo(),
206-
format!(
207-
"{}dyn {}",
208-
if needs_bracket { "<" } else { "" },
209-
if is_global { "(" } else { "" },
210-
),
211-
)]);
212-
213-
if is_global || needs_bracket {
214-
sugg.push((
215-
self_ty.span.shrink_to_hi(),
216-
format!(
217-
"{}{}",
218-
if is_global { ")" } else { "" },
219-
if needs_bracket { ">" } else { "" },
220-
),
221-
));
222-
}
223-
224-
if self_ty.span.edition().at_least_rust_2021() {
225-
let msg = "trait objects must include the `dyn` keyword";
226-
let label = "add `dyn` keyword before this trait";
227-
let mut diag =
228-
rustc_errors::struct_span_code_err!(tcx.dcx(), self_ty.span, E0782, "{}", msg);
229-
if self_ty.span.can_be_used_for_suggestions()
230-
&& !self.maybe_lint_impl_trait(self_ty, &mut diag)
231-
{
232-
diag.multipart_suggestion_verbose(
233-
label,
234-
sugg,
235-
Applicability::MachineApplicable,
236-
);
237-
}
238-
// check if the impl trait that we are considering is a impl of a local trait
239-
self.maybe_lint_blanket_trait_impl(self_ty, &mut diag);
240-
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
241-
} else {
242-
let msg = "trait objects without an explicit `dyn` are deprecated";
243-
tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
244-
if self_ty.span.can_be_used_for_suggestions() {
245-
lint.multipart_suggestion_verbose(
246-
"if this is an object-safe trait, use `dyn`",
247-
sugg,
248-
Applicability::MachineApplicable,
249-
);
250-
}
251-
self.maybe_lint_blanket_trait_impl(self_ty, lint);
252-
});
253-
}
254-
}
255-
}
256263
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2341,12 +2341,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
23412341
)
23422342
}
23432343
hir::TyKind::TraitObject(bounds, lifetime, repr) => {
2344-
self.maybe_lint_bare_trait(hir_ty, in_path);
2344+
self.prohibit_or_lint_bare_trait_object_ty(hir_ty, in_path);
2345+
23452346
let repr = match repr {
23462347
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
23472348
TraitObjectSyntax::DynStar => ty::DynStar,
23482349
};
2349-
23502350
self.lower_trait_object_ty(
23512351
hir_ty.span,
23522352
hir_ty.hir_id,

0 commit comments

Comments
 (0)