diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-21 16:42:08 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-21 16:42:08 +0000 |
commit | 35868c4f7dc479dd5f731a2785ec6a203046ea9c (patch) | |
tree | e78313acecc4fa84a11a2d8e7da7c85c98f940e0 /crates/hir_ty/src/lib.rs | |
parent | 1ae20d2b894171f0b8368309da727cd365b95fc1 (diff) | |
parent | d8f8b495ad5c9e3676ddf7af53b23bb5b7f2fde0 (diff) |
Merge #8133
8133: Ignore type bindings in generic_predicates_for_param (fix panic on ena and crates depending on it) r=flodiebold a=flodiebold
This allows us to handle more cases without a query cycle, which includes certain cases that rustc accepted. That in turn means we avoid triggering salsa-rs/salsa#257 on valid code (it will still happen if the user writes an actual cycle).
We actually accept more definitions than rustc now; that's because rustc only ignores bindings when looking up super traits, whereas we now also ignore them when looking for predicates to disambiguate associated type shorthand. We could introduce a separate query for super traits if necessary, but for now I think this should be fine.
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/hir_ty/src/lib.rs')
-rw-r--r-- | crates/hir_ty/src/lib.rs | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index c46529879..ad908f957 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, |
@@ -936,10 +940,19 @@ impl Ty { | |||
936 | let param_data = &generic_params.types[id.local_id]; | 940 | let param_data = &generic_params.types[id.local_id]; |
937 | match param_data.provenance { | 941 | match param_data.provenance { |
938 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 942 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
943 | let substs = Substitution::type_params(db, id.parent); | ||
939 | let predicates = db | 944 | let predicates = db |
940 | .generic_predicates_for_param(id) | 945 | .generic_predicates(id.parent) |
941 | .into_iter() | 946 | .into_iter() |
942 | .map(|pred| pred.value.clone()) | 947 | .map(|pred| pred.clone().subst(&substs)) |
948 | .filter(|wc| match &wc { | ||
949 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
950 | WhereClause::AliasEq(AliasEq { | ||
951 | alias: AliasTy::Projection(proj), | ||
952 | ty: _, | ||
953 | }) => proj.self_type_parameter() == self, | ||
954 | _ => false, | ||
955 | }) | ||
943 | .collect_vec(); | 956 | .collect_vec(); |
944 | 957 | ||
945 | Some(predicates) | 958 | Some(predicates) |