aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/path.rs1
-rw-r--r--crates/ra_hir_expand/src/name.rs1
-rw-r--r--crates/ra_hir_ty/src/infer.rs20
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs12
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs32
5 files changed, 61 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 7302cf0f1..00325cd99 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -257,6 +257,7 @@ macro_rules! __known_path {
257 (std::ops::Try) => {}; 257 (std::ops::Try) => {};
258 (std::ops::Neg) => {}; 258 (std::ops::Neg) => {};
259 (std::ops::Not) => {}; 259 (std::ops::Not) => {};
260 (std::ops::Index) => {};
260 ($path:path) => { 261 ($path:path) => {
261 compile_error!("Please register your known path in the path module") 262 compile_error!("Please register your known path in the path module")
262 }; 263 };
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index 59d8214fd..fd02ffa4e 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -161,6 +161,7 @@ pub mod known {
161 Range, 161 Range,
162 Neg, 162 Neg,
163 Not, 163 Not,
164 Index,
164 // Builtin macros 165 // Builtin macros
165 file, 166 file,
166 column, 167 column,
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 98ba05fc2..bbbc391c4 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -363,14 +363,26 @@ 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 builder = Substs::build_for_def(self.db, res_assoc_ty)
379 .push(inner_ty)
380 .fill(params.iter().cloned());
369 let projection = ProjectionPredicate { 381 let projection = ProjectionPredicate {
370 ty: ty.clone(), 382 ty: ty.clone(),
371 projection_ty: ProjectionTy { 383 projection_ty: ProjectionTy {
372 associated_ty: res_assoc_ty, 384 associated_ty: res_assoc_ty,
373 parameters: Substs::single(inner_ty), 385 parameters: builder.build(),
374 }, 386 },
375 }; 387 };
376 self.obligations.push(Obligation::Projection(projection)); 388 self.obligations.push(Obligation::Projection(projection));
@@ -517,6 +529,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
517 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; 529 let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
518 Some(struct_.into()) 530 Some(struct_.into())
519 } 531 }
532
533 fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
534 let path = path![std::ops::Index];
535 let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
536 self.db.trait_data(trait_).associated_type_by_name(&name![Output])
537 }
520} 538}
521 539
522/// The kinds of placeholders we need during type inference. There's separate 540/// 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 6917c183b..8be567917 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#"