diff options
author | Edwin Cheng <[email protected]> | 2019-12-19 04:45:07 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-12-19 04:45:07 +0000 |
commit | dddee23f43a0e1939124a607ba534e69a810843a (patch) | |
tree | 02fd55e52fcd54b43f218303b9a9fc2fd7d623b0 /crates | |
parent | 242f0ae1d8e6766091a6050431c3d417a43a2a3e (diff) |
Add std::ops::Index support for infering
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 32 |
5 files changed, 63 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3b26e8337..9e37ac416 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -254,6 +254,7 @@ macro_rules! __known_path { | |||
254 | (std::ops::Try) => {}; | 254 | (std::ops::Try) => {}; |
255 | (std::ops::Neg) => {}; | 255 | (std::ops::Neg) => {}; |
256 | (std::ops::Not) => {}; | 256 | (std::ops::Not) => {}; |
257 | (std::ops::Index) => {}; | ||
257 | ($path:path) => { | 258 | ($path:path) => { |
258 | compile_error!("Please register your known path in the path module") | 259 | compile_error!("Please register your known path in the path module") |
259 | }; | 260 | }; |
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..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] |
430 | fn infer_ops_index() { | ||
431 | let (db, pos) = TestDB::with_position( | ||
432 | r#" | ||
433 | //- /main.rs crate:main deps:std | ||
434 | |||
435 | struct Bar; | ||
436 | struct Foo; | ||
437 | |||
438 | impl std::ops::Index<u32> for Bar { | ||
439 | type Output = Foo; | ||
440 | } | ||
441 | |||
442 | fn 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::*; | ||
451 | mod 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] | ||
430 | fn deref_trait() { | 462 | fn deref_trait() { |
431 | let t = type_at( | 463 | let t = type_at( |
432 | r#" | 464 | r#" |