@@ -13,6 +13,7 @@ use crate::errors::{
13
13
} ;
14
14
use crate :: middle:: resolve_lifetime as rl;
15
15
use crate :: require_c_abi_if_c_variadic;
16
+ use rustc_ast:: TraitObjectSyntax ;
16
17
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
17
18
use rustc_errors:: { struct_span_err, Applicability , ErrorReported , FatalError } ;
18
19
use rustc_hir as hir;
@@ -24,7 +25,8 @@ use rustc_hir::{GenericArg, GenericArgs};
24
25
use rustc_middle:: ty:: subst:: { self , GenericArgKind , InternalSubsts , Subst , SubstsRef } ;
25
26
use rustc_middle:: ty:: GenericParamDefKind ;
26
27
use 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 ;
28
30
use rustc_span:: lev_distance:: find_best_match_for_name;
29
31
use rustc_span:: symbol:: { Ident , Symbol } ;
30
32
use rustc_span:: { Span , DUMMY_SP } ;
@@ -2266,13 +2268,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2266
2268
/// Parses the programmer's textual representation of a type into our
2267
2269
/// internal notion of a type.
2268
2270
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 )
2270
2278
}
2271
2279
2272
2280
/// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait
2273
2281
/// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors.
2274
2282
#[ 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 > {
2276
2284
let tcx = self . tcx ( ) ;
2277
2285
2278
2286
let result_ty = match ast_ty. kind {
@@ -2283,7 +2291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2283
2291
hir:: TyKind :: Rptr ( ref region, ref mt) => {
2284
2292
let r = self . ast_region_to_region ( region, None ) ;
2285
2293
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 ) ;
2287
2295
tcx. mk_ref ( r, ty:: TypeAndMut { ty : t, mutbl : mt. mutbl } )
2288
2296
}
2289
2297
hir:: TyKind :: Never => tcx. types . never ,
@@ -2302,6 +2310,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2302
2310
) )
2303
2311
}
2304
2312
hir:: TyKind :: TraitObject ( bounds, ref lifetime, _) => {
2313
+ self . maybe_lint_bare_trait ( ast_ty, in_path) ;
2305
2314
self . conv_object_ty_poly_trait_ref ( ast_ty. span , bounds, lifetime, borrowed)
2306
2315
}
2307
2316
hir:: TyKind :: Path ( hir:: QPath :: Resolved ( ref maybe_qself, ref path) ) => {
@@ -2329,7 +2338,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2329
2338
}
2330
2339
hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( ref qself, ref segment) ) => {
2331
2340
debug ! ( ?qself, ?segment) ;
2332
- let ty = self . ast_ty_to_ty ( qself) ;
2341
+ let ty = self . ast_ty_to_ty_inner ( qself, false , true ) ;
2333
2342
2334
2343
let res = if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, path) ) = qself. kind {
2335
2344
path. res
@@ -2586,4 +2595,62 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
2586
2595
}
2587
2596
Some ( r)
2588
2597
}
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
+ }
2589
2656
}
0 commit comments