about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-04-28 17:24:22 +0000
committerbors <bors@rust-lang.org>2022-04-28 17:24:22 +0000
commit339a1867f45b6bbfa0f5f5f274706b1b81b71663 (patch)
treee92c2d727f7b4eee3dd5bb0beffd4ad89363d8f5
parentd382e24a11c8706b201c8437894506d191691334 (diff)
parentc7027122db14317c4c4d72469e13af0292f64254 (diff)
downloadrust-339a1867f45b6bbfa0f5f5f274706b1b81b71663.tar.gz
rust-339a1867f45b6bbfa0f5f5f274706b1b81b71663.zip
Auto merge of #12110 - jonas-schievink:inline-self-type, r=jonas-schievink
feat: Make "inline type alias" work for `Self`

Fixes https://github.com/rust-lang/rust-analyzer/issues/12109
-rw-r--r--crates/ide_assists/src/handlers/inline_type_alias.rs119
1 files changed, 102 insertions, 17 deletions
diff --git a/crates/ide_assists/src/handlers/inline_type_alias.rs b/crates/ide_assists/src/handlers/inline_type_alias.rs
index eeb2e2e6679..bc4a07358cc 100644
--- a/crates/ide_assists/src/handlers/inline_type_alias.rs
+++ b/crates/ide_assists/src/handlers/inline_type_alias.rs
@@ -3,7 +3,7 @@
 // - "inline_alias_to_users" assist #10881.
 // - Remove unused aliases if there are no longer any users, see inline_call.rs.
 
-use hir::PathResolution;
+use hir::{HasSource, PathResolution};
 use itertools::Itertools;
 use std::collections::HashMap;
 use syntax::{
@@ -41,31 +41,48 @@ use crate::{
 // }
 // ```
 pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let alias_instance = ctx.find_node_at_offset::<ast::PathType>()?;
-    let alias = get_type_alias(&ctx, &alias_instance)?;
-    let concrete_type = alias.ty()?;
-
     enum Replacement {
         Generic { lifetime_map: LifetimeMap, const_and_type_map: ConstAndTypeMap },
         Plain,
     }
 
-    let replacement = if let Some(alias_generics) = alias.generic_param_list() {
-        if alias_generics.generic_params().next().is_none() {
-            cov_mark::hit!(no_generics_params);
-            return None;
+    let alias_instance = ctx.find_node_at_offset::<ast::PathType>()?;
+    let concrete_type;
+    let replacement;
+    match alias_instance.path()?.as_single_name_ref() {
+        Some(nameref) if nameref.Self_token().is_some() => {
+            match ctx.sema.resolve_path(&alias_instance.path()?)? {
+                PathResolution::SelfType(imp) => {
+                    concrete_type = imp.source(ctx.db())?.value.self_ty()?;
+                }
+                // FIXME: should also work in ADT definitions
+                _ => return None,
+            }
+
+            replacement = Replacement::Plain;
         }
+        _ => {
+            let alias = get_type_alias(&ctx, &alias_instance)?;
+            concrete_type = alias.ty()?;
+
+            replacement = if let Some(alias_generics) = alias.generic_param_list() {
+                if alias_generics.generic_params().next().is_none() {
+                    cov_mark::hit!(no_generics_params);
+                    return None;
+                }
 
-        let instance_args =
-            alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast);
+                let instance_args =
+                    alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast);
 
-        Replacement::Generic {
-            lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?,
-            const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?,
+                Replacement::Generic {
+                    lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?,
+                    const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?,
+                }
+            } else {
+                Replacement::Plain
+            };
         }
-    } else {
-        Replacement::Plain
-    };
+    }
 
     let target = alias_instance.syntax().text_range();
 
@@ -755,4 +772,72 @@ fn main() {
 "#,
         );
     }
+
+    #[test]
+    fn inline_self_type() {
+        check_assist(
+            inline_type_alias,
+            r#"
+struct Strukt;
+
+impl Strukt {
+    fn new() -> Self$0 {}
+}
+"#,
+            r#"
+struct Strukt;
+
+impl Strukt {
+    fn new() -> Strukt {}
+}
+"#,
+        );
+        check_assist(
+            inline_type_alias,
+            r#"
+struct Strukt<'a, T, const C: usize>(&'a [T; C]);
+
+impl<T, const C: usize> Strukt<'_, T, C> {
+    fn new() -> Self$0 {}
+}
+"#,
+            r#"
+struct Strukt<'a, T, const C: usize>(&'a [T; C]);
+
+impl<T, const C: usize> Strukt<'_, T, C> {
+    fn new() -> Strukt<'_, T, C> {}
+}
+"#,
+        );
+        check_assist(
+            inline_type_alias,
+            r#"
+struct Strukt<'a, T, const C: usize>(&'a [T; C]);
+
+trait Tr<'b, T> {}
+
+impl<T, const C: usize> Tr<'static, u8> for Strukt<'_, T, C> {
+    fn new() -> Self$0 {}
+}
+"#,
+            r#"
+struct Strukt<'a, T, const C: usize>(&'a [T; C]);
+
+trait Tr<'b, T> {}
+
+impl<T, const C: usize> Tr<'static, u8> for Strukt<'_, T, C> {
+    fn new() -> Strukt<'_, T, C> {}
+}
+"#,
+        );
+
+        check_assist_not_applicable(
+            inline_type_alias,
+            r#"
+trait Tr {
+    fn new() -> Self$0;
+}
+"#,
+        );
+    }
 }