@@ -13,6 +13,7 @@ use crate::errors::{
1313} ;
1414use crate :: middle:: resolve_lifetime as rl;
1515use crate :: require_c_abi_if_c_variadic;
16+ use rustc_ast:: TraitObjectSyntax ;
1617use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1718use rustc_errors:: { struct_span_err, Applicability , ErrorReported , FatalError } ;
1819use rustc_hir as hir;
@@ -24,7 +25,8 @@ use rustc_hir::{GenericArg, GenericArgs};
2425use rustc_middle:: ty:: subst:: { self , GenericArgKind , InternalSubsts , Subst , SubstsRef } ;
2526use rustc_middle:: ty:: GenericParamDefKind ;
2627use rustc_middle:: ty:: { self , Const , DefIdTree , Ty , TyCtxt , TypeFoldable } ;
27- use rustc_session:: lint:: builtin:: AMBIGUOUS_ASSOCIATED_ITEMS ;
28+ use rustc_session:: lint:: builtin:: { AMBIGUOUS_ASSOCIATED_ITEMS , BARE_TRAIT_OBJECTS } ;
29+ use rustc_span:: edition:: Edition ;
2830use rustc_span:: lev_distance:: find_best_match_for_name;
2931use rustc_span:: symbol:: { Ident , Symbol } ;
3032use rustc_span:: { Span , DUMMY_SP } ;
@@ -2266,13 +2268,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22662268 /// Parses the programmer's textual representation of a type into our
22672269 /// internal notion of a type.
22682270 pub fn ast_ty_to_ty ( & self , ast_ty : & hir:: Ty < ' _ > ) -> Ty < ' tcx > {
2269- self . ast_ty_to_ty_inner ( ast_ty, false )
2271+ self . ast_ty_to_ty_inner ( ast_ty, false , false )
2272+ }
2273+
2274+ /// Parses the programmer's textual representation of a type into our
2275+ /// internal notion of a type. This is meant to be used within a path.
2276+ pub fn ast_ty_to_ty_in_path ( & self , ast_ty : & hir:: Ty < ' _ > ) -> Ty < ' tcx > {
2277+ self . ast_ty_to_ty_inner ( ast_ty, false , true )
22702278 }
22712279
22722280 /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
22732281 /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
22742282 #[ tracing:: instrument( level = "debug" , skip( self ) ) ]
2275- fn ast_ty_to_ty_inner ( & self , ast_ty : & hir:: Ty < ' _ > , borrowed : bool ) -> Ty < ' tcx > {
2283+ fn ast_ty_to_ty_inner ( & self , ast_ty : & hir:: Ty < ' _ > , borrowed : bool , in_path : bool ) -> Ty < ' tcx > {
22762284 let tcx = self . tcx ( ) ;
22772285
22782286 let result_ty = match ast_ty. kind {
@@ -2283,7 +2291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22832291 hir:: TyKind :: Rptr ( ref region, ref mt) => {
22842292 let r = self . ast_region_to_region ( region, None ) ;
22852293 debug ! ( ?r) ;
2286- let t = self . ast_ty_to_ty_inner ( mt. ty , true ) ;
2294+ let t = self . ast_ty_to_ty_inner ( mt. ty , true , false ) ;
22872295 tcx. mk_ref ( r, ty:: TypeAndMut { ty : t, mutbl : mt. mutbl } )
22882296 }
22892297 hir:: TyKind :: Never => tcx. types . never ,
@@ -2302,6 +2310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23022310 ) )
23032311 }
23042312 hir:: TyKind :: TraitObject ( bounds, ref lifetime, _) => {
2313+ self . maybe_lint_bare_trait ( ast_ty, in_path) ;
23052314 self . conv_object_ty_poly_trait_ref ( ast_ty. span , bounds, lifetime, borrowed)
23062315 }
23072316 hir:: TyKind :: Path ( hir:: QPath :: Resolved ( ref maybe_qself, ref path) ) => {
@@ -2329,7 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23292338 }
23302339 hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( ref qself, ref segment) ) => {
23312340 debug ! ( ?qself, ?segment) ;
2332- let ty = self . ast_ty_to_ty ( qself) ;
2341+ let ty = self . ast_ty_to_ty_inner ( qself, false , true ) ;
23332342
23342343 let res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = qself. kind {
23352344 path. res
@@ -2586,4 +2595,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
25862595 }
25872596 Some ( r)
25882597 }
2598+
2599+ fn maybe_lint_bare_trait ( & self , self_ty : & hir:: Ty < ' _ > , in_path : bool ) {
2600+ let tcx = self . tcx ( ) ;
2601+ if let hir:: TyKind :: TraitObject ( [ poly_trait_ref, ..] , _, TraitObjectSyntax :: None ) =
2602+ self_ty. kind
2603+ {
2604+ let needs_bracket = in_path
2605+ && !tcx
2606+ . sess
2607+ . source_map ( )
2608+ . span_to_prev_source ( self_ty. span )
2609+ . ok ( )
2610+ . map_or ( false , |s| s. trim_end ( ) . ends_with ( '<' ) ) ;
2611+
2612+ let is_global = poly_trait_ref. trait_ref . path . is_global ( ) ;
2613+ let sugg = Vec :: from_iter ( [
2614+ (
2615+ self_ty. span . shrink_to_lo ( ) ,
2616+ format ! (
2617+ "{}dyn {}" ,
2618+ if needs_bracket { "<" } else { "" } ,
2619+ if is_global { "(" } else { "" } ,
2620+ ) ,
2621+ ) ,
2622+ (
2623+ self_ty. span . shrink_to_hi ( ) ,
2624+ format ! (
2625+ "{}{}" ,
2626+ if is_global { ")" } else { "" } ,
2627+ if needs_bracket { ">" } else { "" } ,
2628+ ) ,
2629+ ) ,
2630+ ] ) ;
2631+ if self_ty. span . edition ( ) >= Edition :: Edition2021 {
2632+ let msg = "trait objects must include the `dyn` keyword" ;
2633+ let label = "add `dyn` keyword before this trait" ;
2634+ rustc_errors:: struct_span_err!( tcx. sess, self_ty. span, E0782 , "{}" , msg)
2635+ . multipart_suggestion_verbose ( label, sugg, Applicability :: MachineApplicable )
2636+ . emit ( ) ;
2637+ } else {
2638+ let msg = "trait objects without an explicit `dyn` are deprecated" ;
2639+ tcx. struct_span_lint_hir (
2640+ BARE_TRAIT_OBJECTS ,
2641+ self_ty. hir_id ,
2642+ self_ty. span ,
2643+ |lint| {
2644+ lint. build ( msg)
2645+ . multipart_suggestion_verbose (
2646+ "use `dyn`" ,
2647+ sugg,
2648+ Applicability :: MachineApplicable ,
2649+ )
2650+ . emit ( )
2651+ } ,
2652+ ) ;
2653+ }
2654+ }
2655+ }
25892656}
0 commit comments