@@ -80,6 +80,11 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
8080 && cx. tcx . is_diagnostic_item ( sym:: Into , middle_trait_ref. def_id )
8181 && !matches ! ( middle_trait_ref. substs. type_at( 1 ) . kind( ) , ty:: Alias ( ty:: Opaque , _) )
8282 {
83+ if !target_ty. find_self_aliases ( ) . is_empty ( ) {
84+ // It's tricky to expand self-aliases correctly, we'll ignore it to not cause a
85+ // bad suggestion/fix.
86+ return ;
87+ }
8388 span_lint_and_then (
8489 cx,
8590 FROM_OVER_INTO ,
@@ -163,8 +168,7 @@ fn convert_to_from(
163168 let PatKind :: Binding ( .., self_ident, None ) = input. pat . kind else { return None } ;
164169
165170 let from = snippet_opt ( cx, self_ty. span ) ?;
166- // If Self is used, it refers to `self_ty`, which is now out `from` snippet
167- let into = replace_self ( & snippet_opt ( cx, target_ty. span ) ?, & from) ;
171+ let into = snippet_opt ( cx, target_ty. span ) ?;
168172
169173 let mut suggestions = vec ! [
170174 // impl Into<T> for U -> impl From<T> for U
@@ -213,75 +217,3 @@ fn convert_to_from(
213217
214218 Some ( suggestions)
215219}
216-
217- fn replace_self ( input : & str , replace_with : & str ) -> String {
218- const SELF : & str = "Self" ;
219- let mut chunks = input. split ( SELF ) . peekable ( ) ;
220- if let Some ( first) = chunks. next ( ) {
221- let mut last_ended_with_break = false ;
222- // Heuristic, we're making a guess that the expansion probably doesn't exceed `input.len() * 2`
223- let mut output = String :: with_capacity ( input. len ( ) * 2 ) ;
224- if first. is_empty ( ) || first. ends_with ( word_break) {
225- last_ended_with_break = true ;
226- }
227- output. push_str ( first) ;
228- while let Some ( val) = chunks. next ( ) {
229- let is_last = chunks. peek ( ) . is_none ( ) ;
230- if last_ended_with_break && is_last && val. is_empty ( ) {
231- output. push_str ( replace_with) ;
232- break ;
233- }
234- let this_starts_with_break = val. starts_with ( word_break) ;
235- let this_ends_with_break = val. ends_with ( word_break) ;
236- if this_starts_with_break && last_ended_with_break {
237- output. push_str ( replace_with) ;
238- } else {
239- output. push_str ( SELF ) ;
240- }
241- output. push_str ( val) ;
242- last_ended_with_break = this_ends_with_break;
243- }
244- output
245- } else {
246- input. to_string ( )
247- }
248- }
249-
250- #[ inline]
251- fn word_break ( ch : char ) -> bool {
252- !ch. is_alphanumeric ( )
253- }
254-
255- #[ cfg( test) ]
256- mod tests {
257- use crate :: from_over_into:: replace_self;
258-
259- #[ test]
260- fn replace_doesnt_touch_coincidental_self ( ) {
261- let input = "impl Into<SelfType> for String {" ;
262- assert_eq ! ( input, & replace_self( input, "T" ) ) ;
263- }
264-
265- #[ test]
266- fn replace_replaces_self ( ) {
267- let input = "impl Into<Self> for String {" ;
268- assert_eq ! ( "impl Into<String> for String {" , & replace_self( input, "String" ) ) ;
269- }
270- #[ test]
271- fn replace_replaces_self_many ( ) {
272- let input = "impl Into<Self<Self<SelfSelfSelfSelf>>> for Self {" ;
273- assert_eq ! (
274- "impl Into<String<String<SelfSelfSelfSelf>>> for String {" ,
275- & replace_self( input, "String" )
276- ) ;
277- }
278-
279- #[ test]
280- fn replace_replaces_self_many_starts_ends_self ( ) {
281- let input = "Self impl Into<Self<Self<SelfSelf>>> for Self" ;
282- assert_eq ! (
283- "String impl Into<String<String<SelfSelf>>> for String" ,
284- & replace_self( input, "String" )
285- ) ;
286- }
287- }
0 commit comments