aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/infer.rs22
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs12
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs32
3 files changed, 61 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 98ba05fc2..14bfdde3d 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -363,14 +363,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
363 } 363 }
364 364
365 fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty { 365 fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
366 self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
367 }
368
369 fn resolve_associated_type_with_params(
370 &mut self,
371 inner_ty: Ty,
372 assoc_ty: Option<TypeAliasId>,
373 params: &[Ty],
374 ) -> Ty {
366 match assoc_ty { 375 match assoc_ty {
367 Some(res_assoc_ty) => { 376 Some(res_assoc_ty) => {
368 let ty = self.table.new_type_var(); 377 let ty = self.table.new_type_var();
378 let mut builder = Substs::builder(1 + params.len()).push(inner_ty);
379 for ty in params {
380 builder = builder.push(ty.clone());
381 }
382
369 let projection = ProjectionPredicate { 383 let projection = ProjectionPredicate {
370 ty: ty.clone(), 384 ty: ty.clone(),
371 projection_ty: ProjectionTy { 385 projection_ty: ProjectionTy {
372 associated_ty: res_assoc_ty, 386 associated_ty: res_assoc_ty,
373 parameters: Substs::single(inner_ty), 387 parameters: builder.build(),
374 }, 388 },
375 }; 389 };
376 self.obligations.push(Obligation::Projection(projection)); 390 self.obligations.push(Obligation::Projection(projection));
@@ -517,6 +531,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
517 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 531 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
518 Some(struct_.into()) 532 Some(struct_.into())
519 } 533 }
534
535 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
536 let path = path![std::ops::Index];
537 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
538 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
539 }
520} 540}
521 541
522/// The kinds of placeholders we need during type inference. There's separate 542/// The kinds of placeholders we need during type inference. There's separate
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index 924ad3e81..011c6c5c6 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -422,10 +422,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
422 } 422 }
423 } 423 }
424 Expr::Index { base, index } => { 424 Expr::Index { base, index } => {
425 let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); 425 let base_ty = self.infer_expr_inner(*base, &Expectation::none());
426 let _index_ty = self.infer_expr(*index, &Expectation::none()); 426 let index_ty = self.infer_expr(*index, &Expectation::none());
427 // FIXME: use `std::ops::Index::Output` to figure out the real return type 427
428 Ty::Unknown 428 self.resolve_associated_type_with_params(
429 base_ty,
430 self.resolve_ops_index_output(),
431 &[index_ty],
432 )
429 } 433 }
430 Expr::Tuple { exprs } => { 434 Expr::Tuple { exprs } => {
431 let mut tys = match &expected.ty { 435 let mut tys = match &expected.ty {
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 802937cb0..2d92a5eec 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -427,6 +427,38 @@ fn indexing_arrays() {
427} 427}
428 428
429#[test] 429#[test]
430fn infer_ops_index() {
431 let (db, pos) = TestDB::with_position(
432 r#"
433//- /main.rs crate:main deps:std
434
435struct Bar;
436struct Foo;
437
438impl std::ops::Index<u32> for Bar {
439 type Output = Foo;
440}
441
442fn test() {
443 let a = Bar;
444 let b = a[1];
445 b<|>;
446}
447
448//- /std.rs crate:std
449
450#[prelude_import] use ops::*;
451mod ops {
452 pub trait Index<Idx> {
453 type Output;
454 }
455}
456"#,
457 );
458 assert_eq!("Foo", type_at_pos(&db, pos));
459}
460
461#[test]
430fn deref_trait() { 462fn deref_trait() {
431 let t = type_at( 463 let t = type_at(
432 r#" 464 r#"