summaryrefslogtreecommitdiffstats
path: root/vendor/chalk-solve-0.87.0/src/clauses.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/chalk-solve-0.87.0/src/clauses.rs
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chalk-solve-0.87.0/src/clauses.rs')
-rw-r--r--vendor/chalk-solve-0.87.0/src/clauses.rs1132
1 files changed, 0 insertions, 1132 deletions
diff --git a/vendor/chalk-solve-0.87.0/src/clauses.rs b/vendor/chalk-solve-0.87.0/src/clauses.rs
deleted file mode 100644
index e3fdd351b..000000000
--- a/vendor/chalk-solve-0.87.0/src/clauses.rs
+++ /dev/null
@@ -1,1132 +0,0 @@
-use self::builder::ClauseBuilder;
-use self::env_elaborator::elaborate_env_clauses;
-use self::program_clauses::ToProgramClauses;
-use crate::goal_builder::GoalBuilder;
-use crate::rust_ir::{Movability, WellKnownTrait};
-use crate::split::Split;
-use crate::RustIrDatabase;
-use chalk_ir::cast::{Cast, Caster};
-use chalk_ir::could_match::CouldMatch;
-use chalk_ir::interner::Interner;
-use chalk_ir::*;
-use rustc_hash::FxHashSet;
-use std::iter;
-use std::marker::PhantomData;
-use tracing::{debug, instrument};
-
-pub mod builder;
-mod builtin_traits;
-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<I: Interner>(db: &dyn RustIrDatabase<I>, ty: &TyKind<I>) -> Vec<Ty<I>> {
- let interner = db.interner();
-
- match ty {
- // For non-phantom_data adts we collect its variants/fields
- TyKind::Adt(adt_id, substitution) if !db.adt_datum(*adt_id).flags.phantom_data => {
- let adt_datum = &db.adt_datum(*adt_id);
- let adt_datum_bound = adt_datum.binders.clone().substitute(interner, substitution);
- adt_datum_bound
- .variants
- .into_iter()
- .flat_map(|variant| variant.fields.into_iter())
- .collect()
- }
- // And for `PhantomData<T>`, we pass `T`.
- TyKind::Adt(_, substitution)
- | TyKind::Tuple(_, substitution)
- | TyKind::FnDef(_, substitution) => substitution
- .iter(interner)
- .filter_map(|x| x.ty(interner))
- .cloned()
- .collect(),
-
- TyKind::Array(ty, _) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, _, ty) => {
- vec![ty.clone()]
- }
-
- TyKind::Str | TyKind::Never | TyKind::Scalar(_) => Vec::new(),
-
- TyKind::Generator(generator_id, substitution) => {
- let generator_datum = &db.generator_datum(*generator_id);
- let generator_datum_bound = generator_datum
- .input_output
- .clone()
- .substitute(interner, &substitution);
-
- let mut tys = generator_datum_bound.upvars;
- tys.push(
- TyKind::GeneratorWitness(*generator_id, substitution.clone()).intern(interner),
- );
- tys
- }
-
- TyKind::Closure(_, _) => panic!("this function should not be called for closures"),
- TyKind::GeneratorWitness(_, _) => {
- panic!("this function should not be called for generator witnesses")
- }
- TyKind::Function(_) => panic!("this function should not be called for functions"),
- TyKind::InferenceVar(_, _) | TyKind::BoundVar(_) => {
- panic!("this function should not be called for inference or bound vars")
- }
- TyKind::Placeholder(_) => panic!("this function should not be called for placeholders"),
- TyKind::Dyn(_) => panic!("this function should not be called for dyn types"),
- TyKind::Alias(_) => panic!("this function should not be called for alias"),
- TyKind::Foreign(_) => panic!("constituent_types of foreign types are unknown!"),
- TyKind::Error => Vec::new(),
- TyKind::OpaqueType(_, _) => panic!("constituent_types of opaque types are unknown!"),
- TyKind::AssociatedType(_, _) => {
- panic!("constituent_types of associated types are unknown!")
- }
- }
-}
-
-/// FIXME(#505) update comments for ADTs
-/// For auto-traits, we generate a default rule for every struct,
-/// unless there is a manual impl for that struct given explicitly.
-///
-/// So, if you have `impl Send for MyList<Foo>`, then we would
-/// generate no rule for `MyList` at all -- similarly if you have
-/// `impl !Send for MyList<Foo>`, or `impl<T> Send for MyList<T>`.
-///
-/// But if you have no rules at all for `Send` / `MyList`, then we
-/// generate an impl based on the field types of `MyList`. For example
-/// given the following program:
-///
-/// ```notrust
-/// #[auto] trait Send { }
-///
-/// struct MyList<T> {
-/// data: T,
-/// next: Box<Option<MyList<T>>>,
-/// }
-///
-/// ```
-///
-/// we generate:
-///
-/// ```notrust
-/// forall<T> {
-/// Implemented(MyList<T>: Send) :-
-/// Implemented(T: Send),
-/// Implemented(Box<Option<MyList<T>>>: Send).
-/// }
-/// ```
-#[instrument(level = "debug", skip(builder))]
-pub fn push_auto_trait_impls<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- auto_trait_id: TraitId<I>,
- ty: &TyKind<I>,
-) -> Result<(), Floundered> {
- let interner = builder.interner();
-
- // Must be an auto trait.
- assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
-
- // Auto traits never have generic parameters of their own (apart from `Self`).
- assert_eq!(
- builder.db.trait_datum(auto_trait_id).binders.len(interner),
- 1
- );
-
- // If there is a `impl AutoTrait for Foo<..>` or `impl !AutoTrait
- // for Foo<..>`, where `Foo` is the adt we're looking at, then
- // we don't generate our own rules.
- if builder.db.impl_provided_for(auto_trait_id, ty) {
- debug!("impl provided");
- return Ok(());
- }
-
- let mk_ref = |ty: Ty<I>| TraitRef {
- trait_id: auto_trait_id,
- substitution: Substitution::from1(interner, ty.cast(interner)),
- };
-
- let consequence = mk_ref(ty.clone().intern(interner));
-
- match ty {
- // function-types implement auto traits unconditionally
- TyKind::Function(_) => {
- builder.push_fact(consequence);
- Ok(())
- }
- TyKind::InferenceVar(_, _) | TyKind::BoundVar(_) => Err(Floundered),
-
- // auto traits are not implemented for foreign types
- TyKind::Foreign(_) => Ok(()),
-
- // closures require binders, while the other types do not
- TyKind::Closure(closure_id, substs) => {
- let closure_fn_substitution = builder.db.closure_fn_substitution(*closure_id, substs);
- let binders = builder.db.closure_upvars(*closure_id, substs);
- let upvars = binders.substitute(builder.db.interner(), &closure_fn_substitution);
-
- // in a same behavior as for non-auto traits (reuse the code) we can require that
- // every bound type must implement this auto-trait
- use crate::clauses::builtin_traits::needs_impl_for_tys;
- needs_impl_for_tys(builder.db, builder, consequence, Some(upvars).into_iter());
-
- Ok(())
- }
- TyKind::Generator(generator_id, _) => {
- if Some(auto_trait_id) == builder.db.well_known_trait_id(WellKnownTrait::Unpin) {
- match builder.db.generator_datum(*generator_id).movability {
- // immovable generators are never `Unpin`
- Movability::Static => (),
- // movable generators are always `Unpin`
- Movability::Movable => builder.push_fact(consequence),
- }
- } else {
- // if trait is not `Unpin`, use regular auto trait clause
- let conditions = constituent_types(builder.db, ty).into_iter().map(mk_ref);
- builder.push_clause(consequence, conditions);
- }
- Ok(())
- }
-
- TyKind::GeneratorWitness(generator_id, _) => {
- push_auto_trait_impls_generator_witness(builder, auto_trait_id, *generator_id);
- Ok(())
- }
-
- TyKind::OpaqueType(opaque_ty_id, _) => {
- push_auto_trait_impls_opaque(builder, auto_trait_id, *opaque_ty_id);
- Ok(())
- }
-
- // No auto traits
- TyKind::AssociatedType(_, _)
- | TyKind::Placeholder(_)
- | TyKind::Dyn(_)
- | TyKind::Alias(_) => Ok(()),
-
- // app_ty implements AutoTrait if all constituents of app_ty implement AutoTrait
- _ => {
- let conditions = constituent_types(builder.db, ty).into_iter().map(mk_ref);
-
- builder.push_clause(consequence, conditions);
- Ok(())
- }
- }
-}
-
-/// Leak auto traits for opaque types, just like `push_auto_trait_impls` does for structs.
-///
-/// For example, given the following program:
-///
-/// ```notrust
-/// #[auto] trait Send { }
-/// trait Trait { }
-/// struct Bar { }
-/// opaque type Foo: Trait = Bar
-/// ```
-/// Checking the goal `Foo: Send` would generate the following:
-///
-/// ```notrust
-/// Foo: Send :- Bar: Send
-/// ```
-#[instrument(level = "debug", skip(builder))]
-pub fn push_auto_trait_impls_opaque<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- auto_trait_id: TraitId<I>,
- opaque_id: OpaqueTyId<I>,
-) {
- let opaque_ty_datum = &builder.db.opaque_ty_data(opaque_id);
- let interner = builder.interner();
-
- // Must be an auto trait.
- assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
-
- // Auto traits never have generic parameters of their own (apart from `Self`).
- assert_eq!(
- builder.db.trait_datum(auto_trait_id).binders.len(interner),
- 1
- );
-
- let hidden_ty = builder.db.hidden_opaque_type(opaque_id);
- let binders = opaque_ty_datum.bound.clone();
- builder.push_binders(binders, |builder, _| {
- let self_ty =
- TyKind::OpaqueType(opaque_id, builder.substitution_in_scope()).intern(interner);
-
- // trait_ref = `OpaqueType<...>: MyAutoTrait`
- let auto_trait_ref = TraitRef {
- trait_id: auto_trait_id,
- substitution: Substitution::from1(interner, self_ty),
- };
-
- // OpaqueType<...>: MyAutoTrait :- HiddenType: MyAutoTrait
- builder.push_clause(
- auto_trait_ref,
- std::iter::once(TraitRef {
- trait_id: auto_trait_id,
- substitution: Substitution::from1(interner, hidden_ty.clone()),
- }),
- );
- });
-}
-
-#[instrument(level = "debug", skip(builder))]
-pub fn push_auto_trait_impls_generator_witness<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- auto_trait_id: TraitId<I>,
- generator_id: GeneratorId<I>,
-) {
- let witness_datum = builder.db.generator_witness_datum(generator_id);
- let interner = builder.interner();
-
- // Must be an auto trait.
- assert!(builder.db.trait_datum(auto_trait_id).is_auto_trait());
-
- // Auto traits never have generic parameters of their own (apart from `Self`).
- assert_eq!(
- builder.db.trait_datum(auto_trait_id).binders.len(interner),
- 1
- );
-
- // Push binders for the generator generic parameters. These can be used by
- // both upvars and witness types
- builder.push_binders(witness_datum.inner_types.clone(), |builder, inner_types| {
- let witness_ty = TyKind::GeneratorWitness(generator_id, builder.substitution_in_scope())
- .intern(interner);
-
- // trait_ref = `GeneratorWitness<...>: MyAutoTrait`
- let auto_trait_ref = TraitRef {
- trait_id: auto_trait_id,
- substitution: Substitution::from1(interner, witness_ty),
- };
-
- // Create a goal of the form:
- // forall<L0, L1, ..., LN> {
- // WitnessType1<L0, L1, ... LN, P0, P1, ..., PN>: MyAutoTrait,
- // ...
- // WitnessTypeN<L0, L1, ... LN, P0, P1, ..., PN>: MyAutoTrait,
- //
- // }
- //
- // where `L0, L1, ...LN` are our existentially bound witness lifetimes,
- // and `P0, P1, ..., PN` are the normal generator generics.
- //
- // We create a 'forall' goal due to the fact that our witness lifetimes
- // are *existentially* quantified - the precise reigon is erased during
- // type checking, so we just know that the type takes *some* region
- // as a parameter. Therefore, we require that the auto trait bound
- // hold for *all* regions, which guarantees that the bound will
- // hold for the original lifetime (before it was erased).
- //
- // This does not take into account well-formed information from
- // the witness types. For example, if we have the type
- // `struct Foo<'a, 'b> { val: &'a &'b u8 }`
- // then `'b: 'a` must hold for `Foo<'a, 'b>` to be well-formed.
- // If we have `Foo<'a, 'b>` stored as a witness type, we will
- // not currently use this information to determine a more precise
- // relationship between 'a and 'b. In the future, we will likely
- // do this to avoid incorrectly rejecting correct code.
- let gb = &mut GoalBuilder::new(builder.db);
- let witness_goal = gb.forall(
- &inner_types.types,
- auto_trait_id,
- |gb, _subst, types, auto_trait_id| {
- Goal::new(
- gb.interner(),
- GoalData::All(Goals::from_iter(
- gb.interner(),
- types.iter().map(|witness_ty| TraitRef {
- trait_id: auto_trait_id,
- substitution: Substitution::from1(gb.interner(), witness_ty.clone()),
- }),
- )),
- )
- },
- );
-
- // GeneratorWitnessType: AutoTrait :- forall<...> ...
- // where 'forall<...> ...' is the goal described above.
- builder.push_clause(auto_trait_ref, std::iter::once(witness_goal));
- })
-}
-
-/// Given some goal `goal` that must be proven, along with
-/// its `environment`, figures out the program clauses that apply
-/// to this goal from the Rust program. So for example if the goal
-/// is `Implemented(T: Clone)`, then this function might return clauses
-/// derived from the trait `Clone` and its impls.
-#[instrument(level = "debug", skip(db))]
-pub fn program_clauses_for_goal<'db, I: Interner>(
- db: &'db dyn RustIrDatabase<I>,
- goal: &UCanonical<InEnvironment<DomainGoal<I>>>,
-) -> Result<Vec<ProgramClause<I>>, Floundered> {
- let interner = db.interner();
-
- let custom_clauses = db.custom_clauses().into_iter();
- let clauses_that_could_match =
- program_clauses_that_could_match(db, goal).map(|cl| cl.into_iter())?;
-
- let clauses: Vec<ProgramClause<I>> = custom_clauses
- .chain(clauses_that_could_match)
- .chain(
- db.program_clauses_for_env(&goal.canonical.value.environment)
- .iter(interner)
- .cloned(),
- )
- .filter(|c| {
- c.could_match(
- interner,
- db.unification_database(),
- &goal.canonical.value.goal,
- )
- })
- .collect();
-
- debug!(?clauses);
-
- Ok(clauses)
-}
-
-/// Returns a set of program clauses that could possibly match
-/// `goal`. This can be any superset of the correct set, but the
-/// more precise you can make it, the more efficient solving will
-/// be.
-#[instrument(level = "debug", skip(db))]
-pub fn program_clauses_that_could_match<I: Interner>(
- db: &dyn RustIrDatabase<I>,
- goal: &UCanonical<InEnvironment<DomainGoal<I>>>,
-) -> Result<Vec<ProgramClause<I>>, Floundered> {
- let interner = db.interner();
- let mut clauses: Vec<ProgramClause<I>> = vec![];
- let builder = &mut ClauseBuilder::new(db, &mut clauses);
-
- let UCanonical {
- canonical:
- Canonical {
- value: InEnvironment { environment, goal },
- binders,
- },
- universes: _,
- } = goal;
-
- match goal {
- DomainGoal::Holds(WhereClause::Implemented(trait_ref)) => {
- let self_ty = trait_ref.self_type_parameter(interner);
-
- let trait_id = trait_ref.trait_id;
- let trait_datum = db.trait_datum(trait_id);
-
- match self_ty.kind(interner) {
- TyKind::InferenceVar(_, _) => {
- panic!("Inference vars not allowed when getting program clauses")
- }
- TyKind::Alias(alias) => {
- // An alias could normalize to anything, including `dyn trait`
- // or an opaque type, so push a clause that asks for the
- // self type to be normalized and return.
- push_alias_implemented_clause(builder, trait_ref.clone(), alias.clone());
- return Ok(clauses);
- }
-
- _ if self_ty.is_general_var(interner, binders) => {
- if trait_datum.is_non_enumerable_trait() || trait_datum.is_auto_trait() {
- return Err(Floundered);
- }
- }
-
- TyKind::OpaqueType(opaque_ty_id, _) => {
- db.opaque_ty_data(*opaque_ty_id)
- .to_program_clauses(builder, environment);
- }
-
- TyKind::Dyn(_) => {
- // If the self type is a `dyn trait` type, generate program-clauses
- // that indicates that it implements its own traits.
- // FIXME: This is presently rather wasteful, in that we don't check that the
- // these program clauses we are generating are actually relevant to the goal
- // `goal` that we are actually *trying* to prove (though there is some later
- // code that will screen out irrelevant stuff).
- //
- // In other words, if we were trying to prove `Implemented(dyn
- // Fn(&u8): Clone)`, we would still generate two clauses that are
- // totally irrelevant to that goal, because they let us prove other
- // things but not `Clone`.
- dyn_ty::build_dyn_self_ty_clauses(db, builder, self_ty.clone())
- }
-
- // We don't actually do anything here, but we need to record the types when logging
- TyKind::Adt(adt_id, _) => {
- let _ = db.adt_datum(*adt_id);
- }
-
- TyKind::FnDef(fn_def_id, _) => {
- let _ = db.fn_def_datum(*fn_def_id);
- }
-
- _ => {}
- }
-
- // This is needed for the coherence related impls, as well
- // as for the `Implemented(Foo) :- FromEnv(Foo)` rule.
- trait_datum.to_program_clauses(builder, environment);
-
- for impl_id in db.impls_for_trait(
- trait_ref.trait_id,
- trait_ref.substitution.as_slice(interner),
- binders,
- ) {
- db.impl_datum(impl_id)
- .to_program_clauses(builder, environment);
- }
-
- // If this is a `Foo: Send` (or any auto-trait), then add
- // the automatic impls for `Foo`.
- let trait_datum = db.trait_datum(trait_id);
- if trait_datum.is_auto_trait() {
- let generalized = generalize::Generalize::apply(db.interner(), trait_ref.clone());
- builder.push_binders(generalized, |builder, trait_ref| {
- let ty = trait_ref.self_type_parameter(interner);
- push_auto_trait_impls(builder, trait_id, ty.kind(interner))
- })?;
- }
-
- if let Some(well_known) = trait_datum.well_known {
- builtin_traits::add_builtin_program_clauses(
- db,
- builder,
- well_known,
- trait_ref.clone(),
- binders,
- )?;
- }
- }
- DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => match &alias_eq.alias {
- AliasTy::Projection(proj) => {
- let trait_self_ty = db
- .trait_ref_from_projection(proj)
- .self_type_parameter(interner);
-
- match trait_self_ty.kind(interner) {
- TyKind::Alias(alias) => {
- // An alias could normalize to anything, including an
- // opaque type, so push a clause that asks for the self
- // type to be normalized and return.
- push_alias_alias_eq_clause(
- builder,
- proj.clone(),
- alias_eq.ty.clone(),
- alias.clone(),
- );
- return Ok(clauses);
- }
- TyKind::OpaqueType(opaque_ty_id, _) => {
- db.opaque_ty_data(*opaque_ty_id)
- .to_program_clauses(builder, environment);
- }
- // If the self type is a `dyn trait` type, generate program-clauses
- // for any associated type bindings it contains.
- // FIXME: see the fixme for the analogous code for Implemented goals.
- TyKind::Dyn(_) => {
- dyn_ty::build_dyn_self_ty_clauses(db, builder, trait_self_ty.clone())
- }
- _ => {}
- }
-
- db.associated_ty_data(proj.associated_ty_id)
- .to_program_clauses(builder, environment)
- }
- AliasTy::Opaque(opaque_ty) => db
- .opaque_ty_data(opaque_ty.opaque_ty_id)
- .to_program_clauses(builder, environment),
- },
- DomainGoal::Holds(WhereClause::LifetimeOutlives(..)) => {
- builder.push_bound_lifetime(|builder, a| {
- builder.push_bound_lifetime(|builder, b| {
- builder.push_fact_with_constraints(
- DomainGoal::Holds(WhereClause::LifetimeOutlives(LifetimeOutlives {
- a: a.clone(),
- b: b.clone(),
- })),
- Some(InEnvironment::new(
- &Environment::new(interner),
- Constraint::LifetimeOutlives(a, b),
- )),
- );
- })
- });
- }
- DomainGoal::Holds(WhereClause::TypeOutlives(..)) => {
- builder.push_bound_ty(|builder, ty| {
- builder.push_bound_lifetime(|builder, lifetime| {
- builder.push_fact_with_constraints(
- DomainGoal::Holds(WhereClause::TypeOutlives(TypeOutlives {
- ty: ty.clone(),
- lifetime: lifetime.clone(),
- })),
- Some(InEnvironment::new(
- &Environment::new(interner),
- Constraint::TypeOutlives(ty, lifetime),
- )),
- )
- })
- });
- }
- DomainGoal::WellFormed(WellFormed::Trait(trait_ref))
- | DomainGoal::LocalImplAllowed(trait_ref) => {
- db.trait_datum(trait_ref.trait_id)
- .to_program_clauses(builder, environment);
- }
- DomainGoal::ObjectSafe(trait_id) => {
- if builder.db.is_object_safe(*trait_id) {
- builder.push_fact(DomainGoal::ObjectSafe(*trait_id));
- }
- }
- DomainGoal::WellFormed(WellFormed::Ty(ty))
- | DomainGoal::IsUpstream(ty)
- | DomainGoal::DownstreamType(ty)
- | DomainGoal::IsFullyVisible(ty)
- | DomainGoal::IsLocal(ty) => match_ty(builder, environment, ty)?,
- DomainGoal::FromEnv(_) => (), // Computed in the environment
- DomainGoal::Normalize(Normalize { alias, ty: _ }) => match alias {
- AliasTy::Projection(proj) => {
- // Normalize goals derive from `AssociatedTyValue` datums,
- // which are found in impls. That is, if we are
- // normalizing (e.g.) `<T as Iterator>::Item>`, then
- // search for impls of iterator and, within those impls,
- // for associated type values:
- //
- // ```ignore
- // impl Iterator for Foo {
- // type Item = Bar; // <-- associated type value
- // }
- // ```
- let associated_ty_datum = db.associated_ty_data(proj.associated_ty_id);
- let trait_id = associated_ty_datum.trait_id;
- let trait_ref = db.trait_ref_from_projection(proj);
- let trait_parameters = trait_ref.substitution.as_parameters(interner);
-
- let trait_datum = db.trait_datum(trait_id);
-
- let self_ty = trait_ref.self_type_parameter(interner);
- if let TyKind::InferenceVar(_, _) = self_ty.kind(interner) {
- panic!("Inference vars not allowed when getting program clauses");
- }
-
- // Flounder if the self-type is unknown and the trait is non-enumerable.
- //
- // e.g., Normalize(<?X as Iterator>::Item = u32)
- if (self_ty.is_general_var(interner, binders))
- && trait_datum.is_non_enumerable_trait()
- {
- return Err(Floundered);
- }
-
- if let Some(well_known) = trait_datum.well_known {
- builtin_traits::add_builtin_assoc_program_clauses(
- db, builder, well_known, self_ty,
- )?;
- }
-
- push_program_clauses_for_associated_type_values_in_impls_of(
- builder,
- environment,
- trait_id,
- trait_parameters,
- binders,
- );
-
- if environment.has_compatible_clause(interner) {
- push_clauses_for_compatible_normalize(
- db,
- builder,
- interner,
- trait_id,
- proj.associated_ty_id,
- );
- }
- }
- AliasTy::Opaque(_) => (),
- },
- DomainGoal::Compatible | DomainGoal::Reveal => (),
- };
-
- Ok(clauses)
-}
-
-/// Adds clauses to allow normalizing possible downstream associated type
-/// implementations when in the "compatible" mode. Example clauses:
-///
-/// ```notrust
-/// for<type, type, type> Normalize(<^0.0 as Trait<^0.1>>::Item -> ^0.2)
-/// :- Compatible, Implemented(^0.0: Trait<^0.1>), DownstreamType(^0.1), CannotProve
-/// for<type, type, type> Normalize(<^0.0 as Trait<^0.1>>::Item -> ^0.2)
-/// :- Compatible, Implemented(^0.0: Trait<^0.1>), IsFullyVisible(^0.0), DownstreamType(^0.1), CannotProve
-/// ```
-fn push_clauses_for_compatible_normalize<I: Interner>(
- db: &dyn RustIrDatabase<I>,
- builder: &mut ClauseBuilder<'_, I>,
- interner: I,
- trait_id: TraitId<I>,
- associated_ty_id: AssocTypeId<I>,
-) {
- let trait_datum = db.trait_datum(trait_id);
- let trait_binders = trait_datum.binders.map_ref(|b| &b.where_clauses).cloned();
- builder.push_binders(trait_binders, |builder, where_clauses| {
- let projection = ProjectionTy {
- associated_ty_id,
- substitution: builder.substitution_in_scope(),
- };
- let trait_ref = TraitRef {
- trait_id,
- substitution: builder.substitution_in_scope(),
- };
- let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect();
-
- builder.push_bound_ty(|builder, target_ty| {
- for i in 0..type_parameters.len() {
- builder.push_clause(
- DomainGoal::Normalize(Normalize {
- ty: target_ty.clone(),
- alias: AliasTy::Projection(projection.clone()),
- }),
- where_clauses
- .iter()
- .cloned()
- .casted(interner)
- .chain(iter::once(DomainGoal::Compatible.cast(interner)))
- .chain(iter::once(
- WhereClause::Implemented(trait_ref.clone()).cast(interner),
- ))
- .chain((0..i).map(|j| {
- DomainGoal::IsFullyVisible(type_parameters[j].clone()).cast(interner)
- }))
- .chain(iter::once(
- DomainGoal::DownstreamType(type_parameters[i].clone()).cast(interner),
- ))
- .chain(iter::once(GoalData::CannotProve.intern(interner))),
- );
- }
- });
- });
-}
-
-/// Generate program clauses from the associated-type values
-/// found in impls of the given trait. i.e., if `trait_id` = Iterator,
-/// then we would generate program clauses from each `type Item = ...`
-/// found in any impls of `Iterator`:
-/// which are found in impls. That is, if we are
-/// normalizing (e.g.) `<T as Iterator>::Item>`, then
-/// search for impls of iterator and, within those impls,
-/// for associated type values:
-///
-/// ```ignore
-/// impl Iterator for Foo {
-/// type Item = Bar; // <-- associated type value
-/// }
-/// ```
-#[instrument(level = "debug", skip(builder))]
-fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- environment: &Environment<I>,
- trait_id: TraitId<I>,
- trait_parameters: &[GenericArg<I>],
- binders: &CanonicalVarKinds<I>,
-) {
- for impl_id in builder
- .db
- .impls_for_trait(trait_id, trait_parameters, binders)
- {
- let impl_datum = builder.db.impl_datum(impl_id);
- if !impl_datum.is_positive() {
- continue;
- }
-
- debug!(?impl_id);
-
- for &atv_id in &impl_datum.associated_ty_value_ids {
- let atv = builder.db.associated_ty_value(atv_id);
- debug!(?atv_id, ?atv);
- atv.to_program_clauses(builder, environment);
- }
- }
-}
-
-fn push_alias_implemented_clause<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- trait_ref: TraitRef<I>,
- alias: AliasTy<I>,
-) {
- let interner = builder.interner();
- assert_eq!(
- *trait_ref.self_type_parameter(interner).kind(interner),
- TyKind::Alias(alias.clone())
- );
-
- // TODO: instead generate clauses without reference to the specific type parameters of the goal?
- let generalized = generalize::Generalize::apply(interner, (trait_ref, alias));
- builder.push_binders(generalized, |builder, (trait_ref, alias)| {
- let binders = Binders::with_fresh_type_var(interner, |ty_var| ty_var);
-
- // forall<..., T> {
- // <X as Y>::Z: Trait :- T: Trait, <X as Y>::Z == T
- // }
- builder.push_binders(binders, |builder, bound_var| {
- let fresh_self_subst = Substitution::from_iter(
- interner,
- std::iter::once(bound_var.clone().cast(interner)).chain(
- trait_ref.substitution.as_slice(interner)[1..]
- .iter()
- .cloned(),
- ),
- );
- let fresh_self_trait_ref = TraitRef {
- trait_id: trait_ref.trait_id,
- substitution: fresh_self_subst,
- };
- builder.push_clause(
- DomainGoal::Holds(WhereClause::Implemented(trait_ref.clone())),
- &[
- DomainGoal::Holds(WhereClause::Implemented(fresh_self_trait_ref)),
- DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
- alias: alias.clone(),
- ty: bound_var,
- })),
- ],
- );
- });
- });
-}
-
-fn push_alias_alias_eq_clause<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- projection_ty: ProjectionTy<I>,
- ty: Ty<I>,
- alias: AliasTy<I>,
-) {
- let interner = builder.interner();
- let self_ty = builder
- .db
- .trait_ref_from_projection(&projection_ty)
- .self_type_parameter(interner);
- assert_eq!(*self_ty.kind(interner), TyKind::Alias(alias.clone()));
-
- // TODO: instead generate clauses without reference to the specific type parameters of the goal?
- let generalized = generalize::Generalize::apply(interner, (projection_ty, ty, alias));
- builder.push_binders(generalized, |builder, (projection_ty, ty, alias)| {
- let binders = Binders::with_fresh_type_var(interner, |ty_var| ty_var);
-
- // forall<..., T> {
- // <<X as Y>::A as Z>::B == U :- <T as Z>::B == U, <X as Y>::A == T
- // }
- builder.push_binders(binders, |builder, bound_var| {
- let fresh_self_subst = Substitution::from_iter(
- interner,
- std::iter::once(bound_var.clone().cast(interner)).chain(
- projection_ty.substitution.as_slice(interner)[1..]
- .iter()
- .cloned(),
- ),
- );
- let fresh_alias = AliasTy::Projection(ProjectionTy {
- associated_ty_id: projection_ty.associated_ty_id,
- substitution: fresh_self_subst,
- });
- builder.push_clause(
- DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
- alias: AliasTy::Projection(projection_ty.clone()),
- ty: ty.clone(),
- })),
- &[
- DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
- alias: fresh_alias,
- ty: ty.clone(),
- })),
- DomainGoal::Holds(WhereClause::AliasEq(AliasEq {
- alias: alias.clone(),
- ty: bound_var,
- })),
- ],
- );
- });
- });
-}
-
-/// Examine `T` and push clauses that may be relevant to proving the
-/// following sorts of goals (and maybe others):
-///
-/// * `DomainGoal::WellFormed(T)`
-/// * `DomainGoal::IsUpstream(T)`
-/// * `DomainGoal::DownstreamType(T)`
-/// * `DomainGoal::IsFullyVisible(T)`
-/// * `DomainGoal::IsLocal(T)`
-///
-/// Note that the type `T` must not be an unbound inference variable;
-/// earlier parts of the logic should "flounder" in that case.
-fn match_ty<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- environment: &Environment<I>,
- ty: &Ty<I>,
-) -> Result<(), Floundered> {
- let interner = builder.interner();
- match ty.kind(interner) {
- TyKind::InferenceVar(_, _) => {
- panic!("Inference vars not allowed when getting program clauses")
- }
- TyKind::Adt(adt_id, _) => builder
- .db
- .adt_datum(*adt_id)
- .to_program_clauses(builder, environment),
- TyKind::OpaqueType(opaque_ty_id, _) => builder
- .db
- .opaque_ty_data(*opaque_ty_id)
- .to_program_clauses(builder, environment),
- TyKind::Error => {}
- TyKind::AssociatedType(type_id, _) => builder
- .db
- .associated_ty_data(*type_id)
- .to_program_clauses(builder, environment),
- TyKind::FnDef(fn_def_id, _) => builder
- .db
- .fn_def_datum(*fn_def_id)
- .to_program_clauses(builder, environment),
- TyKind::Str
- | TyKind::Never
- | TyKind::Scalar(_)
- | TyKind::Foreign(_)
- | TyKind::Tuple(0, _) => {
- // These have no substitutions, so they are trivially WF
- builder.push_fact(WellFormed::Ty(ty.clone()));
- }
- TyKind::Raw(mutbl, _) => {
- // forall<T> WF(*const T) :- WF(T);
- builder.push_bound_ty(|builder, ty| {
- builder.push_clause(
- WellFormed::Ty(TyKind::Raw(*mutbl, ty.clone()).intern(builder.interner())),
- Some(WellFormed::Ty(ty)),
- );
- });
- }
- TyKind::Ref(mutbl, _, _) => {
- // forall<'a, T> WF(&'a T) :- WF(T), T: 'a
- builder.push_bound_ty(|builder, ty| {
- builder.push_bound_lifetime(|builder, lifetime| {
- let ref_ty = TyKind::Ref(*mutbl, lifetime.clone(), ty.clone())
- .intern(builder.interner());
- builder.push_clause(
- WellFormed::Ty(ref_ty),
- [
- DomainGoal::WellFormed(WellFormed::Ty(ty.clone())),
- DomainGoal::Holds(WhereClause::TypeOutlives(TypeOutlives {
- ty,
- lifetime,
- })),
- ],
- );
- })
- });
- }
- TyKind::Slice(_) => {
- // forall<T> WF([T]) :- T: Sized, WF(T)
- builder.push_bound_ty(|builder, ty| {
- let sized = builder.db.well_known_trait_id(WellKnownTrait::Sized);
- builder.push_clause(
- WellFormed::Ty(TyKind::Slice(ty.clone()).intern(builder.interner())),
- sized
- .map(|id| {
- DomainGoal::Holds(WhereClause::Implemented(TraitRef {
- trait_id: id,
- substitution: Substitution::from1(interner, ty.clone()),
- }))
- })
- .into_iter()
- .chain(Some(DomainGoal::WellFormed(WellFormed::Ty(ty)))),
- );
- });
- }
- TyKind::Array(..) => {
- // forall<T. const N: usize> WF([T, N]) :- T: Sized
- let interner = builder.interner();
- let binders = Binders::new(
- VariableKinds::from_iter(
- interner,
- [
- VariableKind::Ty(TyVariableKind::General),
- VariableKind::Const(
- TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(interner),
- ),
- ],
- ),
- PhantomData::<I>,
- );
- builder.push_binders(binders, |builder, PhantomData| {
- let placeholders_in_scope = builder.placeholders_in_scope();
- let placeholder_count = placeholders_in_scope.len();
- let ty = placeholders_in_scope[placeholder_count - 2]
- .assert_ty_ref(interner)
- .clone();
- let size = placeholders_in_scope[placeholder_count - 1]
- .assert_const_ref(interner)
- .clone();
-
- let sized = builder.db.well_known_trait_id(WellKnownTrait::Sized);
- let array_ty = TyKind::Array(ty.clone(), size).intern(interner);
- builder.push_clause(
- WellFormed::Ty(array_ty),
- sized
- .map(|id| {
- DomainGoal::Holds(WhereClause::Implemented(TraitRef {
- trait_id: id,
- substitution: Substitution::from1(interner, ty.clone()),
- }))
- })
- .into_iter()
- .chain(Some(DomainGoal::WellFormed(WellFormed::Ty(ty)))),
- );
- });
- }
- TyKind::Tuple(len, _) => {
- // WF((T0, ..., Tn, U)) :- T0: Sized, ..., Tn: Sized, WF(T0), ..., WF(Tn), WF(U)
- let interner = builder.interner();
- let binders = Binders::new(
- VariableKinds::from_iter(
- interner,
- iter::repeat_with(|| VariableKind::Ty(TyVariableKind::General)).take(*len),
- ),
- PhantomData::<I>,
- );
- builder.push_binders(binders, |builder, PhantomData| {
- let placeholders_in_scope = builder.placeholders_in_scope();
-
- let substs = Substitution::from_iter(
- builder.interner(),
- &placeholders_in_scope[placeholders_in_scope.len() - len..],
- );
-
- let tuple_ty = TyKind::Tuple(*len, substs.clone()).intern(interner);
- let sized = builder.db.well_known_trait_id(WellKnownTrait::Sized);
- builder.push_clause(
- WellFormed::Ty(tuple_ty),
- substs.as_slice(interner)[..*len - 1]
- .iter()
- .filter_map(|s| {
- let ty_var = s.assert_ty_ref(interner).clone();
- sized.map(|id| {
- DomainGoal::Holds(WhereClause::Implemented(TraitRef {
- trait_id: id,
- substitution: Substitution::from1(interner, ty_var),
- }))
- })
- })
- .chain(substs.iter(interner).map(|subst| {
- DomainGoal::WellFormed(WellFormed::Ty(
- subst.assert_ty_ref(interner).clone(),
- ))
- })),
- );
- });
- }
- TyKind::Closure(_, _) | TyKind::Generator(_, _) | TyKind::GeneratorWitness(_, _) => {
- let ty = generalize::Generalize::apply(builder.db.interner(), ty.clone());
- builder.push_binders(ty, |builder, ty| {
- builder.push_fact(WellFormed::Ty(ty));
- });
- }
- TyKind::Placeholder(_) => {
- builder.push_fact(WellFormed::Ty(ty.clone()));
- }
- TyKind::Alias(AliasTy::Projection(proj)) => builder
- .db
- .associated_ty_data(proj.associated_ty_id)
- .to_program_clauses(builder, environment),
- TyKind::Alias(AliasTy::Opaque(opaque_ty)) => builder
- .db
- .opaque_ty_data(opaque_ty.opaque_ty_id)
- .to_program_clauses(builder, environment),
- TyKind::Function(_quantified_ty) => {
- let ty = generalize::Generalize::apply(builder.db.interner(), ty.clone());
- builder.push_binders(ty, |builder, ty| builder.push_fact(WellFormed::Ty(ty)));
- }
- TyKind::BoundVar(_) => return Err(Floundered),
- TyKind::Dyn(dyn_ty) => {
- // FIXME(#203)
- // - Object safety? (not needed with RFC 2027)
- // - Implied bounds
- // - Bounds on the associated types
- // - Checking that all associated types are specified, including
- // those on supertraits.
- // - For trait objects with GATs, if we allow them in the future,
- // check that the bounds are fully general (
- // `dyn for<'a> StreamingIterator<Item<'a> = &'a ()>` is OK,
- // `dyn StreamingIterator<Item<'static> = &'static ()>` is not).
- let generalized_ty =
- generalize::Generalize::apply(builder.db.interner(), dyn_ty.clone());
- builder.push_binders(generalized_ty, |builder, dyn_ty| {
- let bounds = dyn_ty
- .bounds
- .substitute(interner, &[ty.clone().cast::<GenericArg<I>>(interner)]);
-
- let mut wf_goals = Vec::new();
-
- wf_goals.extend(bounds.iter(interner).flat_map(|bound| {
- bound.map_ref(|bound| -> Vec<_> {
- match bound {
- WhereClause::Implemented(trait_ref) => {
- vec![DomainGoal::WellFormed(WellFormed::Trait(trait_ref.clone()))]
- }
- WhereClause::AliasEq(_)
- | WhereClause::LifetimeOutlives(_)
- | WhereClause::TypeOutlives(_) => vec![],
- }
- })
- }));
-
- builder.push_clause(WellFormed::Ty(ty.clone()), wf_goals);
- });
- }
- }
- Ok(())
-}
-
-fn match_alias_ty<I: Interner>(
- builder: &mut ClauseBuilder<'_, I>,
- environment: &Environment<I>,
- alias: &AliasTy<I>,
-) {
- if let AliasTy::Projection(projection_ty) = alias {
- builder
- .db
- .associated_ty_data(projection_ty.associated_ty_id)
- .to_program_clauses(builder, environment)
- }
-}
-
-#[instrument(level = "debug", skip(db))]
-pub fn program_clauses_for_env<'db, I: Interner>(
- db: &'db dyn RustIrDatabase<I>,
- environment: &Environment<I>,
-) -> ProgramClauses<I> {
- let mut last_round = environment
- .clauses
- .as_slice(db.interner())
- .iter()
- .cloned()
- .collect::<FxHashSet<_>>();
- let mut closure = last_round.clone();
- let mut next_round = FxHashSet::default();
- while !last_round.is_empty() {
- elaborate_env_clauses(
- db,
- &last_round.drain().collect::<Vec<_>>(),
- &mut next_round,
- environment,
- );
- last_round.extend(
- next_round
- .drain()
- .filter(|clause| closure.insert(clause.clone())),
- );
- }
-
- ProgramClauses::from_iter(db.interner(), closure)
-}