aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFedor Sakharov <[email protected]>2020-05-13 14:06:42 +0100
committerFedor Sakharov <[email protected]>2020-05-13 14:07:44 +0100
commit00f3b6c59ae3df9a7bfb1cd8b694d5f9b6a78be4 (patch)
tree847a60e19f55dd8da4e819bd1a76b23588fb9f76 /crates
parent88d3959c33c3b8729cecbe062cff8474516df29f (diff)
Correctly fill default type parameters
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/Cargo.toml1
-rw-r--r--crates/ra_assists/src/ast_transform.rs20
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs50
-rw-r--r--crates/ra_hir/src/code_model.rs5
-rw-r--r--crates/ra_syntax/src/ast/make.rs4
5 files changed, 79 insertions, 1 deletions
diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml
index 3bcf58ba4..488ab7bc8 100644
--- a/crates/ra_assists/Cargo.toml
+++ b/crates/ra_assists/Cargo.toml
@@ -21,4 +21,5 @@ ra_prof = { path = "../ra_prof" }
21ra_db = { path = "../ra_db" } 21ra_db = { path = "../ra_db" }
22ra_ide_db = { path = "../ra_ide_db" } 22ra_ide_db = { path = "../ra_ide_db" }
23hir = { path = "../ra_hir", package = "ra_hir" } 23hir = { path = "../ra_hir", package = "ra_hir" }
24hir_def = { path = "../ra_hir_def", package = "ra_hir_def" }
24test_utils = { path = "../test_utils" } 25test_utils = { path = "../test_utils" }
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 9ac65ab39..d81218bc8 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -2,6 +2,7 @@
2use rustc_hash::FxHashMap; 2use rustc_hash::FxHashMap;
3 3
4use hir::{PathResolution, SemanticsScope}; 4use hir::{PathResolution, SemanticsScope};
5use hir_def::type_ref::TypeRef;
5use ra_ide_db::RootDatabase; 6use ra_ide_db::RootDatabase;
6use ra_syntax::{ 7use ra_syntax::{
7 algo::SyntaxRewriter, 8 algo::SyntaxRewriter,
@@ -51,7 +52,24 @@ impl<'a> SubstituteTypeParams<'a> {
51 .into_iter() 52 .into_iter()
52 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky 53 // this is a trait impl, so we need to skip the first type parameter -- this is a bit hacky
53 .skip(1) 54 .skip(1)
54 .zip(substs.into_iter()) 55 // The actual list of trait type parameters may be longer than the one
56 // used in the `impl` block due to trailing default type parametrs.
57 // For that case we extend the `substs` with an empty iterator so we
58 // can still hit those trailing values and check if they actually have
59 // a default type. If they do, go for that type from `hir` to `ast` so
60 // the resulting change can be applied correctly.
61 .zip(substs.into_iter().map(Some).chain(std::iter::repeat(None)))
62 .filter_map(|(k, v)| match v {
63 Some(v) => Some((k, v)),
64 None => match k.default(source_scope.db)? {
65 TypeRef::Path(path) => Some((
66 k,
67 ast::make::type_arg(&format!("{}", path.mod_path().as_ident()?))
68 .type_ref()?,
69 )),
70 _ => None,
71 },
72 })
55 .collect(); 73 .collect();
56 return SubstituteTypeParams { 74 return SubstituteTypeParams {
57 source_scope, 75 source_scope,
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index c1ce87914..22e1156d2 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -618,4 +618,54 @@ impl Foo for S {
618}"#, 618}"#,
619 ) 619 )
620 } 620 }
621
622 #[test]
623 fn test_generic_single_default_parameter() {
624 check_assist(
625 add_missing_impl_members,
626 r#"
627trait Foo<T = Self> {
628 fn bar(&self, other: &T);
629}
630
631struct S;
632impl Foo for S { <|> }"#,
633 r#"
634trait Foo<T = Self> {
635 fn bar(&self, other: &T);
636}
637
638struct S;
639impl Foo for S {
640 <|>fn bar(&self, other: &Self) {
641 todo!()
642 }
643}"#,
644 )
645 }
646
647 #[test]
648 fn test_generic_default_parameter_is_second() {
649 check_assist(
650 add_missing_impl_members,
651 r#"
652trait Foo<T1, T2 = Self> {
653 fn bar(&self, this: &T1, that: &T2);
654}
655
656struct S<T>;
657impl Foo<T> for S<T> { <|> }"#,
658 r#"
659trait Foo<T1, T2 = Self> {
660 fn bar(&self, this: &T1, that: &T2);
661}
662
663struct S<T>;
664impl Foo<T> for S<T> {
665 <|>fn bar(&self, this: &T, that: &Self) {
666 todo!()
667 }
668}"#,
669 )
670 }
621} 671}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index e8e3211fc..3c56f39c1 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -989,6 +989,11 @@ impl TypeParam {
989 ty: InEnvironment { value: ty, environment }, 989 ty: InEnvironment { value: ty, environment },
990 } 990 }
991 } 991 }
992
993 pub fn default(self, db: &dyn HirDatabase) -> Option<TypeRef> {
994 let params = db.generic_params(self.id.parent);
995 params.types[self.id.local_id].default.clone()
996 }
992} 997}
993 998
994// FIXME: rename from `ImplDef` to `Impl` 999// FIXME: rename from `ImplDef` to `Impl`
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 12c5228f5..8981cbe33 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -13,6 +13,10 @@ pub fn name_ref(text: &str) -> ast::NameRef {
13 ast_from_text(&format!("fn f() {{ {}; }}", text)) 13 ast_from_text(&format!("fn f() {{ {}; }}", text))
14} 14}
15 15
16pub fn type_arg(text: &str) -> ast::TypeArg {
17 ast_from_text(&format!("impl F<{}> for G {{}}", text))
18}
19
16pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment { 20pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
17 ast_from_text(&format!("use {};", name_ref)) 21 ast_from_text(&format!("use {};", name_ref))
18} 22}