@@ -4,7 +4,7 @@ use hir::ItemKind;
44use rustc_ast:: Mutability ;
55use rustc_errors:: Applicability ;
66use rustc_hir as hir;
7- use rustc_middle:: ty:: Ty ;
7+ use rustc_middle:: ty:: { Ref , Ty } ;
88use rustc_session:: lint:: builtin:: FUTURE_PRELUDE_COLLISION ;
99use rustc_span:: symbol:: kw:: Underscore ;
1010use rustc_span:: symbol:: { sym, Ident } ;
@@ -46,21 +46,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4646 return ;
4747 }
4848
49- self . tcx . struct_span_lint_hir (
50- FUTURE_PRELUDE_COLLISION ,
51- call_expr. hir_id ,
52- call_expr. span ,
53- |lint| {
54- let sp = call_expr. span ;
55- let trait_name =
56- self . trait_path_or_bare_name ( span, call_expr. hir_id , pick. item . container . id ( ) ) ;
57-
58- let mut lint = lint. build ( & format ! (
59- "trait method `{}` will become ambiguous in Rust 2021" ,
60- segment. ident. name
61- ) ) ;
62-
63- if let Ok ( self_expr) = self . sess ( ) . source_map ( ) . span_to_snippet ( self_expr. span ) {
49+ if matches ! ( pick. kind, probe:: PickKind :: InherentImplPick | probe:: PickKind :: ObjectPick ) {
50+ // avoid repeatedly adding unneeded `&*`s
51+ if pick. autoderefs == 1
52+ && matches ! (
53+ pick. autoref_or_ptr_adjustment,
54+ Some ( probe:: AutorefOrPtrAdjustment :: Autoref { .. } )
55+ )
56+ && matches ! ( self_ty. kind( ) , Ref ( ..) )
57+ {
58+ return ;
59+ }
60+ // Inherent impls only require not relying on autoref and autoderef in order to
61+ // ensure that the trait implementation won't be used
62+ self . tcx . struct_span_lint_hir (
63+ FUTURE_PRELUDE_COLLISION ,
64+ self_expr. hir_id ,
65+ self_expr. span ,
66+ |lint| {
67+ let sp = self_expr. span ;
68+
69+ let mut lint = lint. build ( & format ! (
70+ "trait method `{}` will become ambiguous in Rust 2021" ,
71+ segment. ident. name
72+ ) ) ;
73+
6474 let derefs = "*" . repeat ( pick. autoderefs ) ;
6575
6676 let autoref = match pick. autoref_or_ptr_adjustment {
@@ -74,46 +84,115 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7484 } ) => "&" ,
7585 Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) | None => "" ,
7686 } ;
77- let self_adjusted = if let Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) =
78- pick. autoref_or_ptr_adjustment
87+ if let Ok ( self_expr) = self . sess ( ) . source_map ( ) . span_to_snippet ( self_expr. span )
7988 {
80- format ! ( "{}{} as *const _" , derefs, self_expr)
89+ let self_adjusted = if let Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) =
90+ pick. autoref_or_ptr_adjustment
91+ {
92+ format ! ( "{}{} as *const _" , derefs, self_expr)
93+ } else {
94+ format ! ( "{}{}{}" , autoref, derefs, self_expr)
95+ } ;
96+
97+ lint. span_suggestion (
98+ sp,
99+ "disambiguate the method call" ,
100+ format ! ( "({})" , self_adjusted) ,
101+ Applicability :: MachineApplicable ,
102+ ) ;
81103 } else {
82- format ! ( "{}{}{}" , autoref , derefs , self_expr )
83- } ;
84- let args = args
85- . iter ( )
86- . skip ( 1 )
87- . map ( |arg| {
88- format ! (
89- ", {}" ,
90- self . sess ( ) . source_map ( ) . span_to_snippet ( arg . span ) . unwrap ( )
91- )
92- } )
93- . collect :: < String > ( ) ;
94-
95- lint. span_suggestion (
96- sp ,
97- "disambiguate the associated function" ,
98- format ! (
99- "{}::{}({}{})" ,
100- trait_name , segment . ident . name , self_adjusted , args
101- ) ,
102- Applicability :: MachineApplicable ,
103- ) ;
104- } else {
105- lint. span_help (
106- sp ,
107- & format ! (
108- "disambiguate the associated function with `{}::{}(...)`" ,
109- trait_name , segment . ident ,
110- ) ,
104+ let self_adjusted = if let Some ( probe :: AutorefOrPtrAdjustment :: ToConstPtr ) =
105+ pick . autoref_or_ptr_adjustment
106+ {
107+ format ! ( "{}(...) as *const _" , derefs )
108+ } else {
109+ format ! ( "{}{}..." , autoref , derefs )
110+ } ;
111+ lint . span_help (
112+ sp ,
113+ & format ! ( "disambiguate the method call with `({})`" , self_adjusted , ) ,
114+ ) ;
115+ }
116+
117+ lint. emit ( ) ;
118+ } ,
119+ ) ;
120+ } else {
121+ // trait implementations require full disambiguation to not clash with the new prelude
122+ // additions (i.e. convert from dot-call to fully-qualified call)
123+ self . tcx . struct_span_lint_hir (
124+ FUTURE_PRELUDE_COLLISION ,
125+ call_expr . hir_id ,
126+ call_expr . span ,
127+ | lint| {
128+ let sp = call_expr . span ;
129+ let trait_name = self . trait_path_or_bare_name (
130+ span ,
131+ call_expr . hir_id ,
132+ pick . item . container . id ( ) ,
111133 ) ;
112- }
113134
114- lint. emit ( ) ;
115- } ,
116- ) ;
135+ let mut lint = lint. build ( & format ! (
136+ "trait method `{}` will become ambiguous in Rust 2021" ,
137+ segment. ident. name
138+ ) ) ;
139+
140+ if let Ok ( self_expr) = self . sess ( ) . source_map ( ) . span_to_snippet ( self_expr. span )
141+ {
142+ let derefs = "*" . repeat ( pick. autoderefs ) ;
143+
144+ let autoref = match pick. autoref_or_ptr_adjustment {
145+ Some ( probe:: AutorefOrPtrAdjustment :: Autoref {
146+ mutbl : Mutability :: Mut ,
147+ ..
148+ } ) => "&mut " ,
149+ Some ( probe:: AutorefOrPtrAdjustment :: Autoref {
150+ mutbl : Mutability :: Not ,
151+ ..
152+ } ) => "&" ,
153+ Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) | None => "" ,
154+ } ;
155+ let self_adjusted = if let Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) =
156+ pick. autoref_or_ptr_adjustment
157+ {
158+ format ! ( "{}{} as *const _" , derefs, self_expr)
159+ } else {
160+ format ! ( "{}{}{}" , autoref, derefs, self_expr)
161+ } ;
162+ let args = args
163+ . iter ( )
164+ . skip ( 1 )
165+ . map ( |arg| {
166+ format ! (
167+ ", {}" ,
168+ self . sess( ) . source_map( ) . span_to_snippet( arg. span) . unwrap( )
169+ )
170+ } )
171+ . collect :: < String > ( ) ;
172+
173+ lint. span_suggestion (
174+ sp,
175+ "disambiguate the associated function" ,
176+ format ! (
177+ "{}::{}({}{})" ,
178+ trait_name, segment. ident. name, self_adjusted, args
179+ ) ,
180+ Applicability :: MachineApplicable ,
181+ ) ;
182+ } else {
183+ lint. span_help (
184+ sp,
185+ & format ! (
186+ "disambiguate the associated function with `{}::{}(...)`" ,
187+ trait_name, segment. ident,
188+ ) ,
189+ ) ;
190+ }
191+
192+ lint. emit ( ) ;
193+ } ,
194+ ) ;
195+ }
117196 }
118197
119198 pub ( super ) fn lint_fully_qualified_call_from_2018 (
@@ -226,11 +305,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
226305 // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick,
227306 // so just take the first one.
228307 match import_items[ 0 ] . kind {
229- ItemKind :: Use ( path, _) => {
230- // FIXME: serialize path into something readable like a::b, there must be a fn for this
231- debug ! ( "no name for trait, found import of path: {:?}" , path) ;
232- return None ;
233- }
308+ ItemKind :: Use ( path, _) => Some (
309+ path. segments
310+ . iter ( )
311+ . map ( |segment| segment. ident . to_string ( ) )
312+ . collect :: < Vec < _ > > ( )
313+ . join ( "::" ) ,
314+ ) ,
234315 _ => {
235316 span_bug ! ( span, "unexpected item kind, expected a use: {:?}" , import_items[ 0 ] . kind) ;
236317 }
0 commit comments