@@ -4,7 +4,7 @@ use hir::ItemKind;
4
4
use rustc_ast:: Mutability ;
5
5
use rustc_errors:: Applicability ;
6
6
use rustc_hir as hir;
7
- use rustc_middle:: ty:: Ty ;
7
+ use rustc_middle:: ty:: { Ref , Ty } ;
8
8
use rustc_session:: lint:: builtin:: FUTURE_PRELUDE_COLLISION ;
9
9
use rustc_span:: symbol:: kw:: Underscore ;
10
10
use rustc_span:: symbol:: { sym, Ident } ;
@@ -46,21 +46,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46
46
return ;
47
47
}
48
48
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
+
64
74
let derefs = "*" . repeat ( pick. autoderefs ) ;
65
75
66
76
let autoref = match pick. autoref_or_ptr_adjustment {
@@ -74,46 +84,115 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
74
84
} ) => "&" ,
75
85
Some ( probe:: AutorefOrPtrAdjustment :: ToConstPtr ) | None => "" ,
76
86
} ;
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 )
79
88
{
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
+ ) ;
81
103
} 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 ( ) ,
111
133
) ;
112
- }
113
134
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
+ }
117
196
}
118
197
119
198
pub ( super ) fn lint_fully_qualified_call_from_2018 (
@@ -226,11 +305,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
226
305
// All that is left is `_`! We need to use the full path. It doesn't matter which one we pick,
227
306
// so just take the first one.
228
307
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
+ ) ,
234
315
_ => {
235
316
span_bug ! ( span, "unexpected item kind, expected a use: {:?}" , import_items[ 0 ] . kind) ;
236
317
}
0 commit comments