From 78fcc8b5bb1808d6bcc59b866b66377646484fb0 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sat, 30 Jan 2021 14:35:36 +0100 Subject: [PATCH 1/8] Generate clauses for opaque super traits like we do for dyn --- chalk-solve/src/clauses/dyn_ty.rs | 2 +- chalk-solve/src/clauses/program_clauses.rs | 13 +++++++++++-- tests/test/opaque_types.rs | 20 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index 33b85a427e0..eb5d878248c 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -84,7 +84,7 @@ pub(super) fn build_dyn_self_ty_clauses( /// Generate `Implemented` clauses for a `dyn Trait` type. We need to generate /// `Implemented` clauses for all super traits, and for each trait we require /// its where clauses. (See #203.) -fn push_dyn_ty_impl_clauses( +pub(super) fn push_dyn_ty_impl_clauses( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, trait_ref: TraitRef, diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 736684bc721..0429bfd10b0 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -195,10 +195,19 @@ impl ToProgramClauses for OpaqueTyDatum { let substitution = Substitution::from1(interner, alias_placeholder_ty); for bound in opaque_ty_bound.bounds { - // Implemented(!T<..>: Bound). let bound_with_placeholder_ty = bound.substitute(interner, &substitution); builder.push_binders(bound_with_placeholder_ty, |builder, bound| { - builder.push_fact(bound); + match bound { + WhereClause::Implemented(trait_ref) => { + super::dyn_ty::push_dyn_ty_impl_clauses(builder.db, builder, trait_ref) + } + WhereClause::AliasEq(_) => { + // Implemented(!T<..>: Bound). + builder.push_fact(bound); + } + WhereClause::LifetimeOutlives(_) => {} + WhereClause::TypeOutlives(_) => {} + } }); } }); diff --git a/tests/test/opaque_types.rs b/tests/test/opaque_types.rs index 108d465db36..088da1ea6e8 100644 --- a/tests/test/opaque_types.rs +++ b/tests/test/opaque_types.rs @@ -263,3 +263,23 @@ fn opaque_auto_traits_indirect() { } } } + +#[test] +fn opaque_super_trait() { + test! { + program { + trait Base {} + trait Super where Self: Base {} + impl Base for () {} + impl Super for () {} + + opaque type Opaque: Super = (); + } + + goal { + Opaque: Base + } yields { + "Unique" + } + } +} \ No newline at end of file From b9b6fd2b39585250b2c5fb2225956e41bfbaebf9 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sat, 30 Jan 2021 14:55:36 +0100 Subject: [PATCH 2/8] Move shared super trait code to new mod --- chalk-solve/src/clauses.rs | 1 + chalk-solve/src/clauses/dyn_ty.rs | 118 +-------------------- chalk-solve/src/clauses/program_clauses.rs | 4 +- chalk-solve/src/clauses/super_traits.rs | 115 ++++++++++++++++++++ 4 files changed, 122 insertions(+), 116 deletions(-) create mode 100644 chalk-solve/src/clauses/super_traits.rs diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index ea6851338e2..cbe78632a05 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -18,6 +18,7 @@ mod dyn_ty; mod env_elaborator; mod generalize; pub mod program_clauses; +mod super_traits; // yields the types "contained" in `app_ty` fn constituent_types(db: &dyn RustIrDatabase, ty: &TyKind) -> Vec> { diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index eb5d878248c..00dcf9b2282 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -1,11 +1,6 @@ -use rustc_hash::FxHashSet; - -use super::{builder::ClauseBuilder, generalize}; +use super::{builder::ClauseBuilder, generalize, super_traits::push_alias_ty_impl_clauses}; use crate::RustIrDatabase; -use chalk_ir::{ - cast::Cast, fold::shift::Shift, interner::Interner, Binders, BoundVar, DebruijnIndex, TraitId, - TraitRef, Ty, TyKind, WhereClause, -}; +use chalk_ir::{cast::Cast, interner::Interner, Ty, TyKind, WhereClause}; /// If the self type `S` of an `Implemented` goal is a `dyn trait` type, we wish /// to generate program-clauses that indicates that it implements its own @@ -70,7 +65,7 @@ pub(super) fn build_dyn_self_ty_clauses( builder.push_binders(qwc, |builder, wc| match &wc { // For the implemented traits, we need to elaborate super traits and add where clauses from the trait WhereClause::Implemented(trait_ref) => { - push_dyn_ty_impl_clauses(db, builder, trait_ref.clone()) + push_alias_ty_impl_clauses(db, builder, trait_ref.clone()) } // Associated item bindings are just taken as facts (?) WhereClause::AliasEq(_) => builder.push_fact(wc), @@ -80,110 +75,3 @@ pub(super) fn build_dyn_self_ty_clauses( } }); } - -/// Generate `Implemented` clauses for a `dyn Trait` type. We need to generate -/// `Implemented` clauses for all super traits, and for each trait we require -/// its where clauses. (See #203.) -pub(super) fn push_dyn_ty_impl_clauses( - db: &dyn RustIrDatabase, - builder: &mut ClauseBuilder<'_, I>, - trait_ref: TraitRef, -) { - let interner = db.interner(); - // We have some `dyn Trait`, and some `trait SuperTrait: WC` - // which is a super trait of `Trait` (including actually - // just being the same trait); then we want to push - // `Implemented(dyn Trait: SuperTrait) :- WC`. - - let super_trait_refs = - super_traits(db, trait_ref.trait_id).substitute(interner, &trait_ref.substitution); - - for q_super_trait_ref in super_trait_refs { - builder.push_binders(q_super_trait_ref.clone(), |builder, super_trait_ref| { - let trait_datum = db.trait_datum(super_trait_ref.trait_id); - let wc = trait_datum - .where_clauses() - .cloned() - .substitute(interner, &super_trait_ref.substitution); - builder.push_clause(super_trait_ref, wc); - }); - } -} - -pub fn super_traits( - db: &dyn RustIrDatabase, - trait_id: TraitId, -) -> Binders>>> { - let interner = db.interner(); - let mut seen_traits = FxHashSet::default(); - let trait_datum = db.trait_datum(trait_id); - let trait_ref = Binders::empty( - db.interner(), - TraitRef { - trait_id, - substitution: trait_datum - .binders - .identity_substitution(interner) - .shifted_in(interner), - }, - ); - let mut trait_refs = Vec::new(); - go(db, trait_ref, &mut seen_traits, &mut trait_refs); - - fn go( - db: &dyn RustIrDatabase, - trait_ref: Binders>, - seen_traits: &mut FxHashSet>, - trait_refs: &mut Vec>>, - ) { - let interner = db.interner(); - let trait_id = trait_ref.skip_binders().trait_id; - // Avoid cycles - if !seen_traits.insert(trait_id) { - return; - } - trait_refs.push(trait_ref.clone()); - let trait_datum = db.trait_datum(trait_id); - let super_trait_refs = trait_datum - .binders - .map_ref(|td| { - td.where_clauses - .iter() - .filter_map(|qwc| { - qwc.as_ref().filter_map(|wc| match wc { - WhereClause::Implemented(tr) => { - let self_ty = tr.self_type_parameter(db.interner()); - - // We're looking for where clauses - // of the form `Self: Trait`. That's - // ^1.0 because we're one binder in. - if self_ty.bound_var(db.interner()) - != Some(BoundVar::new(DebruijnIndex::ONE, 0)) - { - return None; - } - Some(tr.clone()) - } - WhereClause::AliasEq(_) => None, - WhereClause::LifetimeOutlives(..) => None, - WhereClause::TypeOutlives(..) => None, - }) - }) - .collect::>() - }) - // we skip binders on the trait_ref here and add them to the binders - // on the trait ref in the loop below. We could probably avoid this if - // we could turn the `Binders>` into a `Vec>` easily. - .substitute(db.interner(), &trait_ref.skip_binders().substitution); - for q_super_trait_ref in super_trait_refs { - // So now we need to combine the binders of trait_ref with the - // binders of super_trait_ref. - let actual_binders = Binders::new(trait_ref.binders.clone(), q_super_trait_ref); - let q_super_trait_ref = actual_binders.fuse_binders(interner); - go(db, q_super_trait_ref, seen_traits, trait_refs); - } - seen_traits.remove(&trait_id); - } - - Binders::new(trait_datum.binders.binders.clone(), trait_refs) -} diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 0429bfd10b0..1557c23548d 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -7,6 +7,8 @@ use chalk_ir::*; use std::iter; use tracing::instrument; +use super::super_traits::push_alias_ty_impl_clauses; + /// Trait for lowering a given piece of rust-ir source (e.g., an impl /// or struct definition) into its associated "program clauses" -- /// that is, into the lowered, logical rules that it defines. @@ -199,7 +201,7 @@ impl ToProgramClauses for OpaqueTyDatum { builder.push_binders(bound_with_placeholder_ty, |builder, bound| { match bound { WhereClause::Implemented(trait_ref) => { - super::dyn_ty::push_dyn_ty_impl_clauses(builder.db, builder, trait_ref) + push_alias_ty_impl_clauses(builder.db, builder, trait_ref) } WhereClause::AliasEq(_) => { // Implemented(!T<..>: Bound). diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs new file mode 100644 index 00000000000..8bc78f9439a --- /dev/null +++ b/chalk-solve/src/clauses/super_traits.rs @@ -0,0 +1,115 @@ +use rustc_hash::FxHashSet; + +use super::builder::ClauseBuilder; +use crate::RustIrDatabase; +use chalk_ir::{ + fold::shift::Shift, interner::Interner, Binders, BoundVar, DebruijnIndex, TraitId, TraitRef, + WhereClause, +}; + +/// Generate `Implemented` clauses for `dyn Trait` and opaque types. We need to generate +/// `Implemented` clauses for all super traits, and for each trait we require +/// its where clauses. (See #203.) +pub(super) fn push_alias_ty_impl_clauses( + db: &dyn RustIrDatabase, + builder: &mut ClauseBuilder<'_, I>, + trait_ref: TraitRef, +) { + let interner = db.interner(); + // We have some `dyn Trait`, and some `trait SuperTrait: WC` + // which is a super trait of `Trait` (including actually + // just being the same trait); then we want to push + // `Implemented(dyn Trait: SuperTrait) :- WC`. + + let super_trait_refs = + super_traits(db, trait_ref.trait_id).substitute(interner, &trait_ref.substitution); + + for q_super_trait_ref in super_trait_refs { + builder.push_binders(q_super_trait_ref.clone(), |builder, super_trait_ref| { + let trait_datum = db.trait_datum(super_trait_ref.trait_id); + let wc = trait_datum + .where_clauses() + .cloned() + .substitute(interner, &super_trait_ref.substitution); + builder.push_clause(super_trait_ref, wc); + }); + } +} + +pub fn super_traits( + db: &dyn RustIrDatabase, + trait_id: TraitId, +) -> Binders>>> { + let interner = db.interner(); + let mut seen_traits = FxHashSet::default(); + let trait_datum = db.trait_datum(trait_id); + let trait_ref = Binders::empty( + db.interner(), + TraitRef { + trait_id, + substitution: trait_datum + .binders + .identity_substitution(interner) + .shifted_in(interner), + }, + ); + let mut trait_refs = Vec::new(); + go(db, trait_ref, &mut seen_traits, &mut trait_refs); + + fn go( + db: &dyn RustIrDatabase, + trait_ref: Binders>, + seen_traits: &mut FxHashSet>, + trait_refs: &mut Vec>>, + ) { + let interner = db.interner(); + let trait_id = trait_ref.skip_binders().trait_id; + // Avoid cycles + if !seen_traits.insert(trait_id) { + return; + } + trait_refs.push(trait_ref.clone()); + let trait_datum = db.trait_datum(trait_id); + let super_trait_refs = trait_datum + .binders + .map_ref(|td| { + td.where_clauses + .iter() + .filter_map(|qwc| { + qwc.as_ref().filter_map(|wc| match wc { + WhereClause::Implemented(tr) => { + let self_ty = tr.self_type_parameter(db.interner()); + + // We're looking for where clauses + // of the form `Self: Trait`. That's + // ^1.0 because we're one binder in. + if self_ty.bound_var(db.interner()) + != Some(BoundVar::new(DebruijnIndex::ONE, 0)) + { + return None; + } + Some(tr.clone()) + } + WhereClause::AliasEq(_) => None, + WhereClause::LifetimeOutlives(..) => None, + WhereClause::TypeOutlives(..) => None, + }) + }) + .collect::>() + }) + // we skip binders on the trait_ref here and add them to the binders + // on the trait ref in the loop below. We could probably avoid this if + // we could turn the `Binders>` into a `Vec>` easily. + .substitute(db.interner(), &trait_ref.skip_binders().substitution); + for q_super_trait_ref in super_trait_refs { + // So now we need to combine the binders of trait_ref with the + // binders of super_trait_ref. + let actual_binders = Binders::new(trait_ref.binders.clone(), q_super_trait_ref); + let q_super_trait_ref = actual_binders.fuse_binders(interner); + go(db, q_super_trait_ref, seen_traits, trait_refs); + } + seen_traits.remove(&trait_id); + } + + Binders::new(trait_datum.binders.binders.clone(), trait_refs) +} From 01846027df16b2139d4975feae8f84bd50c05919 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sat, 30 Jan 2021 15:03:25 +0100 Subject: [PATCH 3/8] Deduplicate matching on bounds --- chalk-solve/src/clauses/dyn_ty.rs | 15 +++------------ chalk-solve/src/clauses/program_clauses.rs | 16 +--------------- chalk-solve/src/clauses/super_traits.rs | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index 00dcf9b2282..cdae733ea4c 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -1,6 +1,6 @@ -use super::{builder::ClauseBuilder, generalize, super_traits::push_alias_ty_impl_clauses}; +use super::{builder::ClauseBuilder, generalize}; use crate::RustIrDatabase; -use chalk_ir::{cast::Cast, interner::Interner, Ty, TyKind, WhereClause}; +use chalk_ir::{cast::Cast, interner::Interner, Ty, TyKind}; /// If the self type `S` of an `Implemented` goal is a `dyn trait` type, we wish /// to generate program-clauses that indicates that it implements its own @@ -62,16 +62,7 @@ pub(super) fn build_dyn_self_ty_clauses( .cloned() .substitute(interner, &[self_ty.clone().cast(interner)]); - builder.push_binders(qwc, |builder, wc| match &wc { - // For the implemented traits, we need to elaborate super traits and add where clauses from the trait - WhereClause::Implemented(trait_ref) => { - push_alias_ty_impl_clauses(db, builder, trait_ref.clone()) - } - // Associated item bindings are just taken as facts (?) - WhereClause::AliasEq(_) => builder.push_fact(wc), - WhereClause::LifetimeOutlives(..) => {} - WhereClause::TypeOutlives(..) => {} - }); + super::super_traits::push_alias_binders(builder, qwc); } }); } diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 1557c23548d..d094d8c5b76 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -7,8 +7,6 @@ use chalk_ir::*; use std::iter; use tracing::instrument; -use super::super_traits::push_alias_ty_impl_clauses; - /// Trait for lowering a given piece of rust-ir source (e.g., an impl /// or struct definition) into its associated "program clauses" -- /// that is, into the lowered, logical rules that it defines. @@ -198,19 +196,7 @@ impl ToProgramClauses for OpaqueTyDatum { let substitution = Substitution::from1(interner, alias_placeholder_ty); for bound in opaque_ty_bound.bounds { let bound_with_placeholder_ty = bound.substitute(interner, &substitution); - builder.push_binders(bound_with_placeholder_ty, |builder, bound| { - match bound { - WhereClause::Implemented(trait_ref) => { - push_alias_ty_impl_clauses(builder.db, builder, trait_ref) - } - WhereClause::AliasEq(_) => { - // Implemented(!T<..>: Bound). - builder.push_fact(bound); - } - WhereClause::LifetimeOutlives(_) => {} - WhereClause::TypeOutlives(_) => {} - } - }); + super::super_traits::push_alias_binders(builder, bound_with_placeholder_ty); } }); } diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs index 8bc78f9439a..dc709702283 100644 --- a/chalk-solve/src/clauses/super_traits.rs +++ b/chalk-solve/src/clauses/super_traits.rs @@ -7,10 +7,25 @@ use chalk_ir::{ WhereClause, }; +pub(super) fn push_alias_binders( + builder: &mut ClauseBuilder<'_, I>, + binders: Binders>, +) { + builder.push_binders(binders, |builder, bound| match &bound { + // For the implemented traits, we need to elaborate super traits and add where clauses from the trait + WhereClause::Implemented(trait_ref) => { + push_alias_ty_impl_clauses(builder.db, builder, trait_ref.clone()) + } + WhereClause::AliasEq(_) => builder.push_fact(bound), + WhereClause::LifetimeOutlives(..) => {} + WhereClause::TypeOutlives(..) => {} + }); +} + /// Generate `Implemented` clauses for `dyn Trait` and opaque types. We need to generate /// `Implemented` clauses for all super traits, and for each trait we require /// its where clauses. (See #203.) -pub(super) fn push_alias_ty_impl_clauses( +fn push_alias_ty_impl_clauses( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, trait_ref: TraitRef, From 5cb40c7d1d1aa9f5bbbe8f25a549a12021248117 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sat, 30 Jan 2021 15:20:09 +0100 Subject: [PATCH 4/8] Fix formatting --- tests/test/opaque_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test/opaque_types.rs b/tests/test/opaque_types.rs index 088da1ea6e8..fe028313ed6 100644 --- a/tests/test/opaque_types.rs +++ b/tests/test/opaque_types.rs @@ -282,4 +282,4 @@ fn opaque_super_trait() { "Unique" } } -} \ No newline at end of file +} From a27e8870a3b1266ab5813241f9d833b3a9b0b8b5 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 31 Jan 2021 09:02:19 +0100 Subject: [PATCH 5/8] Use more sensical naming --- chalk-solve/src/clauses/dyn_ty.rs | 2 +- chalk-solve/src/clauses/program_clauses.rs | 2 +- chalk-solve/src/clauses/super_traits.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index cdae733ea4c..df1451cdcc8 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -62,7 +62,7 @@ pub(super) fn build_dyn_self_ty_clauses( .cloned() .substitute(interner, &[self_ty.clone().cast(interner)]); - super::super_traits::push_alias_binders(builder, qwc); + super::super_traits::push_where_clause_binders(builder, qwc); } }); } diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index d094d8c5b76..01d8b8298c6 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -196,7 +196,7 @@ impl ToProgramClauses for OpaqueTyDatum { let substitution = Substitution::from1(interner, alias_placeholder_ty); for bound in opaque_ty_bound.bounds { let bound_with_placeholder_ty = bound.substitute(interner, &substitution); - super::super_traits::push_alias_binders(builder, bound_with_placeholder_ty); + super::super_traits::push_where_clause_binders(builder, bound_with_placeholder_ty); } }); } diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs index dc709702283..4f885f04cf6 100644 --- a/chalk-solve/src/clauses/super_traits.rs +++ b/chalk-solve/src/clauses/super_traits.rs @@ -7,14 +7,14 @@ use chalk_ir::{ WhereClause, }; -pub(super) fn push_alias_binders( +pub(super) fn push_where_clause_binders( builder: &mut ClauseBuilder<'_, I>, binders: Binders>, ) { builder.push_binders(binders, |builder, bound| match &bound { // For the implemented traits, we need to elaborate super traits and add where clauses from the trait WhereClause::Implemented(trait_ref) => { - push_alias_ty_impl_clauses(builder.db, builder, trait_ref.clone()) + push_trait_super_clauses(builder.db, builder, trait_ref.clone()) } WhereClause::AliasEq(_) => builder.push_fact(bound), WhereClause::LifetimeOutlives(..) => {} @@ -25,7 +25,7 @@ pub(super) fn push_alias_binders( /// Generate `Implemented` clauses for `dyn Trait` and opaque types. We need to generate /// `Implemented` clauses for all super traits, and for each trait we require /// its where clauses. (See #203.) -fn push_alias_ty_impl_clauses( +fn push_trait_super_clauses( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, trait_ref: TraitRef, From e0bc5f79acf630f3c6e7f2beb5662f51410664ba Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Sun, 31 Jan 2021 09:11:05 +0100 Subject: [PATCH 6/8] Fix unrelated build warning --- chalk-ir/src/could_match.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chalk-ir/src/could_match.rs b/chalk-ir/src/could_match.rs index c70a3be3f04..e0da91e34e2 100644 --- a/chalk-ir/src/could_match.rs +++ b/chalk-ir/src/could_match.rs @@ -33,7 +33,7 @@ where struct MatchZipper<'i, I> { interner: &'i I, db: &'i dyn UnificationDatabase, - }; + } impl<'i, I: Interner> Zipper<'i, I> for MatchZipper<'i, I> { fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> Fallible<()> { From 815263d89d938160014dd2db50600664ba103534 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Wed, 17 Feb 2021 12:28:39 +0100 Subject: [PATCH 7/8] Inline binder pushing to avoid generalizing too much --- chalk-solve/src/clauses/dyn_ty.rs | 17 +++++++++++++++-- chalk-solve/src/clauses/program_clauses.rs | 15 ++++++++++++++- chalk-solve/src/clauses/super_traits.rs | 17 +---------------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index df1451cdcc8..505da43f972 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -1,6 +1,6 @@ use super::{builder::ClauseBuilder, generalize}; use crate::RustIrDatabase; -use chalk_ir::{cast::Cast, interner::Interner, Ty, TyKind}; +use chalk_ir::{cast::Cast, interner::Interner, Ty, TyKind, WhereClause}; /// If the self type `S` of an `Implemented` goal is a `dyn trait` type, we wish /// to generate program-clauses that indicates that it implements its own @@ -62,7 +62,20 @@ pub(super) fn build_dyn_self_ty_clauses( .cloned() .substitute(interner, &[self_ty.clone().cast(interner)]); - super::super_traits::push_where_clause_binders(builder, qwc); + builder.push_binders(qwc, |builder, bound| match &bound { + // For the implemented traits, we need to elaborate super traits and add where clauses from the trait + WhereClause::Implemented(trait_ref) => { + super::super_traits::push_trait_super_clauses( + builder.db, + builder, + trait_ref.clone(), + ) + } + // FIXME: Associated item bindings are just taken as facts (?) + WhereClause::AliasEq(_) => builder.push_fact(bound), + WhereClause::LifetimeOutlives(..) => {} + WhereClause::TypeOutlives(..) => {} + }); } }); } diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 01d8b8298c6..19811ff8b30 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -196,7 +196,20 @@ impl ToProgramClauses for OpaqueTyDatum { let substitution = Substitution::from1(interner, alias_placeholder_ty); for bound in opaque_ty_bound.bounds { let bound_with_placeholder_ty = bound.substitute(interner, &substitution); - super::super_traits::push_where_clause_binders(builder, bound_with_placeholder_ty); + builder.push_binders(bound_with_placeholder_ty, |builder, bound| match &bound { + // For the implemented traits, we need to elaborate super traits and add where clauses from the trait + WhereClause::Implemented(trait_ref) => { + super::super_traits::push_trait_super_clauses( + builder.db, + builder, + trait_ref.clone(), + ) + } + // FIXME: Associated item bindings are just taken as facts (?) + WhereClause::AliasEq(_) => builder.push_fact(bound), + WhereClause::LifetimeOutlives(..) => {} + WhereClause::TypeOutlives(..) => {} + }); } }); } diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs index 4f885f04cf6..5bcc070575b 100644 --- a/chalk-solve/src/clauses/super_traits.rs +++ b/chalk-solve/src/clauses/super_traits.rs @@ -7,25 +7,10 @@ use chalk_ir::{ WhereClause, }; -pub(super) fn push_where_clause_binders( - builder: &mut ClauseBuilder<'_, I>, - binders: Binders>, -) { - builder.push_binders(binders, |builder, bound| match &bound { - // For the implemented traits, we need to elaborate super traits and add where clauses from the trait - WhereClause::Implemented(trait_ref) => { - push_trait_super_clauses(builder.db, builder, trait_ref.clone()) - } - WhereClause::AliasEq(_) => builder.push_fact(bound), - WhereClause::LifetimeOutlives(..) => {} - WhereClause::TypeOutlives(..) => {} - }); -} - /// Generate `Implemented` clauses for `dyn Trait` and opaque types. We need to generate /// `Implemented` clauses for all super traits, and for each trait we require /// its where clauses. (See #203.) -fn push_trait_super_clauses( +pub(super) fn push_trait_super_clauses( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, trait_ref: TraitRef, From 29ba9ee427d0755df22fa3c7d6aba929f03dc37b Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Wed, 17 Feb 2021 12:39:20 +0100 Subject: [PATCH 8/8] Rewrite comments to include both dyn and opaque types --- chalk-solve/src/clauses/super_traits.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/chalk-solve/src/clauses/super_traits.rs b/chalk-solve/src/clauses/super_traits.rs index 5bcc070575b..3110b03e8d1 100644 --- a/chalk-solve/src/clauses/super_traits.rs +++ b/chalk-solve/src/clauses/super_traits.rs @@ -16,10 +16,13 @@ pub(super) fn push_trait_super_clauses( trait_ref: TraitRef, ) { let interner = db.interner(); - // We have some `dyn Trait`, and some `trait SuperTrait: WC` - // which is a super trait of `Trait` (including actually - // just being the same trait); then we want to push - // `Implemented(dyn Trait: SuperTrait) :- WC`. + // Given`trait SuperTrait: WC`, which is a super trait + // of `Trait` (including actually just being the same trait); + // then we want to push + // - for `dyn Trait`: + // `Implemented(dyn Trait: SuperTrait) :- WC`. + // - for placeholder `!T` of `opaque type T: Trait = HiddenTy`: + // `Implemented(!T: SuperTrait) :- WC` let super_trait_refs = super_traits(db, trait_ref.trait_id).substitute(interner, &trait_ref.substitution);