Repository: rust-analyzer/rust-analyzer
Pull request #2321 (2019-11-20 08:45:20)

Allow non-path default type parameters

matklad: bors r+
🤖

Patch:
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 8925ba3a9f..78fab1a13a 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -5,12 +5,9 @@
 
 use std::sync::Arc;
 
-use hir_def::{
-    path::Path,
-    type_ref::{TypeBound, TypeRef},
-};
+use hir_def::type_ref::{TypeBound, TypeRef};
 use hir_expand::name::{self, AsName};
-use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner};
+use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
 
 use crate::{
     db::{AstDatabase, DefDatabase, HirDatabase},
@@ -24,7 +21,7 @@ pub struct GenericParam {
     // FIXME: give generic params proper IDs
     pub idx: u32,
     pub name: Name,
-    pub default: Option<Path>,
+    pub default: Option<TypeRef>,
 }
 
 /// Data about the generic parameters of a function, struct, impl, etc.
@@ -140,7 +137,7 @@ impl GenericParams {
         for (idx, type_param) in params.type_params().enumerate() {
             let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
             // FIXME: Use `Path::from_src`
-            let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast);
+            let default = type_param.default_type().map(TypeRef::from_ast);
 
             let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
             self.params.push(param);
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index de3c56097b..03db386055 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -611,9 +611,7 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
     let defaults = generic_params
         .params_including_parent()
         .into_iter()
-        .map(|p| {
-            p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path))
-        })
+        .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
         .collect();
 
     Substs(defaults)
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 2b381dcdba..de506d7cda 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -3625,8 +3625,11 @@ impl AstNode for TypeParam {
 impl ast::NameOwner for TypeParam {}
 impl ast::AttrsOwner for TypeParam {}
 impl ast::TypeBoundsOwner for TypeParam {}
-impl ast::DefaultTypeParamOwner for TypeParam {}
-impl TypeParam {}
+impl TypeParam {
+    pub fn default_type(&self) -> Option<TypeRef> {
+        AstChildren::new(&self.syntax).next()
+    }
+}
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct TypeParamList {
     pub(crate) syntax: SyntaxNode,
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index c2b005886a..f99984fe0f 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -163,9 +163,3 @@ impl Iterator for CommentIter {
         self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
     }
 }
-
-pub trait DefaultTypeParamOwner: AstNode {
-    fn default_type(&self) -> Option<ast::PathType> {
-        child_opt(self)
-    }
-}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 70d85a8e6a..88d1dc109b 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -587,7 +587,10 @@ Grammar(
                 ("lifetime_params", "LifetimeParam" ),
             ]
         ),
-        "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner", "DefaultTypeParamOwner"] ),
+        "TypeParam": (
+            options: [("default_type", "TypeRef")],
+            traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"],
+        ),
         "LifetimeParam": (
             traits: ["AttrsOwner"],
         ),


Test patch:
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c1024d03c7..abfaffb5e2 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1979,6 +1979,30 @@ fn test() {
     );
 }
 
+#[test]
+fn infer_associated_method_generics_with_default_tuple_param() {
+    let t = type_at(
+        r#"
+//- /main.rs
+struct Gen<T=()> {
+    val: T
+}
+
+impl<T> Gen<T> {
+    pub fn make() -> Gen<T> {
+        loop { }
+    }
+}
+
+fn test() {
+    let a = Gen::make();
+    a.val<|>;
+}
+"#,
+    );
+    assert_eq!(t, "()");
+}
+
 #[test]
 fn infer_associated_method_generics_without_args() {
     assert_snapshot!(