diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 69 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 51 |
3 files changed, 124 insertions, 0 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index c46529879..815bb8418 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -106,6 +106,10 @@ impl ProjectionTy { | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | pub fn self_type_parameter(&self) -> &Ty { | ||
110 | &self.substitution[0] | ||
111 | } | ||
112 | |||
109 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 113 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
110 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { | 114 | match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container { |
111 | AssocContainerId::TraitId(it) => it, | 115 | AssocContainerId::TraitId(it) => it, |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0a4141e69..ad283c1e0 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -369,3 +369,72 @@ fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) { | |||
369 | actual.push('\n'); | 369 | actual.push('\n'); |
370 | expect.assert_eq(&actual); | 370 | expect.assert_eq(&actual); |
371 | } | 371 | } |
372 | |||
373 | #[test] | ||
374 | fn salsa_bug() { | ||
375 | let (mut db, pos) = TestDB::with_position( | ||
376 | " | ||
377 | //- /lib.rs | ||
378 | trait Index { | ||
379 | type Output; | ||
380 | } | ||
381 | |||
382 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
383 | |||
384 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
385 | type Key; | ||
386 | |||
387 | fn len(&self) -> usize; | ||
388 | } | ||
389 | |||
390 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
391 | fn push(&mut self, value: Self::Key); | ||
392 | } | ||
393 | |||
394 | fn main() { | ||
395 | let x = 1; | ||
396 | x.push(1);$0 | ||
397 | } | ||
398 | ", | ||
399 | ); | ||
400 | |||
401 | let module = db.module_for_file(pos.file_id); | ||
402 | let crate_def_map = module.def_map(&db); | ||
403 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
404 | db.infer(def); | ||
405 | }); | ||
406 | |||
407 | let new_text = " | ||
408 | //- /lib.rs | ||
409 | trait Index { | ||
410 | type Output; | ||
411 | } | ||
412 | |||
413 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
414 | |||
415 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
416 | type Key; | ||
417 | |||
418 | fn len(&self) -> usize; | ||
419 | } | ||
420 | |||
421 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
422 | fn push(&mut self, value: Self::Key); | ||
423 | } | ||
424 | |||
425 | fn main() { | ||
426 | |||
427 | let x = 1; | ||
428 | x.push(1); | ||
429 | } | ||
430 | " | ||
431 | .to_string(); | ||
432 | |||
433 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
434 | |||
435 | let module = db.module_for_file(pos.file_id); | ||
436 | let crate_def_map = module.def_map(&db); | ||
437 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
438 | db.infer(def); | ||
439 | }); | ||
440 | } | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 8f2bdffc0..1bb6dff95 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -2272,6 +2272,57 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | #[test] | 2274 | #[test] |
2275 | fn unselected_projection_in_trait_env_cycle_3() { | ||
2276 | // this is a cycle, although it would be possible to handle if we didn't go | ||
2277 | // into bindings when looking for traits | ||
2278 | check_types( | ||
2279 | r#" | ||
2280 | //- /main.rs | ||
2281 | trait Trait { | ||
2282 | type Item; | ||
2283 | type OtherItem; | ||
2284 | } | ||
2285 | |||
2286 | fn test<T>() where T: Trait<OtherItem = T::Item> { | ||
2287 | let x: T::Item = no_matter; | ||
2288 | } //^ {unknown} | ||
2289 | "#, | ||
2290 | ); | ||
2291 | } | ||
2292 | |||
2293 | #[test] | ||
2294 | fn unselected_projection_in_trait_env_no_cycle() { | ||
2295 | // this is not a cycle | ||
2296 | check_types( | ||
2297 | r#" | ||
2298 | //- /main.rs | ||
2299 | trait Index { | ||
2300 | type Output; | ||
2301 | } | ||
2302 | |||
2303 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
2304 | |||
2305 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
2306 | type Key; | ||
2307 | |||
2308 | fn len(&self) -> usize; | ||
2309 | } | ||
2310 | |||
2311 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
2312 | fn push(&mut self, value: Self::Key); | ||
2313 | } | ||
2314 | |||
2315 | fn test<T>(t: T) where T: UnificationStoreMut { | ||
2316 | let x; | ||
2317 | t.push(x); | ||
2318 | let y: Key<T>; | ||
2319 | (x, y); | ||
2320 | } //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | ||
2321 | "#, | ||
2322 | ); | ||
2323 | } | ||
2324 | |||
2325 | #[test] | ||
2275 | fn inline_assoc_type_bounds_1() { | 2326 | fn inline_assoc_type_bounds_1() { |
2276 | check_types( | 2327 | check_types( |
2277 | r#" | 2328 | r#" |