From 9f238930f1969731869c89956414f4b160b180c0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 22 Aug 2019 15:28:08 +0300 Subject: [PATCH] Don't add `?` bounds as real bounds closes #1709 --- crates/ra_hir/src/generics.rs | 8 +++++++ crates/ra_hir/src/ty/tests.rs | 29 ++++++++++++++++++++++++++ crates/ra_syntax/src/ast/extensions.rs | 12 +++++++++++ 3 files changed, 49 insertions(+) diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index e6482180d5c..e75337cdf75 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs @@ -75,6 +75,7 @@ pub(crate) fn generic_params_query( }; generics.parent_params = parent.map(|p| db.generic_params(p)); let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; + // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { GenericDef::Function(it) => generics.fill(&it.source(db).ast, start), GenericDef::Struct(it) => generics.fill(&it.source(db).ast, start), @@ -86,6 +87,9 @@ pub(crate) fn generic_params_query( generics.fill(&it.source(db).ast, start + 1); } GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start), + // Note that we don't add `Self` here: in `impl`s, `Self` is not a + // type-parameter, but rather is a type-alias for impl's target + // type, so this is handled by the resovler. GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start), GenericDef::EnumVariant(_) => {} } @@ -135,6 +139,10 @@ fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { } fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { + if bound.has_question_mark() { + // FIXME: remove this bound + return; + } let path = bound .type_ref() .and_then(|tr| match tr { diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 6c2d857bca1..57fd5492d8b 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -3028,6 +3028,35 @@ fn test(s: S) { assert_eq!(t, "{unknown}"); } +#[test] +fn deref_trait_with_question_mark_size() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct Arc; +impl Deref for Arc { + type Target = T; +} + +struct S; +impl S { + fn foo(&self) -> u128 {} +} + +fn test(s: Arc) { + (*s, s.foo())<|> +} +"#, + ); + assert_eq!(t, "(S, u128)"); +} + #[test] fn obligation_from_function_clause() { let t = type_at( diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index 2a59cf65373..efe261fc232 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs @@ -382,6 +382,18 @@ pub fn lifetime_token(&self) -> Option { } } +impl ast::TypeBound { + pub fn question_mark_token(&self) -> Option { + self.syntax() + .children_with_tokens() + .filter_map(|it| it.into_token()) + .find(|it| it.kind() == T![?]) + } + pub fn has_question_mark(&self) -> bool { + self.question_mark_token().is_some() + } +} + impl ast::TraitDef { pub fn is_auto(&self) -> bool { self.syntax().children_with_tokens().any(|t| t.kind() == T![auto])