aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-06-28 20:17:27 +0100
committerFlorian Diebold <[email protected]>2020-07-01 19:40:38 +0100
commitd5d485ef9289589332893f2c0ad96cb366afe9d6 (patch)
tree2a722d6d6c4b41aa4bd0479e5eca2dd5250d1588 /crates/ra_hir_ty/src/method_resolution.rs
parent4a19d5954a4665a7a8572f9592f855f68cf0f2c6 (diff)
Implement Chalk variable kinds
This means we need to keep track of the kinds (general/int/float) of variables in `Canonical`, which requires some more ceremony. (It also exposes some places where we're not really dealing with canonicalization correctly -- another thing to be cleaned up when we switch to using Chalk's types directly.) Should fix the last remaining issue of #2534.
Diffstat (limited to 'crates/ra_hir_ty/src/method_resolution.rs')
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs32
1 files changed, 17 insertions, 15 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index c19519cf1..c3edd6885 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -2,7 +2,7 @@
2//! For details about how this works in rustc, see the method lookup page in the 2//! For details about how this works in rustc, see the method lookup page in the
3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html) 3//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs. 4//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
5use std::sync::Arc; 5use std::{iter, sync::Arc};
6 6
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
@@ -17,7 +17,8 @@ use rustc_hash::{FxHashMap, FxHashSet};
17use super::Substs; 17use super::Substs;
18use crate::{ 18use crate::{
19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy, 19 autoderef, db::HirDatabase, primitive::FloatBitness, utils::all_super_traits, ApplicationTy,
20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 20 Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, TypeCtor,
21 TypeWalk,
21}; 22};
22 23
23/// This is used as a key for indexing impls. 24/// This is used as a key for indexing impls.
@@ -377,7 +378,7 @@ fn iterate_method_candidates_with_autoref(
377 return true; 378 return true;
378 } 379 }
379 let refed = Canonical { 380 let refed = Canonical {
380 num_vars: deref_chain[0].num_vars, 381 kinds: deref_chain[0].kinds.clone(),
381 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 382 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
382 }; 383 };
383 if iterate_method_candidates_by_receiver( 384 if iterate_method_candidates_by_receiver(
@@ -393,7 +394,7 @@ fn iterate_method_candidates_with_autoref(
393 return true; 394 return true;
394 } 395 }
395 let ref_muted = Canonical { 396 let ref_muted = Canonical {
396 num_vars: deref_chain[0].num_vars, 397 kinds: deref_chain[0].kinds.clone(),
397 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 398 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
398 }; 399 };
399 if iterate_method_candidates_by_receiver( 400 if iterate_method_candidates_by_receiver(
@@ -612,18 +613,19 @@ pub(crate) fn inherent_impl_substs(
612 // we create a var for each type parameter of the impl; we need to keep in 613 // we create a var for each type parameter of the impl; we need to keep in
613 // mind here that `self_ty` might have vars of its own 614 // mind here that `self_ty` might have vars of its own
614 let vars = Substs::build_for_def(db, impl_id) 615 let vars = Substs::build_for_def(db, impl_id)
615 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.num_vars) 616 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len())
616 .build(); 617 .build();
617 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 618 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
618 let self_ty_with_vars = 619 let mut kinds = self_ty.kinds.to_vec();
619 Canonical { num_vars: vars.len() + self_ty.num_vars, value: self_ty_with_vars }; 620 kinds.extend(iter::repeat(TyKind::General).take(vars.len()));
620 let substs = super::infer::unify(&self_ty_with_vars, self_ty); 621 let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) };
622 let substs = super::infer::unify(&tys);
621 // We only want the substs for the vars we added, not the ones from self_ty. 623 // We only want the substs for the vars we added, not the ones from self_ty.
622 // Also, if any of the vars we added are still in there, we replace them by 624 // Also, if any of the vars we added are still in there, we replace them by
623 // Unknown. I think this can only really happen if self_ty contained 625 // Unknown. I think this can only really happen if self_ty contained
624 // Unknown, and in that case we want the result to contain Unknown in those 626 // Unknown, and in that case we want the result to contain Unknown in those
625 // places again. 627 // places again.
626 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.num_vars)) 628 substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len()))
627} 629}
628 630
629/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 631/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
@@ -683,15 +685,15 @@ fn generic_implements_goal(
683 trait_: TraitId, 685 trait_: TraitId,
684 self_ty: Canonical<Ty>, 686 self_ty: Canonical<Ty>,
685) -> Canonical<InEnvironment<super::Obligation>> { 687) -> Canonical<InEnvironment<super::Obligation>> {
686 let num_vars = self_ty.num_vars; 688 let mut kinds = self_ty.kinds.to_vec();
687 let substs = super::Substs::build_for_def(db, trait_) 689 let substs = super::Substs::build_for_def(db, trait_)
688 .push(self_ty.value) 690 .push(self_ty.value)
689 .fill_with_bound_vars(DebruijnIndex::INNERMOST, num_vars) 691 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
690 .build(); 692 .build();
691 let num_vars = substs.len() - 1 + self_ty.num_vars; 693 kinds.extend(iter::repeat(TyKind::General).take(substs.len() - 1));
692 let trait_ref = TraitRef { trait_, substs }; 694 let trait_ref = TraitRef { trait_, substs };
693 let obligation = super::Obligation::Trait(trait_ref); 695 let obligation = super::Obligation::Trait(trait_ref);
694 Canonical { num_vars, value: InEnvironment::new(env, obligation) } 696 Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) }
695} 697}
696 698
697fn autoderef_method_receiver( 699fn autoderef_method_receiver(
@@ -704,9 +706,9 @@ fn autoderef_method_receiver(
704 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) = 706 if let Some(Ty::Apply(ApplicationTy { ctor: TypeCtor::Array, parameters })) =
705 deref_chain.last().map(|ty| &ty.value) 707 deref_chain.last().map(|ty| &ty.value)
706 { 708 {
707 let num_vars = deref_chain.last().unwrap().num_vars; 709 let kinds = deref_chain.last().unwrap().kinds.clone();
708 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone()); 710 let unsized_ty = Ty::apply(TypeCtor::Slice, parameters.clone());
709 deref_chain.push(Canonical { value: unsized_ty, num_vars }) 711 deref_chain.push(Canonical { value: unsized_ty, kinds })
710 } 712 }
711 deref_chain 713 deref_chain
712} 714}