1
1
use rustc_ast:: TraitObjectSyntax ;
2
2
use rustc_errors:: codes:: * ;
3
- use rustc_errors:: { Diag , EmissionGuarantee , StashKey } ;
3
+ use rustc_errors:: { Diag , EmissionGuarantee , ErrorGuaranteed , StashKey , Suggestions } ;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def:: { DefKind , Res } ;
6
6
use rustc_lint_defs:: Applicability ;
@@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
15
15
///
16
16
/// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
17
17
/// In edition 2021 and onward we emit a hard error for them.
18
- pub ( super ) fn prohibit_or_lint_bare_trait_object_ty ( & self , self_ty : & hir:: Ty < ' _ > ) {
18
+ pub ( super ) fn prohibit_or_lint_bare_trait_object_ty (
19
+ & self ,
20
+ self_ty : & hir:: Ty < ' _ > ,
21
+ ) -> Option < ErrorGuaranteed > {
19
22
let tcx = self . tcx ( ) ;
20
23
21
24
let hir:: TyKind :: TraitObject ( [ poly_trait_ref, ..] , _, TraitObjectSyntax :: None ) =
22
25
self_ty. kind
23
26
else {
24
- return ;
27
+ return None ;
25
28
} ;
26
29
27
30
let in_path = match tcx. parent_hir_node ( self_ty. hir_id ) {
@@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
70
73
}
71
74
72
75
if self_ty. span . edition ( ) . at_least_rust_2021 ( ) {
73
- let msg = "trait objects must include the `dyn` keyword " ;
74
- let label = "add `dyn` keyword before this trait" ;
76
+ let msg = "expected a type, found a trait " ;
77
+ let label = "you can add the `dyn` keyword if you want a trait object " ;
75
78
let mut diag =
76
79
rustc_errors:: struct_span_code_err!( self . dcx( ) , self_ty. span, E0782 , "{}" , msg) ;
77
80
if self_ty. span . can_be_used_for_suggestions ( )
@@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
83
86
// Check if the impl trait that we are considering is an impl of a local trait.
84
87
self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
85
88
self . maybe_suggest_assoc_ty_bound ( self_ty, & mut diag) ;
86
- diag. stash ( self_ty. span , StashKey :: TraitMissingMethod ) ;
89
+ // In case there is an associate type with the same name
90
+ // Add the suggestion to this error
91
+ if let Some ( mut sugg) =
92
+ tcx. dcx ( ) . steal_non_err ( self_ty. span , StashKey :: AssociatedTypeSuggestion )
93
+ && let Suggestions :: Enabled ( ref mut s1) = diag. suggestions
94
+ && let Suggestions :: Enabled ( ref mut s2) = sugg. suggestions
95
+ {
96
+ s1. append ( s2) ;
97
+ sugg. cancel ( ) ;
98
+ }
99
+ diag. stash ( self_ty. span , StashKey :: TraitMissingMethod )
87
100
} else {
88
101
tcx. node_span_lint ( BARE_TRAIT_OBJECTS , self_ty. hir_id , self_ty. span , |lint| {
89
102
lint. primary_message ( "trait objects without an explicit `dyn` are deprecated" ) ;
@@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
96
109
}
97
110
self . maybe_suggest_blanket_trait_impl ( self_ty, lint) ;
98
111
} ) ;
112
+ None
99
113
}
100
114
}
101
115
@@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
174
188
// 1. Independent functions
175
189
// 2. Functions inside trait blocks
176
190
// 3. Functions inside impl blocks
177
- let ( sig, generics, owner ) = match tcx. hir_node_by_def_id ( parent_id) {
191
+ let ( sig, generics) = match tcx. hir_node_by_def_id ( parent_id) {
178
192
hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Fn ( sig, generics, _) , .. } ) => {
179
- ( sig, generics, None )
193
+ ( sig, generics)
180
194
}
181
195
hir:: Node :: TraitItem ( hir:: TraitItem {
182
196
kind : hir:: TraitItemKind :: Fn ( sig, _) ,
183
197
generics,
184
- owner_id,
185
198
..
186
- } ) => ( sig, generics, Some ( tcx . parent ( owner_id . to_def_id ( ) ) ) ) ,
199
+ } ) => ( sig, generics) ,
187
200
hir:: Node :: ImplItem ( hir:: ImplItem {
188
201
kind : hir:: ImplItemKind :: Fn ( sig, _) ,
189
202
generics,
190
- owner_id,
191
203
..
192
- } ) => ( sig, generics, Some ( tcx . parent ( owner_id . to_def_id ( ) ) ) ) ,
204
+ } ) => ( sig, generics) ,
193
205
_ => return false ,
194
206
} ;
195
207
let Ok ( trait_name) = tcx. sess . source_map ( ) . span_to_snippet ( self_ty. span ) else {
196
208
return false ;
197
209
} ;
198
210
let impl_sugg = vec ! [ ( self_ty. span. shrink_to_lo( ) , "impl " . to_string( ) ) ] ;
199
- let mut is_downgradable = true ;
200
-
201
211
// Check if trait object is safe for suggesting dynamic dispatch.
202
212
let is_dyn_compatible = match self_ty. kind {
203
213
hir:: TyKind :: TraitObject ( objects, ..) => {
204
214
objects. iter ( ) . all ( |( o, _) | match o. trait_ref . path . res {
205
- Res :: Def ( DefKind :: Trait , id) => {
206
- if Some ( id) == owner {
207
- // For recursive traits, don't downgrade the error. (#119652)
208
- is_downgradable = false ;
209
- }
210
- tcx. is_dyn_compatible ( id)
211
- }
215
+ Res :: Def ( DefKind :: Trait , id) => tcx. is_dyn_compatible ( id) ,
212
216
_ => false ,
213
217
} )
214
218
}
@@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
255
259
suggestion,
256
260
Applicability :: MachineApplicable ,
257
261
) ;
258
- } else if is_downgradable {
259
- // We'll emit the dyn-compatibility error already, with a structured suggestion.
260
- diag. downgrade_to_delayed_bug ( ) ;
261
262
}
262
263
return true ;
263
264
}
@@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
281
282
) ;
282
283
if !is_dyn_compatible {
283
284
diag. note ( format ! ( "`{trait_name}` it is dyn-incompatible, so it can't be `dyn`" ) ) ;
284
- if is_downgradable {
285
- // We'll emit the dyn-compatibility error already, with a structured suggestion.
286
- diag. downgrade_to_delayed_bug ( ) ;
287
- }
288
285
} else {
289
286
// No ampersand in suggestion if it's borrowed already
290
287
let ( dyn_str, paren_dyn_str) =
0 commit comments