@@ -9,8 +9,83 @@ use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamNa
99use super :: AstConv ;
1010
1111impl < ' o , ' tcx > dyn AstConv < ' tcx > + ' o {
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<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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}
0 commit comments