11use rustc_ast:: TraitObjectSyntax ;
22use rustc_errors:: codes:: * ;
3- use rustc_errors:: { Diag , EmissionGuarantee , StashKey } ;
3+ use rustc_errors:: { Diag , EmissionGuarantee , ErrorGuaranteed , StashKey , Suggestions } ;
44use rustc_hir as hir;
55use rustc_hir:: def:: { DefKind , Res } ;
66use rustc_lint_defs:: Applicability ;
@@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1515 ///
1616 /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`.
1717 /// 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 > {
1922 let tcx = self . tcx ( ) ;
2023
2124 let hir:: TyKind :: TraitObject ( [ poly_trait_ref, ..] , _, TraitObjectSyntax :: None ) =
2225 self_ty. kind
2326 else {
24- return ;
27+ return None ;
2528 } ;
2629
2730 let in_path = match tcx. parent_hir_node ( self_ty. hir_id ) {
@@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7073 }
7174
7275 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 " ;
7578 let mut diag =
7679 rustc_errors:: struct_span_code_err!( self . dcx( ) , self_ty. span, E0782 , "{}" , msg) ;
7780 if self_ty. span . can_be_used_for_suggestions ( )
@@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8386 // Check if the impl trait that we are considering is an impl of a local trait.
8487 self . maybe_suggest_blanket_trait_impl ( self_ty, & mut diag) ;
8588 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 )
87100 } else {
88101 tcx. node_span_lint ( BARE_TRAIT_OBJECTS , self_ty. hir_id , self_ty. span , |lint| {
89102 lint. primary_message ( "trait objects without an explicit `dyn` are deprecated" ) ;
@@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
96109 }
97110 self . maybe_suggest_blanket_trait_impl ( self_ty, lint) ;
98111 } ) ;
112+ None
99113 }
100114 }
101115
@@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
174188 // 1. Independent functions
175189 // 2. Functions inside trait blocks
176190 // 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) {
178192 hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Fn ( sig, generics, _) , .. } ) => {
179- ( sig, generics, None )
193+ ( sig, generics)
180194 }
181195 hir:: Node :: TraitItem ( hir:: TraitItem {
182196 kind : hir:: TraitItemKind :: Fn ( sig, _) ,
183197 generics,
184- owner_id,
185198 ..
186- } ) => ( sig, generics, Some ( tcx . parent ( owner_id . to_def_id ( ) ) ) ) ,
199+ } ) => ( sig, generics) ,
187200 hir:: Node :: ImplItem ( hir:: ImplItem {
188201 kind : hir:: ImplItemKind :: Fn ( sig, _) ,
189202 generics,
190- owner_id,
191203 ..
192- } ) => ( sig, generics, Some ( tcx . parent ( owner_id . to_def_id ( ) ) ) ) ,
204+ } ) => ( sig, generics) ,
193205 _ => return false ,
194206 } ;
195207 let Ok ( trait_name) = tcx. sess . source_map ( ) . span_to_snippet ( self_ty. span ) else {
196208 return false ;
197209 } ;
198210 let impl_sugg = vec ! [ ( self_ty. span. shrink_to_lo( ) , "impl " . to_string( ) ) ] ;
199- let mut is_downgradable = true ;
200-
201211 // Check if trait object is safe for suggesting dynamic dispatch.
202212 let is_dyn_compatible = match self_ty. kind {
203213 hir:: TyKind :: TraitObject ( objects, ..) => {
204214 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) ,
212216 _ => false ,
213217 } )
214218 }
@@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
255259 suggestion,
256260 Applicability :: MachineApplicable ,
257261 ) ;
258- } else if is_downgradable {
259- // We'll emit the dyn-compatibility error already, with a structured suggestion.
260- diag. downgrade_to_delayed_bug ( ) ;
261262 }
262263 return true ;
263264 }
@@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
281282 ) ;
282283 if !is_dyn_compatible {
283284 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- }
288285 } else {
289286 // No ampersand in suggestion if it's borrowed already
290287 let ( dyn_str, paren_dyn_str) =
0 commit comments