Add from_over_into replace for type in Self reference
This commit is contained in:
parent
423f081089
commit
d4b388eb43
4 changed files with 108 additions and 2 deletions
|
|
@ -163,7 +163,8 @@ fn convert_to_from(
|
|||
let PatKind::Binding(.., self_ident, None) = input.pat.kind else { return None };
|
||||
|
||||
let from = snippet_opt(cx, self_ty.span)?;
|
||||
let into = snippet_opt(cx, target_ty.span)?;
|
||||
// If Self is used, it refers to `self_ty`, which is now out `from` snippet
|
||||
let into = replace_self(&snippet_opt(cx, target_ty.span)?, &from);
|
||||
|
||||
let mut suggestions = vec![
|
||||
// impl Into<T> for U -> impl From<T> for U
|
||||
|
|
@ -212,3 +213,75 @@ fn convert_to_from(
|
|||
|
||||
Some(suggestions)
|
||||
}
|
||||
|
||||
fn replace_self(input: &str, replace_with: &str) -> String {
|
||||
const SELF: &str = "Self";
|
||||
let mut chunks = input.split(SELF).peekable();
|
||||
if let Some(first) = chunks.next() {
|
||||
let mut last_ended_with_break = false;
|
||||
// Heuristic, we're making a guess that the expansion probably doesn't exceed `input.len() * 2`
|
||||
let mut output = String::with_capacity(input.len() * 2);
|
||||
if first.is_empty() || first.ends_with(word_break) {
|
||||
last_ended_with_break = true;
|
||||
}
|
||||
output.push_str(first);
|
||||
while let Some(val) = chunks.next() {
|
||||
let is_last = chunks.peek().is_none();
|
||||
if last_ended_with_break && is_last && val.is_empty() {
|
||||
output.push_str(replace_with);
|
||||
break;
|
||||
}
|
||||
let this_starts_with_break = val.starts_with(word_break);
|
||||
let this_ends_with_break = val.ends_with(word_break);
|
||||
if this_starts_with_break && last_ended_with_break {
|
||||
output.push_str(replace_with);
|
||||
} else {
|
||||
output.push_str(SELF);
|
||||
}
|
||||
output.push_str(val);
|
||||
last_ended_with_break = this_ends_with_break;
|
||||
}
|
||||
output
|
||||
} else {
|
||||
input.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn word_break(ch: char) -> bool {
|
||||
!ch.is_alphanumeric()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::from_over_into::replace_self;
|
||||
|
||||
#[test]
|
||||
fn replace_doesnt_touch_coincidental_self() {
|
||||
let input = "impl Into<SelfType> for String {";
|
||||
assert_eq!(input, &replace_self(input, "T"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_replaces_self() {
|
||||
let input = "impl Into<Self> for String {";
|
||||
assert_eq!("impl Into<String> for String {", &replace_self(input, "String"));
|
||||
}
|
||||
#[test]
|
||||
fn replace_replaces_self_many() {
|
||||
let input = "impl Into<Self<Self<SelfSelfSelfSelf>>> for Self {";
|
||||
assert_eq!(
|
||||
"impl Into<String<String<SelfSelfSelfSelf>>> for String {",
|
||||
&replace_self(input, "String")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replace_replaces_self_many_starts_ends_self() {
|
||||
let input = "Self impl Into<Self<Self<SelfSelf>>> for Self";
|
||||
assert_eq!(
|
||||
"String impl Into<String<String<SelfSelf>>> for String",
|
||||
&replace_self(input, "String")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,4 +88,14 @@ impl Into<Opaque> for IntoOpaque {
|
|||
fn into(self) -> Opaque {}
|
||||
}
|
||||
|
||||
pub struct Lval<T>(T);
|
||||
|
||||
pub struct Rval<T>(T);
|
||||
|
||||
impl<T> From<Lval<T>> for Rval<Lval<T>> {
|
||||
fn from(val: Lval<T>) -> Self {
|
||||
Rval(val)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -88,4 +88,14 @@ impl Into<Opaque> for IntoOpaque {
|
|||
fn into(self) -> Opaque {}
|
||||
}
|
||||
|
||||
pub struct Lval<T>(T);
|
||||
|
||||
pub struct Rval<T>(T);
|
||||
|
||||
impl<T> Into<Rval<Self>> for Lval<T> {
|
||||
fn into(self) -> Rval<Self> {
|
||||
Rval(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -71,5 +71,18 @@ LL ~ fn from(val: Vec<T>) -> Self {
|
|||
LL ~ FromOverInto(val)
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
|
||||
--> $DIR/from_over_into.rs:95:1
|
||||
|
|
||||
LL | impl<T> Into<Rval<Self>> for Lval<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: replace the `Into` implementation with `From<Lval<T>>`
|
||||
|
|
||||
LL ~ impl<T> From<Lval<T>> for Rval<Lval<T>> {
|
||||
LL ~ fn from(val: Lval<T>) -> Self {
|
||||
LL ~ Rval(val)
|
||||
|
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue