diff options
author | Florian Diebold <[email protected]> | 2021-03-20 19:07:36 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-03-21 14:29:03 +0000 |
commit | d8f8b495ad5c9e3676ddf7af53b23bb5b7f2fde0 (patch) | |
tree | 66d68e003d7fa1b311e1b4b99c01de6ea0984372 /crates | |
parent | 0623bb4d71725d6b07e8cef5665094581f951fc0 (diff) |
Ignore type bindings in generic_predicates_for_param
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.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 21 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 25 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 5 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 2 |
6 files changed, 52 insertions, 19 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index e34be7e42..568cb7eb9 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -2068,7 +2068,10 @@ impl Type { | |||
2068 | match pred { | 2068 | match pred { |
2069 | WhereClause::Implemented(trait_ref) => { | 2069 | WhereClause::Implemented(trait_ref) => { |
2070 | cb(type_.clone()); | 2070 | cb(type_.clone()); |
2071 | walk_substs(db, type_, &trait_ref.substitution, cb); | 2071 | // skip the self type. it's likely the type we just got the bounds from |
2072 | for ty in trait_ref.substitution.iter().skip(1) { | ||
2073 | walk_type(db, &type_.derived(ty.clone()), cb); | ||
2074 | } | ||
2072 | } | 2075 | } |
2073 | _ => (), | 2076 | _ => (), |
2074 | } | 2077 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 3845009ae..9d3b79be3 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -571,13 +571,22 @@ impl HirDisplay for Ty { | |||
571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 571 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
572 | } | 572 | } |
573 | TypeParamProvenance::ArgumentImplTrait => { | 573 | TypeParamProvenance::ArgumentImplTrait => { |
574 | let bounds = f.db.generic_predicates_for_param(id); | ||
575 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 574 | let substs = Substitution::type_params_for_generics(f.db, &generics); |
576 | write_bounds_like_dyn_trait_with_prefix( | 575 | let bounds = f |
577 | "impl", | 576 | .db |
578 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 577 | .generic_predicates(id.parent) |
579 | f, | 578 | .into_iter() |
580 | )?; | 579 | .map(|pred| pred.clone().subst(&substs)) |
580 | .filter(|wc| match &wc { | ||
581 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
582 | WhereClause::AliasEq(AliasEq { | ||
583 | alias: AliasTy::Projection(proj), | ||
584 | ty: _, | ||
585 | }) => proj.self_type_parameter() == self, | ||
586 | _ => false, | ||
587 | }) | ||
588 | .collect::<Vec<_>>(); | ||
589 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; | ||
581 | } | 590 | } |
582 | } | 591 | } |
583 | } | 592 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 815bb8418..ad908f957 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -940,10 +940,19 @@ impl Ty { | |||
940 | let param_data = &generic_params.types[id.local_id]; | 940 | let param_data = &generic_params.types[id.local_id]; |
941 | match param_data.provenance { | 941 | match param_data.provenance { |
942 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 942 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
943 | let substs = Substitution::type_params(db, id.parent); | ||
943 | let predicates = db | 944 | let predicates = db |
944 | .generic_predicates_for_param(id) | 945 | .generic_predicates(id.parent) |
945 | .into_iter() | 946 | .into_iter() |
946 | .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 | }) | ||
947 | .collect_vec(); | 956 | .collect_vec(); |
948 | 957 | ||
949 | Some(predicates) | 958 | Some(predicates) |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index cbbb535e5..2bdfcd310 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -189,7 +189,10 @@ impl<'a> TyLoweringContext<'a> { | |||
189 | let self_ty = | 189 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 192 | bounds |
193 | .iter() | ||
194 | .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) | ||
195 | .collect() | ||
193 | }); | 196 | }); |
194 | TyKind::Dyn(predicates).intern(&Interner) | 197 | TyKind::Dyn(predicates).intern(&Interner) |
195 | } | 198 | } |
@@ -666,6 +669,7 @@ impl<'a> TyLoweringContext<'a> { | |||
666 | pub(crate) fn lower_where_predicate( | 669 | pub(crate) fn lower_where_predicate( |
667 | &'a self, | 670 | &'a self, |
668 | where_predicate: &'a WherePredicate, | 671 | where_predicate: &'a WherePredicate, |
672 | ignore_bindings: bool, | ||
669 | ) -> impl Iterator<Item = WhereClause> + 'a { | 673 | ) -> impl Iterator<Item = WhereClause> + 'a { |
670 | match where_predicate { | 674 | match where_predicate { |
671 | WherePredicate::ForLifetime { target, bound, .. } | 675 | WherePredicate::ForLifetime { target, bound, .. } |
@@ -688,7 +692,9 @@ impl<'a> TyLoweringContext<'a> { | |||
688 | .intern(&Interner) | 692 | .intern(&Interner) |
689 | } | 693 | } |
690 | }; | 694 | }; |
691 | self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter() | 695 | self.lower_type_bound(bound, self_ty, ignore_bindings) |
696 | .collect::<Vec<_>>() | ||
697 | .into_iter() | ||
692 | } | 698 | } |
693 | WherePredicate::Lifetime { .. } => vec![].into_iter(), | 699 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
694 | } | 700 | } |
@@ -698,6 +704,7 @@ impl<'a> TyLoweringContext<'a> { | |||
698 | &'a self, | 704 | &'a self, |
699 | bound: &'a TypeBound, | 705 | bound: &'a TypeBound, |
700 | self_ty: Ty, | 706 | self_ty: Ty, |
707 | ignore_bindings: bool, | ||
701 | ) -> impl Iterator<Item = WhereClause> + 'a { | 708 | ) -> impl Iterator<Item = WhereClause> + 'a { |
702 | let mut bindings = None; | 709 | let mut bindings = None; |
703 | let trait_ref = match bound { | 710 | let trait_ref = match bound { |
@@ -711,6 +718,7 @@ impl<'a> TyLoweringContext<'a> { | |||
711 | trait_ref.into_iter().chain( | 718 | trait_ref.into_iter().chain( |
712 | bindings | 719 | bindings |
713 | .into_iter() | 720 | .into_iter() |
721 | .filter(move |_| !ignore_bindings) | ||
714 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), | 722 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), |
715 | ) | 723 | ) |
716 | } | 724 | } |
@@ -755,6 +763,7 @@ impl<'a> TyLoweringContext<'a> { | |||
755 | preds.extend(self.lower_type_bound( | 763 | preds.extend(self.lower_type_bound( |
756 | bound, | 764 | bound, |
757 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), | 765 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), |
766 | false, | ||
758 | )); | 767 | )); |
759 | } | 768 | } |
760 | preds | 769 | preds |
@@ -766,7 +775,7 @@ impl<'a> TyLoweringContext<'a> { | |||
766 | let self_ty = | 775 | let self_ty = |
767 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 776 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
768 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 777 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
769 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 778 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect() |
770 | }); | 779 | }); |
771 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | 780 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } |
772 | } | 781 | } |
@@ -896,7 +905,9 @@ pub(crate) fn generic_predicates_for_param_query( | |||
896 | }, | 905 | }, |
897 | WherePredicate::Lifetime { .. } => false, | 906 | WherePredicate::Lifetime { .. } => false, |
898 | }) | 907 | }) |
899 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 908 | .flat_map(|pred| { |
909 | ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p)) | ||
910 | }) | ||
900 | .collect() | 911 | .collect() |
901 | } | 912 | } |
902 | 913 | ||
@@ -918,7 +929,7 @@ pub(crate) fn trait_environment_query( | |||
918 | let mut traits_in_scope = Vec::new(); | 929 | let mut traits_in_scope = Vec::new(); |
919 | let mut clauses = Vec::new(); | 930 | let mut clauses = Vec::new(); |
920 | for pred in resolver.where_predicates_in_scope() { | 931 | for pred in resolver.where_predicates_in_scope() { |
921 | for pred in ctx.lower_where_predicate(pred) { | 932 | for pred in ctx.lower_where_predicate(pred, false) { |
922 | if let WhereClause::Implemented(tr) = &pred { | 933 | if let WhereClause::Implemented(tr) = &pred { |
923 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 934 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
924 | } | 935 | } |
@@ -967,7 +978,9 @@ pub(crate) fn generic_predicates_query( | |||
967 | let generics = generics(db.upcast(), def); | 978 | let generics = generics(db.upcast(), def); |
968 | resolver | 979 | resolver |
969 | .where_predicates_in_scope() | 980 | .where_predicates_in_scope() |
970 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 981 | .flat_map(|pred| { |
982 | ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p)) | ||
983 | }) | ||
971 | .collect() | 984 | .collect() |
972 | } | 985 | } |
973 | 986 | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 1bb6dff95..37cd04c6f 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -2273,8 +2273,7 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
2273 | 2273 | ||
2274 | #[test] | 2274 | #[test] |
2275 | fn unselected_projection_in_trait_env_cycle_3() { | 2275 | fn unselected_projection_in_trait_env_cycle_3() { |
2276 | // this is a cycle, although it would be possible to handle if we didn't go | 2276 | // this is a cycle for rustc; we currently accept it |
2277 | // into bindings when looking for traits | ||
2278 | check_types( | 2277 | check_types( |
2279 | r#" | 2278 | r#" |
2280 | //- /main.rs | 2279 | //- /main.rs |
@@ -2285,7 +2284,7 @@ trait Trait { | |||
2285 | 2284 | ||
2286 | fn test<T>() where T: Trait<OtherItem = T::Item> { | 2285 | fn test<T>() where T: Trait<OtherItem = T::Item> { |
2287 | let x: T::Item = no_matter; | 2286 | let x: T::Item = no_matter; |
2288 | } //^ {unknown} | 2287 | } //^ Trait::Item<T> |
2289 | "#, | 2288 | "#, |
2290 | ); | 2289 | ); |
2291 | } | 2290 | } |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 734679414..944145603 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -395,7 +395,7 @@ pub(crate) fn associated_ty_data_query( | |||
395 | let bounds = type_alias_data | 395 | let bounds = type_alias_data |
396 | .bounds | 396 | .bounds |
397 | .iter() | 397 | .iter() |
398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) | 398 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 399 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | 400 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) |
401 | .collect(); | 401 | .collect(); |