aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-03-20 19:07:36 +0000
committerFlorian Diebold <[email protected]>2021-03-21 14:29:03 +0000
commitd8f8b495ad5c9e3676ddf7af53b23bb5b7f2fde0 (patch)
tree66d68e003d7fa1b311e1b4b99c01de6ea0984372 /crates
parent0623bb4d71725d6b07e8cef5665094581f951fc0 (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.rs5
-rw-r--r--crates/hir_ty/src/display.rs21
-rw-r--r--crates/hir_ty/src/lib.rs13
-rw-r--r--crates/hir_ty/src/lower.rs25
-rw-r--r--crates/hir_ty/src/tests/traits.rs5
-rw-r--r--crates/hir_ty/src/traits/chalk.rs2
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]
2275fn unselected_projection_in_trait_env_cycle_3() { 2275fn 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
2286fn test<T>() where T: Trait<OtherItem = T::Item> { 2285fn 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();