aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock20
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/generics.rs12
-rw-r--r--crates/ra_hir/src/resolve.rs12
-rw-r--r--crates/ra_hir/src/ty.rs4
-rw-r--r--crates/ra_hir/src/ty/infer.rs10
-rw-r--r--crates/ra_hir/src/ty/lower.rs20
-rw-r--r--crates/ra_hir/src/ty/tests.rs134
-rw-r--r--crates/ra_hir/src/ty/traits.rs11
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs6
-rw-r--r--crates/ra_ide_api/src/completion/complete_postfix.rs82
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__postfix_completion_works_for_trivial_path_expression.snap64
12 files changed, 252 insertions, 127 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d6f526363..e0599edb3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -280,7 +280,7 @@ dependencies = [
280 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 280 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
281 "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", 281 "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
282 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 282 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
283 "regex 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 283 "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
284 "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 284 "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
285 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", 285 "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
286 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 286 "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -481,7 +481,7 @@ dependencies = [
481 "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 481 "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
482 "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 482 "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
483 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 483 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
484 "regex 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 484 "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
485 "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 485 "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
486] 486]
487 487
@@ -610,7 +610,7 @@ dependencies = [
610 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 610 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
611 "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 611 "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
612 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 612 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
613 "regex 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 613 "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
614] 614]
615 615
616[[package]] 616[[package]]
@@ -1051,7 +1051,7 @@ dependencies = [
1051 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", 1051 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
1052 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1052 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1053 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1053 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1054 "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 1054 "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
1055] 1055]
1056 1056
1057[[package]] 1057[[package]]
@@ -1514,19 +1514,19 @@ dependencies = [
1514 1514
1515[[package]] 1515[[package]]
1516name = "regex" 1516name = "regex"
1517version = "1.1.8" 1517version = "1.1.9"
1518source = "registry+https://github.com/rust-lang/crates.io-index" 1518source = "registry+https://github.com/rust-lang/crates.io-index"
1519dependencies = [ 1519dependencies = [
1520 "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", 1520 "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
1521 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1521 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1522 "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", 1522 "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
1523 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", 1523 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
1524 "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 1524 "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
1525] 1525]
1526 1526
1527[[package]] 1527[[package]]
1528name = "regex-syntax" 1528name = "regex-syntax"
1529version = "0.6.7" 1529version = "0.6.8"
1530source = "registry+https://github.com/rust-lang/crates.io-index" 1530source = "registry+https://github.com/rust-lang/crates.io-index"
1531dependencies = [ 1531dependencies = [
1532 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 1532 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1800,7 +1800,7 @@ dependencies = [
1800 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 1800 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
1801 "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 1801 "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
1802 "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 1802 "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
1803 "regex 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)", 1803 "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
1804 "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", 1804 "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
1805 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", 1805 "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
1806 "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 1806 "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2255,8 +2255,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2255"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 2255"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
2256"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 2256"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
2257"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" 2257"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
2258"checksum regex 1.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1325e8a57b7da4cbcb38b3957112f729990bad0a18420e7e250ef6b1d9a15763" 2258"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad"
2259"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48" 2259"checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21"
2260"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c" 2260"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
2261"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" 2261"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
2262"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" 2262"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f"
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index a9c6c52d9..0e6e3fdb7 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -163,10 +163,10 @@ pub trait HirDatabase: DefDatabase + AstDatabase {
163 #[salsa::invoke(crate::ty::callable_item_sig)] 163 #[salsa::invoke(crate::ty::callable_item_sig)]
164 fn callable_item_signature(&self, def: CallableDef) -> FnSig; 164 fn callable_item_signature(&self, def: CallableDef) -> FnSig;
165 165
166 #[salsa::invoke(crate::ty::generic_predicates)] 166 #[salsa::invoke(crate::ty::generic_predicates_query)]
167 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; 167 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>;
168 168
169 #[salsa::invoke(crate::ty::generic_defaults)] 169 #[salsa::invoke(crate::ty::generic_defaults_query)]
170 fn generic_defaults(&self, def: GenericDef) -> Substs; 170 fn generic_defaults(&self, def: GenericDef) -> Substs;
171 171
172 #[salsa::invoke(crate::expr::body_with_source_map_query)] 172 #[salsa::invoke(crate::expr::body_with_source_map_query)]
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 9929331d3..521e47090 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -11,8 +11,8 @@ use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 path::Path, 12 path::Path,
13 type_ref::TypeRef, 13 type_ref::TypeRef,
14 AdtDef, AsName, Container, Enum, Function, HasSource, ImplBlock, Name, Struct, Trait, 14 AdtDef, AsName, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct,
15 TypeAlias, Union, 15 Trait, TypeAlias, Union,
16}; 16};
17 17
18/// Data about a generic parameter (to a function, struct, impl, ...). 18/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -50,8 +50,11 @@ pub enum GenericDef {
50 Trait(Trait), 50 Trait(Trait),
51 TypeAlias(TypeAlias), 51 TypeAlias(TypeAlias),
52 ImplBlock(ImplBlock), 52 ImplBlock(ImplBlock),
53 // enum variants cannot have generics themselves, but their parent enums
54 // can, and this makes some code easier to write
55 EnumVariant(EnumVariant),
53} 56}
54impl_froms!(GenericDef: Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock); 57impl_froms!(GenericDef: Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, EnumVariant);
55 58
56impl GenericParams { 59impl GenericParams {
57 pub(crate) fn generic_params_query( 60 pub(crate) fn generic_params_query(
@@ -62,6 +65,7 @@ impl GenericParams {
62 let parent = match def { 65 let parent = match def {
63 GenericDef::Function(it) => it.container(db).map(GenericDef::from), 66 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
64 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), 67 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
68 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()),
65 GenericDef::Struct(_) 69 GenericDef::Struct(_)
66 | GenericDef::Union(_) 70 | GenericDef::Union(_)
67 | GenericDef::Enum(_) 71 | GenericDef::Enum(_)
@@ -86,6 +90,7 @@ impl GenericParams {
86 } 90 }
87 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).ast, start), 91 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).ast, start),
88 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).ast, start), 92 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).ast, start),
93 GenericDef::EnumVariant(_) => {}
89 } 94 }
90 95
91 Arc::new(generics) 96 Arc::new(generics)
@@ -184,6 +189,7 @@ impl GenericDef {
184 GenericDef::Trait(inner) => inner.resolver(db), 189 GenericDef::Trait(inner) => inner.resolver(db),
185 GenericDef::TypeAlias(inner) => inner.resolver(db), 190 GenericDef::TypeAlias(inner) => inner.resolver(db),
186 GenericDef::ImplBlock(inner) => inner.resolver(db), 191 GenericDef::ImplBlock(inner) => inner.resolver(db),
192 GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db),
187 } 193 }
188 } 194 }
189} 195}
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index c8be27e54..e2a7639b0 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -221,6 +221,18 @@ impl Resolver {
221 pub(crate) fn krate(&self) -> Option<Crate> { 221 pub(crate) fn krate(&self) -> Option<Crate> {
222 self.module().map(|t| t.0.krate()) 222 self.module().map(|t| t.0.krate())
223 } 223 }
224
225 pub(crate) fn where_predicates_in_scope<'a>(
226 &'a self,
227 ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a {
228 self.scopes
229 .iter()
230 .filter_map(|scope| match scope {
231 Scope::GenericParams(params) => Some(params),
232 _ => None,
233 })
234 .flat_map(|params| params.where_predicates.iter())
235 }
224} 236}
225 237
226impl Resolver { 238impl Resolver {
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 11afdc0f3..d8c7945e1 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -23,8 +23,8 @@ pub(crate) use autoderef::autoderef;
23pub(crate) use infer::{infer_query, InferTy, InferenceResult}; 23pub(crate) use infer::{infer_query, InferTy, InferenceResult};
24pub use lower::CallableDef; 24pub use lower::CallableDef;
25pub(crate) use lower::{ 25pub(crate) use lower::{
26 callable_item_sig, generic_defaults, generic_predicates, type_for_def, type_for_field, 26 callable_item_sig, generic_defaults_query, generic_predicates_query, type_for_def,
27 TypableDef, 27 type_for_field, TypableDef,
28}; 28};
29pub(crate) use traits::ProjectionPredicate; 29pub(crate) use traits::ProjectionPredicate;
30 30
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index a23daabc2..e79e5e223 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -849,8 +849,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
849 fn register_obligations_for_call(&mut self, callable_ty: &Ty) { 849 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
850 if let Ty::Apply(a_ty) = callable_ty { 850 if let Ty::Apply(a_ty) = callable_ty {
851 if let TypeCtor::FnDef(def) = a_ty.ctor { 851 if let TypeCtor::FnDef(def) = a_ty.ctor {
852 let generic_predicates = self.db.generic_predicates(def.into());
853 for predicate in generic_predicates.iter() {
854 let predicate = predicate.clone().subst(&a_ty.parameters);
855 if let Some(obligation) = Obligation::from_predicate(predicate) {
856 self.obligations.push(obligation);
857 }
858 }
852 // add obligation for trait implementation, if this is a trait method 859 // add obligation for trait implementation, if this is a trait method
853 // FIXME also register obligations from where clauses from the trait or impl and method
854 match def { 860 match def {
855 CallableDef::Function(f) => { 861 CallableDef::Function(f) => {
856 if let Some(trait_) = f.parent_trait(self.db) { 862 if let Some(trait_) = f.parent_trait(self.db) {
@@ -992,7 +998,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
992 (Vec::new(), Ty::Unknown) 998 (Vec::new(), Ty::Unknown)
993 } 999 }
994 }; 1000 };
995 // FIXME register obligations from where clauses from the function 1001 self.register_obligations_for_call(&callee_ty);
996 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); 1002 let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown));
997 for (arg, param) in args.iter().zip(param_iter) { 1003 for (arg, param) in args.iter().zip(param_iter) {
998 self.infer_expr(*arg, &Expectation::has_type(param)); 1004 self.infer_expr(*arg, &Expectation::has_type(param));
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 8b1b2a7f9..b48ada760 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -318,15 +318,13 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
318} 318}
319 319
320/// Resolve the where clause(s) of an item with generics. 320/// Resolve the where clause(s) of an item with generics.
321pub(crate) fn generic_predicates( 321pub(crate) fn generic_predicates_query(
322 db: &impl HirDatabase, 322 db: &impl HirDatabase,
323 def: GenericDef, 323 def: GenericDef,
324) -> Arc<[GenericPredicate]> { 324) -> Arc<[GenericPredicate]> {
325 let resolver = def.resolver(db); 325 let resolver = def.resolver(db);
326 let generic_params = def.generic_params(db); 326 let predicates = resolver
327 let predicates = generic_params 327 .where_predicates_in_scope()
328 .where_predicates
329 .iter()
330 .map(|pred| { 328 .map(|pred| {
331 TraitRef::for_where_predicate(db, &resolver, pred) 329 TraitRef::for_where_predicate(db, &resolver, pred)
332 .map_or(GenericPredicate::Error, GenericPredicate::Implemented) 330 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
@@ -336,7 +334,7 @@ pub(crate) fn generic_predicates(
336} 334}
337 335
338/// Resolve the default type params from generics 336/// Resolve the default type params from generics
339pub(crate) fn generic_defaults(db: &impl HirDatabase, def: GenericDef) -> Substs { 337pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> Substs {
340 let resolver = def.resolver(db); 338 let resolver = def.resolver(db);
341 let generic_params = def.generic_params(db); 339 let generic_params = def.generic_params(db);
342 340
@@ -511,3 +509,13 @@ pub enum CallableDef {
511 EnumVariant(EnumVariant), 509 EnumVariant(EnumVariant),
512} 510}
513impl_froms!(CallableDef: Function, Struct, EnumVariant); 511impl_froms!(CallableDef: Function, Struct, EnumVariant);
512
513impl From<CallableDef> for GenericDef {
514 fn from(def: CallableDef) -> GenericDef {
515 match def {
516 CallableDef::Function(f) => f.into(),
517 CallableDef::Struct(s) => s.into(),
518 CallableDef::EnumVariant(e) => e.into(),
519 }
520 }
521}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 20fa74fb4..aacd94a26 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2232,16 +2232,18 @@ fn test() {
2232} 2232}
2233"#), 2233"#),
2234 @r###" 2234 @r###"
2235[86; 87) 't': T 2235 â‹®
2236[92; 94) '{}': () 2236 â‹®[86; 87) 't': T
2237[105; 144) '{ ...(s); }': () 2237 â‹®[92; 94) '{}': ()
2238[115; 116) 's': S<{unknown}> 2238 â‹®[105; 144) '{ ...(s); }': ()
2239[119; 120) 'S': S<{unknown}>(T) -> S<T> 2239 â‹®[115; 116) 's': S<u32>
2240[119; 129) 'S(unknown)': S<{unknown}> 2240 â‹®[119; 120) 'S': S<u32>(T) -> S<T>
2241[121; 128) 'unknown': {unknown} 2241 â‹®[119; 129) 'S(unknown)': S<u32>
2242[135; 138) 'foo': fn foo<S<{unknown}>>(T) -> () 2242 â‹®[121; 128) 'unknown': u32
2243[135; 141) 'foo(s)': () 2243 â‹®[135; 138) 'foo': fn foo<S<u32>>(T) -> ()
2244[139; 140) 's': S<{unknown}>"### 2244 â‹®[135; 141) 'foo(s)': ()
2245 â‹®[139; 140) 's': S<u32>
2246 "###
2245 ); 2247 );
2246} 2248}
2247 2249
@@ -2259,17 +2261,19 @@ fn test() {
2259} 2261}
2260"#), 2262"#),
2261 @r###" 2263 @r###"
2262[87; 88) 't': T 2264 â‹®
2263[98; 100) '{}': () 2265 â‹®[87; 88) 't': T
2264[111; 163) '{ ...(s); }': () 2266 â‹®[98; 100) '{}': ()
2265[121; 122) 's': S<{unknown}> 2267 â‹®[111; 163) '{ ...(s); }': ()
2266[125; 126) 'S': S<{unknown}>(T) -> S<T> 2268 â‹®[121; 122) 's': S<u32>
2267[125; 135) 'S(unknown)': S<{unknown}> 2269 â‹®[125; 126) 'S': S<u32>(T) -> S<T>
2268[127; 134) 'unknown': {unknown} 2270 â‹®[125; 135) 'S(unknown)': S<u32>
2269[145; 146) 'x': u32 2271 â‹®[127; 134) 'unknown': u32
2270[154; 157) 'foo': fn foo<u32, S<{unknown}>>(T) -> U 2272 â‹®[145; 146) 'x': u32
2271[154; 160) 'foo(s)': u32 2273 â‹®[154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U
2272[158; 159) 's': S<{unknown}>"### 2274 â‹®[154; 160) 'foo(s)': u32
2275 â‹®[158; 159) 's': S<u32>
2276 "###
2273 ); 2277 );
2274} 2278}
2275 2279
@@ -2822,6 +2826,94 @@ fn test(s: S) {
2822 assert_eq!(t, "{unknown}"); 2826 assert_eq!(t, "{unknown}");
2823} 2827}
2824 2828
2829#[test]
2830fn obligation_from_function_clause() {
2831 let t = type_at(
2832 r#"
2833//- /main.rs
2834struct S;
2835
2836trait Trait<T> {}
2837impl Trait<u32> for S {}
2838
2839fn foo<T: Trait<U>, U>(t: T) -> U {}
2840
2841fn test(s: S) {
2842 foo(s)<|>;
2843}
2844"#,
2845 );
2846 assert_eq!(t, "u32");
2847}
2848
2849#[test]
2850fn obligation_from_method_clause() {
2851 let t = type_at(
2852 r#"
2853//- /main.rs
2854struct S;
2855
2856trait Trait<T> {}
2857impl Trait<isize> for S {}
2858
2859struct O;
2860impl O {
2861 fn foo<T: Trait<U>, U>(&self, t: T) -> U {}
2862}
2863
2864fn test() {
2865 O.foo(S)<|>;
2866}
2867"#,
2868 );
2869 assert_eq!(t, "isize");
2870}
2871
2872#[test]
2873fn obligation_from_self_method_clause() {
2874 let t = type_at(
2875 r#"
2876//- /main.rs
2877struct S;
2878
2879trait Trait<T> {}
2880impl Trait<i64> for S {}
2881
2882impl S {
2883 fn foo<U>(&self) -> U where Self: Trait<U> {}
2884}
2885
2886fn test() {
2887 S.foo()<|>;
2888}
2889"#,
2890 );
2891 assert_eq!(t, "i64");
2892}
2893
2894#[test]
2895fn obligation_from_impl_clause() {
2896 let t = type_at(
2897 r#"
2898//- /main.rs
2899struct S;
2900
2901trait Trait<T> {}
2902impl Trait<&str> for S {}
2903
2904struct O<T>;
2905impl<U, T: Trait<U>> O<T> {
2906 fn foo(&self) -> U {}
2907}
2908
2909fn test(o: O<S>) {
2910 o.foo()<|>;
2911}
2912"#,
2913 );
2914 assert_eq!(t, "&str");
2915}
2916
2825fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 2917fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2826 let file = db.parse(pos.file_id).ok().unwrap(); 2918 let file = db.parse(pos.file_id).ok().unwrap();
2827 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 2919 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index cff4de316..23a26a971 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -7,7 +7,7 @@ use parking_lot::Mutex;
7use ra_prof::profile; 7use ra_prof::profile;
8use rustc_hash::FxHashSet; 8use rustc_hash::FxHashSet;
9 9
10use super::{Canonical, ProjectionTy, TraitRef, Ty}; 10use super::{Canonical, GenericPredicate, ProjectionTy, TraitRef, Ty};
11use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 11use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
12 12
13use self::chalk::{from_chalk, ToChalk}; 13use self::chalk::{from_chalk, ToChalk};
@@ -78,6 +78,15 @@ pub enum Obligation {
78 // Projection(ProjectionPredicate), 78 // Projection(ProjectionPredicate),
79} 79}
80 80
81impl Obligation {
82 pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> {
83 match predicate {
84 GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
85 GenericPredicate::Error => None,
86 }
87 }
88}
89
81#[derive(Clone, Debug, PartialEq, Eq, Hash)] 90#[derive(Clone, Debug, PartialEq, Eq, Hash)]
82pub struct ProjectionPredicate { 91pub struct ProjectionPredicate {
83 pub projection_ty: ProjectionTy, 92 pub projection_ty: ProjectionTy,
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 2a0537bc3..4c3744b44 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -428,11 +428,7 @@ pub(crate) fn struct_datum_query(
428 CallableDef::Struct(s) => s.module(db).krate(db), 428 CallableDef::Struct(s) => s.module(db).krate(db),
429 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db), 429 CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db),
430 } != Some(krate); 430 } != Some(krate);
431 let generic_def: GenericDef = match callable { 431 let generic_def: GenericDef = callable.into();
432 CallableDef::Function(f) => f.into(),
433 CallableDef::Struct(s) => s.into(),
434 CallableDef::EnumVariant(v) => v.parent_enum(db).into(),
435 };
436 let generic_params = generic_def.generic_params(db); 432 let generic_params = generic_def.generic_params(db);
437 let bound_vars = Substs::bound_vars(&generic_params); 433 let bound_vars = Substs::bound_vars(&generic_params);
438 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); 434 let where_clauses = convert_where_clauses(db, generic_def, &bound_vars);
diff --git a/crates/ra_ide_api/src/completion/complete_postfix.rs b/crates/ra_ide_api/src/completion/complete_postfix.rs
index 7042d8bff..a25e517f5 100644
--- a/crates/ra_ide_api/src/completion/complete_postfix.rs
+++ b/crates/ra_ide_api/src/completion/complete_postfix.rs
@@ -51,22 +51,82 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
51 51
52#[cfg(test)] 52#[cfg(test)]
53mod tests { 53mod tests {
54 use crate::completion::{check_completion, CompletionKind}; 54 use crate::completion::{do_completion, CompletionItem, CompletionKind};
55 use insta::assert_debug_snapshot_matches;
55 56
56 fn check_snippet_completion(test_name: &str, code: &str) { 57 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> {
57 check_completion(test_name, code, CompletionKind::Postfix); 58 do_completion(code, CompletionKind::Postfix)
58 } 59 }
59 60
60 #[test] 61 #[test]
61 fn postfix_completion_works_for_trivial_path_expression() { 62 fn postfix_completion_works_for_trivial_path_expression() {
62 check_snippet_completion( 63 assert_debug_snapshot_matches!(
63 "postfix_completion_works_for_trivial_path_expression", 64 do_postfix_completion(
64 r#" 65 r#"
65 fn main() { 66 fn main() {
66 let bar = "a"; 67 let bar = "a";
67 bar.<|> 68 bar.<|>
68 } 69 }
69 "#, 70 "#,
71 ),
72 @r###"[
73 CompletionItem {
74 label: "box",
75 source_range: [88; 88),
76 delete: [84; 88),
77 insert: "Box::new(bar)",
78 detail: "Box::new(expr)",
79 },
80 CompletionItem {
81 label: "dbg",
82 source_range: [88; 88),
83 delete: [84; 88),
84 insert: "dbg!(bar)",
85 detail: "dbg!(expr)",
86 },
87 CompletionItem {
88 label: "if",
89 source_range: [88; 88),
90 delete: [84; 88),
91 insert: "if bar {$0}",
92 detail: "if expr {}",
93 },
94 CompletionItem {
95 label: "match",
96 source_range: [88; 88),
97 delete: [84; 88),
98 insert: "match bar {\n ${1:_} => {$0\\},\n}",
99 detail: "match expr {}",
100 },
101 CompletionItem {
102 label: "not",
103 source_range: [88; 88),
104 delete: [84; 88),
105 insert: "!bar",
106 detail: "!expr",
107 },
108 CompletionItem {
109 label: "ref",
110 source_range: [88; 88),
111 delete: [84; 88),
112 insert: "&bar",
113 detail: "&expr",
114 },
115 CompletionItem {
116 label: "refm",
117 source_range: [88; 88),
118 delete: [84; 88),
119 insert: "&mut bar",
120 detail: "&mut expr",
121 },
122 CompletionItem {
123 label: "while",
124 source_range: [88; 88),
125 delete: [84; 88),
126 insert: "while bar {\n$0\n}",
127 detail: "while expr {}",
128 },
129]"###
70 ); 130 );
71 } 131 }
72} 132}
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__postfix_completion_works_for_trivial_path_expression.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__postfix_completion_works_for_trivial_path_expression.snap
deleted file mode 100644
index c1a40b7b4..000000000
--- a/crates/ra_ide_api/src/completion/snapshots/completion_item__postfix_completion_works_for_trivial_path_expression.snap
+++ /dev/null
@@ -1,64 +0,0 @@
1---
2created: "2019-06-23T13:01:08.775536006Z"
3creator: [email protected]
4source: crates/ra_ide_api/src/completion/completion_item.rs
5expression: kind_completions
6---
7[
8 CompletionItem {
9 label: "box",
10 source_range: [76; 76),
11 delete: [72; 76),
12 insert: "Box::new(bar)",
13 detail: "Box::new(expr)",
14 },
15 CompletionItem {
16 label: "dbg",
17 source_range: [76; 76),
18 delete: [72; 76),
19 insert: "dbg!(bar)",
20 detail: "dbg!(expr)",
21 },
22 CompletionItem {
23 label: "if",
24 source_range: [76; 76),
25 delete: [72; 76),
26 insert: "if bar {$0}",
27 detail: "if expr {}",
28 },
29 CompletionItem {
30 label: "match",
31 source_range: [76; 76),
32 delete: [72; 76),
33 insert: "match bar {\n ${1:_} => {$0\\},\n}",
34 detail: "match expr {}",
35 },
36 CompletionItem {
37 label: "not",
38 source_range: [76; 76),
39 delete: [72; 76),
40 insert: "!bar",
41 detail: "!expr",
42 },
43 CompletionItem {
44 label: "ref",
45 source_range: [76; 76),
46 delete: [72; 76),
47 insert: "&bar",
48 detail: "&expr",
49 },
50 CompletionItem {
51 label: "refm",
52 source_range: [76; 76),
53 delete: [72; 76),
54 insert: "&mut bar",
55 detail: "&mut expr",
56 },
57 CompletionItem {
58 label: "while",
59 source_range: [76; 76),
60 delete: [72; 76),
61 insert: "while bar {\n$0\n}",
62 detail: "while expr {}",
63 },
64]