summaryrefslogtreecommitdiffstats
path: root/vendor/chalk-solve
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/chalk-solve')
-rw-r--r--vendor/chalk-solve/.cargo-checksum.json1
-rw-r--r--vendor/chalk-solve/Cargo.toml70
-rw-r--r--vendor/chalk-solve/README.md3
-rw-r--r--vendor/chalk-solve/src/clauses.rs1132
-rw-r--r--vendor/chalk-solve/src/clauses/builder.rs207
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits.rs119
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/clone.rs16
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/copy.rs99
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs73
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/fn_family.rs155
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/generator.rs76
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/sized.rs124
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/tuple.rs30
-rw-r--r--vendor/chalk-solve/src/clauses/builtin_traits/unsize.rs479
-rw-r--r--vendor/chalk-solve/src/clauses/dyn_ty.rs81
-rw-r--r--vendor/chalk-solve/src/clauses/env_elaborator.rs107
-rw-r--r--vendor/chalk-solve/src/clauses/generalize.rs99
-rw-r--r--vendor/chalk-solve/src/clauses/program_clauses.rs921
-rw-r--r--vendor/chalk-solve/src/clauses/super_traits.rs118
-rw-r--r--vendor/chalk-solve/src/coherence.rs149
-rw-r--r--vendor/chalk-solve/src/coherence/orphan.rs44
-rw-r--r--vendor/chalk-solve/src/coherence/solve.rs260
-rw-r--r--vendor/chalk-solve/src/coinductive_goal.rs43
-rw-r--r--vendor/chalk-solve/src/display.rs224
-rw-r--r--vendor/chalk-solve/src/display/bounds.rs168
-rw-r--r--vendor/chalk-solve/src/display/identifiers.rs54
-rw-r--r--vendor/chalk-solve/src/display/items.rs503
-rw-r--r--vendor/chalk-solve/src/display/render_trait.rs30
-rw-r--r--vendor/chalk-solve/src/display/state.rs352
-rw-r--r--vendor/chalk-solve/src/display/stub.rs268
-rw-r--r--vendor/chalk-solve/src/display/ty.rs303
-rw-r--r--vendor/chalk-solve/src/display/utils.rs51
-rw-r--r--vendor/chalk-solve/src/ext.rs113
-rw-r--r--vendor/chalk-solve/src/goal_builder.rs152
-rw-r--r--vendor/chalk-solve/src/infer.rs212
-rw-r--r--vendor/chalk-solve/src/infer/canonicalize.rs237
-rw-r--r--vendor/chalk-solve/src/infer/instantiate.rs111
-rw-r--r--vendor/chalk-solve/src/infer/invert.rs174
-rw-r--r--vendor/chalk-solve/src/infer/test.rs422
-rw-r--r--vendor/chalk-solve/src/infer/ucanonicalize.rs336
-rw-r--r--vendor/chalk-solve/src/infer/unify.rs1448
-rw-r--r--vendor/chalk-solve/src/infer/var.rs152
-rw-r--r--vendor/chalk-solve/src/lib.rs219
-rw-r--r--vendor/chalk-solve/src/logging.rs19
-rw-r--r--vendor/chalk-solve/src/logging_db.rs593
-rw-r--r--vendor/chalk-solve/src/logging_db/id_collector.rs162
-rw-r--r--vendor/chalk-solve/src/rust_ir.rs752
-rw-r--r--vendor/chalk-solve/src/solve.rs350
-rw-r--r--vendor/chalk-solve/src/solve/test/bench.rs111
-rw-r--r--vendor/chalk-solve/src/solve/truncate.rs134
-rw-r--r--vendor/chalk-solve/src/split.rs199
-rw-r--r--vendor/chalk-solve/src/wf.rs1202
52 files changed, 13457 insertions, 0 deletions
diff --git a/vendor/chalk-solve/.cargo-checksum.json b/vendor/chalk-solve/.cargo-checksum.json
new file mode 100644
index 000000000..f93fb555d
--- /dev/null
+++ b/vendor/chalk-solve/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"0af41724ea071b728ceab0fbee7e1783208b880ad7b4686c0c7cd9bc18f56492","README.md":"2de2da988dbbaa8feb78b0a771b7bee942f34705ab057c824b1183300c535c74","src/clauses.rs":"ebb72db87c40e17b2607f582626345286f3def126b5ca5d07e30d2de8ecc70ac","src/clauses/builder.rs":"b8bda05d9e0fca83b6b96b72fae56ea57e2d21c3c2dbb8e72ba0d8b8faeefcbe","src/clauses/builtin_traits.rs":"74839e05dc0be11790a097a01caae15cc085403ccc45b3d853f80c96745d456f","src/clauses/builtin_traits/clone.rs":"36c4603367cfa285043dfd8153121b53df0ee4e4619f7777b4a90d754d6a7942","src/clauses/builtin_traits/copy.rs":"e46a76240b6af043db19ec7fb73d82b9287c5f556075b758bc36aa0d2f574098","src/clauses/builtin_traits/discriminant_kind.rs":"4c987b4c4547586c0180e40cffa1073569a2a3fb50ac56738f962eba6b50f536","src/clauses/builtin_traits/fn_family.rs":"c3eb3594481066bc21593e7663e7e98e110d696854878fbcb43c03ae4971a1f4","src/clauses/builtin_traits/generator.rs":"a8663274c02f4e8b76e6d46c297723d9293b533dd6f45f0c267de177bc809b90","src/clauses/builtin_traits/sized.rs":"2be4e91ce170756dd6a01d334a037a39464e41a5e7fe6f088de55a7332752092","src/clauses/builtin_traits/tuple.rs":"64625a0f2d9c4bcde0c3b68574e517d928429bad29f80d838ad76062694c2124","src/clauses/builtin_traits/unsize.rs":"ba05d22f757e86fa1d901048a29ca94e725eae4f6abbdfe4940404d299bc2e20","src/clauses/dyn_ty.rs":"1d13771582d92c7de96a96bdd2ff7b3ebd26dc1a4d773ee55c5456e3920308b4","src/clauses/env_elaborator.rs":"ad4cd93294f75c1c49fe17aea1cfd41ae4894f10893628a313179ae199fff988","src/clauses/generalize.rs":"68a60005ba8056e9b6a2a5282d17ff6699f1990b0eb6d8bf19b2cd958d8c6b24","src/clauses/program_clauses.rs":"74ace617cf3cf04e00c8905a110f3f04267b7ad1a503309475e232fad5789e9d","src/clauses/super_traits.rs":"e2452a7abb7b8eb8d8ac59cd3032aee8fbc4c52d37954dd8675d3760b80894ba","src/coherence.rs":"452dedfba4db073dc40c3ec25017be6214fed28838f25ec916024664f31ced7d","src/coherence/orphan.rs":"621a839058309f1977e9eea972afa1622a372e06889d8d20aff64788cfba1829","src/coherence/solve.rs":"6677fd4ee28154f72e6d7c34ad3a637323f5169efe54f96e7f7f1b5577f3fa00","src/coinductive_goal.rs":"7a2179fb2d61435cf55c5c87301db6c15edb3cb46750bea381451649b2f1051d","src/display.rs":"ffdb5a8f3523073a3360a48c8be9eaa85f431bff5dc9642d4a929be85ee2984a","src/display/bounds.rs":"7a57ee1dddc199afe933dd76fb5b27f5dbe84ec1a9405c3d4bfb61c3add911dc","src/display/identifiers.rs":"22937fc099812dd9282c20c77ad3797cfa13a8838a0c68638bc4fc32178afbc8","src/display/items.rs":"1464006f0b2684c8092e063fb28ea1e7d0fb77241b76d050b560ac11eb25a8c1","src/display/render_trait.rs":"ccdcbe8e5a1771630dd61eb24b8e384fc30147c285bd40865f9ccc87ab4931b7","src/display/state.rs":"290160db2dd813493f49041b7d21f14f0006bd60a96fb87dd79b5ce44713953a","src/display/stub.rs":"d991613e060871ea638c479e3cdeba67c533a3d4ca68fb0820f3807159c89356","src/display/ty.rs":"5b1a9e8d75c0644df16613cf2f53c8187adc21f1a8db4641b475674b84b07f4f","src/display/utils.rs":"98b0da45184c3934c5707245fdb501e72aa9c916d840907b3b71ca03da51166b","src/ext.rs":"f09806bce122cd3439cfa184435c264cf410eb03c7a6894d428393b745159841","src/goal_builder.rs":"ae59a6f0f3e96eddd197e8887693e6a56506ed848c4698d0a10a9817bd4ff02b","src/infer.rs":"773fe717cccf8e5544d211a10dbece0114fa99f00b587fdb84316c0adc50171b","src/infer/canonicalize.rs":"4d1e7607f779b8806a1a5ecbe6c91101083bf776467b00e7fae5e40e91ad4149","src/infer/instantiate.rs":"ae9a0c3b6d9c898c9429f189c22ff07d00e6784d54520a0b96a6b986d100bb4b","src/infer/invert.rs":"0f016e422ebf94b6b6fad175c6fb7f485ec5b51de4ba0810c782485a2454838d","src/infer/test.rs":"f2285b18331872f2ae639861d318c275b41bd7cbc52a42faa268f339c3313f3e","src/infer/ucanonicalize.rs":"2d94c4fa04026a03ea99ecfd6ec626a4b6f9e834bafd5278f3540e4373519b1e","src/infer/unify.rs":"2b7b3e7aedff0d21c96666e8bdf01b10c125f6057917d6bffb99a8b5f0c95d8f","src/infer/var.rs":"8d657864a789914d1699ca9bc4eb254af381a58c849533d1f4870c5ccad2eaf9","src/lib.rs":"042452f221434c425df391376e07451077d02a2b53358ee416f92b56c3149c20","src/logging.rs":"74445ce59542b977ddb47061294c6772e1d3978b0cdf99e6440ea0dcb698aaba","src/logging_db.rs":"ef66043e71e95796ab24321ecc0b15325b65e3bcfd3fc234acde435972f6ef29","src/logging_db/id_collector.rs":"1286b8fd9ee9b28673907dfc568b2fb6ae072c529f8c517c46861ca3b96e94f8","src/rust_ir.rs":"2182dcaa7015184f46e9d97f6930e352617ec75f5daab4baf87d3c2e452f7108","src/solve.rs":"b91a974ec50ab8c8e37cd2eb8845df0b046910a53df205eb5b07d2793b491f66","src/solve/test/bench.rs":"8da8bb948bdf598ed7f225fd695b12c9e8626cd7a14d4b7d8650de0fae73d655","src/solve/truncate.rs":"d9890902006dccb5e6b4b6347435043be10132ace9b78692a8ebe13b0410901a","src/split.rs":"63d6f033be45da36248188993f747038c6dcd8b4a728427fc79b6ced26368e0d","src/wf.rs":"9934b840a0e7f6225fc3586b8979b200f74b75cf3ef71faaada11344ef33edbd"},"package":"61213deefc36ba265ad01c4d997e18bcddf7922862a4594a47ca4575afb3dab4"} \ No newline at end of file
diff --git a/vendor/chalk-solve/Cargo.toml b/vendor/chalk-solve/Cargo.toml
new file mode 100644
index 000000000..b57214aa8
--- /dev/null
+++ b/vendor/chalk-solve/Cargo.toml
@@ -0,0 +1,70 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "chalk-solve"
+version = "0.87.0"
+authors = [
+ "Rust Compiler Team",
+ "Chalk developers",
+]
+description = "Combines the chalk-engine with chalk-ir"
+readme = "README.md"
+keywords = [
+ "compiler",
+ "traits",
+ "prolog",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/chalk"
+
+[dependencies.chalk-derive]
+version = "=0.87.0"
+
+[dependencies.chalk-ir]
+version = "=0.87.0"
+
+[dependencies.ena]
+version = "0.14.0"
+
+[dependencies.indexmap]
+version = "1.8.0"
+
+[dependencies.itertools]
+version = "0.10.0"
+
+[dependencies.petgraph]
+version = "0.5.1"
+
+[dependencies.rustc-hash]
+version = "1.1.0"
+
+[dependencies.tracing]
+version = "0.1"
+
+[dependencies.tracing-subscriber]
+version = "0.3"
+features = ["env-filter"]
+optional = true
+
+[dependencies.tracing-tree]
+version = "0.2"
+optional = true
+
+[dev-dependencies]
+
+[features]
+default = ["tracing-full"]
+tracing-full = [
+ "tracing-subscriber",
+ "tracing-tree",
+]
diff --git a/vendor/chalk-solve/README.md b/vendor/chalk-solve/README.md
new file mode 100644
index 000000000..bed41761d
--- /dev/null
+++ b/vendor/chalk-solve/README.md
@@ -0,0 +1,3 @@
+A library that defines the rules that translates Rust IR to logical predicates.
+
+See [Github](https://github.com/rust-lang/chalk) for up-to-date information.
diff --git a/vendor/chalk-solve/src/clauses.rs b/vendor/chalk-solve/src/clauses.rs
new file mode 100644
index 000000000..e3fdd351b
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses.rs
@@ -0,0 +1,1132 @@
+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)
+}
diff --git a/vendor/chalk-solve/src/clauses/builder.rs b/vendor/chalk-solve/src/clauses/builder.rs
new file mode 100644
index 000000000..bbe7c2fd2
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builder.rs
@@ -0,0 +1,207 @@
+use std::marker::PhantomData;
+
+use crate::cast::{Cast, CastTo};
+use crate::RustIrDatabase;
+use chalk_ir::fold::{Shift, TypeFoldable};
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::*;
+use tracing::{debug, instrument};
+
+/// The "clause builder" is a useful tool for building up sets of
+/// program clauses. It takes ownership of the output vector while it
+/// lasts, and offers methods like `push_clause` and so forth to
+/// append to it.
+pub struct ClauseBuilder<'me, I: Interner> {
+ pub db: &'me dyn RustIrDatabase<I>,
+ clauses: &'me mut Vec<ProgramClause<I>>,
+ binders: Vec<VariableKind<I>>,
+ parameters: Vec<GenericArg<I>>,
+}
+
+impl<'me, I: Interner> ClauseBuilder<'me, I> {
+ pub fn new(db: &'me dyn RustIrDatabase<I>, clauses: &'me mut Vec<ProgramClause<I>>) -> Self {
+ Self {
+ db,
+ clauses,
+ binders: vec![],
+ parameters: vec![],
+ }
+ }
+
+ /// Pushes a "fact" `forall<..> { consequence }` into the set of
+ /// program clauses, meaning something that we can assume to be
+ /// true unconditionally. The `forall<..>` binders will be
+ /// whichever binders have been pushed (see `push_binders`).
+ pub fn push_fact(&mut self, consequence: impl CastTo<DomainGoal<I>>) {
+ self.push_clause(consequence, None::<Goal<_>>);
+ }
+
+ /// Pushes a "fact" `forall<..> { consequence }` into the set of
+ /// program clauses, meaning something that we can assume to be
+ /// true unconditionally. The `forall<..>` binders will be
+ /// whichever binders have been pushed (see `push_binders`).
+ pub fn push_fact_with_priority(
+ &mut self,
+ consequence: impl CastTo<DomainGoal<I>>,
+ constraints: impl IntoIterator<Item = InEnvironment<Constraint<I>>>,
+ priority: ClausePriority,
+ ) {
+ self.push_clause_with_priority(consequence, None::<Goal<_>>, constraints, priority);
+ }
+
+ /// Pushes a clause `forall<..> { consequence :- conditions }`
+ /// into the set of program clauses, meaning that `consequence`
+ /// can be proven if `conditions` are all true. The `forall<..>`
+ /// binders will be whichever binders have been pushed (see `push_binders`).
+ pub fn push_clause(
+ &mut self,
+ consequence: impl CastTo<DomainGoal<I>>,
+ conditions: impl IntoIterator<Item = impl CastTo<Goal<I>>>,
+ ) {
+ self.push_clause_with_priority(consequence, conditions, None, ClausePriority::High)
+ }
+
+ pub fn push_fact_with_constraints(
+ &mut self,
+ consequence: impl CastTo<DomainGoal<I>>,
+ constraints: impl IntoIterator<Item = InEnvironment<Constraint<I>>>,
+ ) {
+ self.push_fact_with_priority(consequence, constraints, ClausePriority::High)
+ }
+
+ /// Pushes a clause `forall<..> { consequence :- conditions ; constraints }`
+ /// into the set of program clauses, meaning that `consequence`
+ /// can be proven if `conditions` are all true and `constraints`
+ /// are proven to hold. The `forall<..>` binders will be whichever binders
+ /// have been pushed (see `push_binders`).
+ pub fn push_clause_with_priority(
+ &mut self,
+ consequence: impl CastTo<DomainGoal<I>>,
+ conditions: impl IntoIterator<Item = impl CastTo<Goal<I>>>,
+ constraints: impl IntoIterator<Item = InEnvironment<Constraint<I>>>,
+ priority: ClausePriority,
+ ) {
+ let interner = self.db.interner();
+ let clause = ProgramClauseImplication {
+ consequence: consequence.cast(interner),
+ conditions: Goals::from_iter(interner, conditions),
+ constraints: Constraints::from_iter(interner, constraints),
+ priority,
+ };
+
+ let clause = if self.binders.is_empty() {
+ // Compensate for the added empty binder
+ clause.shifted_in(interner)
+ } else {
+ clause
+ };
+
+ self.clauses.push(
+ ProgramClauseData(Binders::new(
+ VariableKinds::from_iter(interner, self.binders.clone()),
+ clause,
+ ))
+ .intern(interner),
+ );
+
+ debug!("pushed clause {:?}", self.clauses.last());
+ }
+
+ /// Accesses the placeholders for the current list of parameters in scope.
+ pub fn placeholders_in_scope(&self) -> &[GenericArg<I>] {
+ &self.parameters
+ }
+
+ /// Accesses the placeholders for the current list of parameters in scope,
+ /// in the form of a `Substitution`.
+ pub fn substitution_in_scope(&self) -> Substitution<I> {
+ Substitution::from_iter(
+ self.db.interner(),
+ self.placeholders_in_scope().iter().cloned(),
+ )
+ }
+
+ /// Executes `op` with the `binders` in-scope; `op` is invoked
+ /// with the bound value `v` as a parameter. After `op` finishes,
+ /// the binders are popped from scope.
+ ///
+ /// The new binders are always pushed onto the end of the internal
+ /// list of binders; this means that any extant values where were
+ /// created referencing the *old* list of binders are still valid.
+ #[instrument(level = "debug", skip(self, op))]
+ pub fn push_binders<R, V>(
+ &mut self,
+ binders: Binders<V>,
+ op: impl FnOnce(&mut Self, V) -> R,
+ ) -> R
+ where
+ V: TypeFoldable<I> + HasInterner<Interner = I>,
+ V: std::fmt::Debug,
+ {
+ let old_len = self.binders.len();
+ let interner = self.interner();
+ self.binders.extend(binders.binders.iter(interner).cloned());
+ self.parameters.extend(
+ binders
+ .binders
+ .iter(interner)
+ .zip(old_len..)
+ .map(|(pk, i)| (i, pk).to_generic_arg(interner)),
+ );
+ let value = binders.substitute(self.interner(), &self.parameters[old_len..]);
+ debug!(?value);
+ let res = op(self, value);
+
+ self.binders.truncate(old_len);
+ self.parameters.truncate(old_len);
+ res
+ }
+
+ /// Push a single binder, for a type, at the end of the binder
+ /// list. The indices of previously bound variables are
+ /// unaffected and hence the context remains usable. Invokes `op`,
+ /// passing a type representing this new type variable in as an
+ /// argument.
+ pub fn push_bound_ty(&mut self, op: impl FnOnce(&mut Self, Ty<I>)) {
+ let interner = self.interner();
+ let binders = Binders::new(
+ VariableKinds::from1(interner, VariableKind::Ty(TyVariableKind::General)),
+ PhantomData::<I>,
+ );
+ self.push_binders(binders, |this, PhantomData| {
+ let ty = this
+ .placeholders_in_scope()
+ .last()
+ .unwrap()
+ .assert_ty_ref(interner)
+ .clone();
+ op(this, ty)
+ });
+ }
+
+ /// Push a single binder, for a lifetime, at the end of the binder
+ /// list. The indices of previously bound variables are
+ /// unaffected and hence the context remains usable. Invokes `op`,
+ /// passing a lifetime representing this new lifetime variable in as an
+ /// argument.
+ pub fn push_bound_lifetime(&mut self, op: impl FnOnce(&mut Self, Lifetime<I>)) {
+ let interner = self.interner();
+ let binders = Binders::new(
+ VariableKinds::from1(interner, VariableKind::Lifetime),
+ PhantomData::<I>,
+ );
+ self.push_binders(binders, |this, PhantomData| {
+ let lifetime = this
+ .placeholders_in_scope()
+ .last()
+ .unwrap()
+ .assert_lifetime_ref(interner)
+ .clone();
+ op(this, lifetime)
+ });
+ }
+
+ pub fn interner(&self) -> I {
+ self.db.interner()
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits.rs b/vendor/chalk-solve/src/clauses/builtin_traits.rs
new file mode 100644
index 000000000..b5a1c7d57
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits.rs
@@ -0,0 +1,119 @@
+use super::{builder::ClauseBuilder, generalize};
+use crate::{CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait};
+use chalk_ir::{Floundered, Substitution, Ty};
+
+mod clone;
+mod copy;
+mod discriminant_kind;
+mod fn_family;
+mod generator;
+mod sized;
+mod tuple;
+mod unsize;
+
+/// For well known traits we have special hard-coded impls, either as an
+/// optimization or to enforce special rules for correctness.
+pub fn add_builtin_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ well_known: WellKnownTrait,
+ trait_ref: TraitRef<I>,
+ binders: &CanonicalVarKinds<I>,
+) -> Result<(), Floundered> {
+ // If `trait_ref` contains bound vars, we want to universally quantify them.
+ // `Generalize` collects them for us.
+ let generalized = generalize::Generalize::apply(db.interner(), trait_ref);
+
+ builder.push_binders(generalized, |builder, trait_ref| {
+ let self_ty = trait_ref.self_type_parameter(db.interner());
+ let ty = self_ty.kind(db.interner()).clone();
+
+ match well_known {
+ // Built-in traits are non-enumerable.
+ _ if self_ty.is_general_var(db.interner(), binders) => return Err(Floundered),
+ WellKnownTrait::Sized => {
+ sized::add_sized_program_clauses(db, builder, trait_ref, ty, binders)?;
+ }
+ WellKnownTrait::Copy => {
+ copy::add_copy_program_clauses(db, builder, trait_ref, ty, binders)?;
+ }
+ WellKnownTrait::Clone => {
+ clone::add_clone_program_clauses(db, builder, trait_ref, ty, binders)?;
+ }
+ WellKnownTrait::FnOnce | WellKnownTrait::FnMut | WellKnownTrait::Fn => {
+ fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
+ }
+ WellKnownTrait::Unsize => {
+ unsize::add_unsize_program_clauses(db, builder, trait_ref, ty)
+ }
+ // DiscriminantKind is automatically implemented for all types
+ WellKnownTrait::DiscriminantKind => builder.push_fact(trait_ref),
+ WellKnownTrait::Generator => {
+ generator::add_generator_program_clauses(db, builder, self_ty)?;
+ }
+ WellKnownTrait::Tuple => {
+ tuple::add_tuple_program_clauses(db, builder, self_ty)?;
+ }
+ // There are no builtin impls provided for the following traits:
+ WellKnownTrait::Unpin
+ | WellKnownTrait::Drop
+ | WellKnownTrait::CoerceUnsized
+ | WellKnownTrait::DispatchFromDyn => (),
+ }
+ Ok(())
+ })
+}
+
+/// Like `add_builtin_program_clauses`, but for `DomainGoal::Normalize` involving
+/// a projection (e.g. `<fn(u8) as FnOnce<(u8,)>>::Output`)
+pub fn add_builtin_assoc_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ well_known: WellKnownTrait,
+ self_ty: Ty<I>,
+) -> Result<(), Floundered> {
+ match well_known {
+ WellKnownTrait::FnOnce => {
+ // If `self_ty` contains bound vars, we want to universally quantify them.
+ // `Generalize` collects them for us.
+ let generalized = generalize::Generalize::apply(db.interner(), self_ty);
+
+ builder.push_binders(generalized, |builder, self_ty| {
+ fn_family::add_fn_trait_program_clauses(db, builder, well_known, self_ty);
+ Ok(())
+ })
+ }
+ WellKnownTrait::DiscriminantKind => {
+ discriminant_kind::add_discriminant_clauses(db, builder, self_ty)
+ }
+ WellKnownTrait::Generator => {
+ let generalized = generalize::Generalize::apply(db.interner(), self_ty);
+
+ builder.push_binders(generalized, |builder, self_ty| {
+ generator::add_generator_program_clauses(db, builder, self_ty)
+ })
+ }
+ _ => Ok(()),
+ }
+}
+
+/// Given a trait ref `T0: Trait` and a list of types `U0..Un`, pushes a clause of the form
+/// `Implemented(T0: Trait) :- Implemented(U0: Trait) .. Implemented(Un: Trait)`
+pub fn needs_impl_for_tys<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ tys: impl Iterator<Item = Ty<I>>,
+) {
+ let trait_id = trait_ref.trait_id;
+
+ // The trait must take one parameter (a type)
+ debug_assert_eq!(db.trait_datum(trait_id).binders.len(db.interner()), 1,);
+ builder.push_clause(
+ trait_ref,
+ tys.map(|ty| TraitRef {
+ trait_id,
+ substitution: Substitution::from1(db.interner(), ty),
+ }),
+ );
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/clone.rs b/vendor/chalk-solve/src/clauses/builtin_traits/clone.rs
new file mode 100644
index 000000000..6d6b3a362
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/clone.rs
@@ -0,0 +1,16 @@
+use crate::clauses::ClauseBuilder;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::{CanonicalVarKinds, Floundered, TyKind};
+
+use super::copy::add_copy_program_clauses;
+
+pub fn add_clone_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ ty: TyKind<I>,
+ binders: &CanonicalVarKinds<I>,
+) -> Result<(), Floundered> {
+ // Implement Clone for types that automaticly implement Copy
+ add_copy_program_clauses(db, builder, trait_ref, ty, binders)
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/copy.rs b/vendor/chalk-solve/src/clauses/builtin_traits/copy.rs
new file mode 100644
index 000000000..c0174b21e
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/copy.rs
@@ -0,0 +1,99 @@
+use crate::clauses::builtin_traits::needs_impl_for_tys;
+use crate::clauses::ClauseBuilder;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::{CanonicalVarKinds, Floundered, Substitution, TyKind, TyVariableKind, VariableKind};
+use std::iter;
+use tracing::instrument;
+
+fn push_tuple_copy_conditions<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ arity: usize,
+ substitution: &Substitution<I>,
+) {
+ // Empty tuples are always Copy
+ if arity == 0 {
+ builder.push_fact(trait_ref);
+ return;
+ }
+
+ let interner = db.interner();
+
+ needs_impl_for_tys(
+ db,
+ builder,
+ trait_ref,
+ substitution
+ .iter(interner)
+ .map(|param| param.assert_ty_ref(interner).clone()),
+ );
+}
+
+#[instrument(skip(db, builder))]
+pub fn add_copy_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ ty: TyKind<I>,
+ binders: &CanonicalVarKinds<I>,
+) -> Result<(), Floundered> {
+ match ty {
+ TyKind::Tuple(arity, ref substitution) => {
+ push_tuple_copy_conditions(db, builder, trait_ref, arity, substitution)
+ }
+ TyKind::Array(ty, _) => {
+ needs_impl_for_tys(db, builder, trait_ref, iter::once(ty));
+ }
+ TyKind::FnDef(_, _) => {
+ builder.push_fact(trait_ref);
+ }
+ TyKind::Closure(closure_id, ref substitution) => {
+ let closure_fn_substitution = db.closure_fn_substitution(closure_id, substitution);
+ let upvars = db.closure_upvars(closure_id, substitution);
+ let upvars = upvars.substitute(db.interner(), &closure_fn_substitution);
+ needs_impl_for_tys(db, builder, trait_ref, Some(upvars).into_iter());
+ }
+
+ // these impls are in libcore
+ TyKind::Ref(_, _, _)
+ | TyKind::Raw(_, _)
+ | TyKind::Scalar(_)
+ | TyKind::Never
+ | TyKind::Str => {}
+
+ TyKind::Adt(_, _)
+ | TyKind::AssociatedType(_, _)
+ | TyKind::Slice(_)
+ | TyKind::OpaqueType(_, _)
+ | TyKind::Foreign(_)
+ | TyKind::Generator(_, _)
+ | TyKind::GeneratorWitness(_, _)
+ | TyKind::Error => {}
+
+ TyKind::Function(_) => builder.push_fact(trait_ref),
+
+ TyKind::InferenceVar(_, TyVariableKind::Float)
+ | TyKind::InferenceVar(_, TyVariableKind::Integer) => builder.push_fact(trait_ref),
+
+ TyKind::BoundVar(bound_var) => {
+ let var_kind = &binders.at(db.interner(), bound_var.index).kind;
+ match var_kind {
+ VariableKind::Ty(TyVariableKind::Integer)
+ | VariableKind::Ty(TyVariableKind::Float) => builder.push_fact(trait_ref),
+
+ // Don't know enough
+ VariableKind::Ty(TyVariableKind::General) => return Err(Floundered),
+
+ VariableKind::Const(_) | VariableKind::Lifetime => {}
+ }
+ }
+
+ // Don't know enough
+ TyKind::InferenceVar(_, TyVariableKind::General) => return Err(Floundered),
+
+ // These should be handled elsewhere
+ TyKind::Alias(_) | TyKind::Dyn(_) | TyKind::Placeholder(_) => {}
+ };
+ Ok(())
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs b/vendor/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs
new file mode 100644
index 000000000..27d49df75
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/discriminant_kind.rs
@@ -0,0 +1,73 @@
+use crate::clauses::ClauseBuilder;
+use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait};
+use chalk_ir::{
+ AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind, TyVariableKind,
+};
+
+pub fn add_discriminant_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ self_ty: Ty<I>,
+) -> Result<(), Floundered> {
+ let interner = db.interner();
+
+ let can_determine_discriminant = match self_ty.data(interner).kind {
+ TyKind::Adt(..)
+ | TyKind::Array(..)
+ | TyKind::Tuple(..)
+ | TyKind::Slice(..)
+ | TyKind::Raw(..)
+ | TyKind::Ref(..)
+ | TyKind::Scalar(_)
+ | TyKind::Str
+ | TyKind::Never
+ | TyKind::FnDef(..)
+ | TyKind::Generator(..)
+ | TyKind::Closure(..)
+ | TyKind::GeneratorWitness(..)
+ | TyKind::Foreign(_)
+ | TyKind::Dyn(_)
+ | TyKind::Function(..)
+ | TyKind::InferenceVar(_, TyVariableKind::Integer)
+ | TyKind::InferenceVar(_, TyVariableKind::Float) => true,
+ TyKind::OpaqueType(..)
+ | TyKind::Alias(_)
+ | TyKind::BoundVar(_)
+ | TyKind::Placeholder(_)
+ | TyKind::AssociatedType(..)
+ | TyKind::Error
+ | TyKind::InferenceVar(..) => false,
+ };
+
+ if !can_determine_discriminant {
+ return Err(Floundered);
+ }
+
+ let disc_ty = db.discriminant_type(self_ty.clone());
+
+ let trait_id = db
+ .well_known_trait_id(WellKnownTrait::DiscriminantKind)
+ .unwrap();
+ let trait_datum = db.trait_datum(trait_id);
+
+ let associated_ty_id = trait_datum.associated_ty_ids[0];
+ let substitution = Substitution::from1(interner, self_ty);
+
+ let trait_ref = TraitRef {
+ trait_id,
+ substitution: substitution.clone(),
+ };
+
+ let normalize = Normalize {
+ alias: AliasTy::Projection(ProjectionTy {
+ associated_ty_id,
+ substitution,
+ }),
+ ty: disc_ty,
+ };
+
+ builder.push_fact(trait_ref);
+ builder.push_fact(normalize);
+
+ Ok(())
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/fn_family.rs b/vendor/chalk-solve/src/clauses/builtin_traits/fn_family.rs
new file mode 100644
index 000000000..f2358bc73
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/fn_family.rs
@@ -0,0 +1,155 @@
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::{ClosureKind, FnDefInputsAndOutputDatum, WellKnownTrait};
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::cast::Cast;
+use chalk_ir::{
+ AliasTy, Binders, Normalize, ProjectionTy, Safety, Substitution, TraitId, Ty, TyKind,
+};
+
+fn push_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ well_known: WellKnownTrait,
+ trait_id: TraitId<I>,
+ self_ty: Ty<I>,
+ arg_sub: Substitution<I>,
+ return_type: Ty<I>,
+) {
+ let interner = db.interner();
+ let tupled = TyKind::Tuple(arg_sub.len(interner), arg_sub).intern(interner);
+ let substitution =
+ Substitution::from_iter(interner, &[self_ty.cast(interner), tupled.cast(interner)]);
+ builder.push_fact(TraitRef {
+ trait_id,
+ substitution: substitution.clone(),
+ });
+
+ // The `Output` type is defined on the `FnOnce`
+ if let WellKnownTrait::FnOnce = well_known {
+ let trait_datum = db.trait_datum(trait_id);
+ assert_eq!(
+ trait_datum.associated_ty_ids.len(),
+ 1,
+ "FnOnce trait should have exactly one associated type, found {:?}",
+ trait_datum.associated_ty_ids
+ );
+ // Constructs the alias. For `Fn`, for example, this would look like
+ // `Normalize(<fn(A) -> B as FnOnce<(A,)>>::Output -> B)`
+ let output_id = trait_datum.associated_ty_ids[0];
+ let alias = AliasTy::Projection(ProjectionTy {
+ associated_ty_id: output_id,
+ substitution,
+ });
+ builder.push_fact(Normalize {
+ alias,
+ ty: return_type,
+ });
+ }
+}
+
+fn push_clauses_for_apply<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ well_known: WellKnownTrait,
+ trait_id: TraitId<I>,
+ self_ty: Ty<I>,
+ inputs_and_output: Binders<FnDefInputsAndOutputDatum<I>>,
+) {
+ let interner = db.interner();
+ builder.push_binders(inputs_and_output, |builder, inputs_and_output| {
+ let arg_sub = inputs_and_output
+ .argument_types
+ .iter()
+ .cloned()
+ .map(|ty| ty.cast(interner));
+ let arg_sub = Substitution::from_iter(interner, arg_sub);
+ let output_ty = inputs_and_output.return_type;
+
+ push_clauses(
+ db, builder, well_known, trait_id, self_ty, arg_sub, output_ty,
+ );
+ });
+}
+
+/// Handles clauses for FnOnce/FnMut/Fn.
+/// If `self_ty` is a function, we push a clause of the form
+/// `fn(A1, A2, ..., AN) -> O: FnTrait<(A1, A2, ..., AN)>`, where `FnTrait`
+/// is the trait corresponding to `trait_id` (FnOnce/FnMut/Fn)
+///
+/// If `trait_id` is `FnOnce`, we also push a clause for the output type of the form:
+/// `Normalize(<fn(A) -> B as FnOnce<(A,)>>::Output -> B)`
+/// We do not add the usual `Implemented(fn(A) -> b as FnOnce<(A,)>` clause
+/// as a condition, since we already called `push_fact` with it
+pub fn add_fn_trait_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ well_known: WellKnownTrait,
+ self_ty: Ty<I>,
+) {
+ let interner = db.interner();
+ let trait_id = db.well_known_trait_id(well_known).unwrap();
+
+ match self_ty.kind(interner) {
+ TyKind::FnDef(fn_def_id, substitution) => {
+ let fn_def_datum = builder.db.fn_def_datum(*fn_def_id);
+ if fn_def_datum.sig.safety == Safety::Safe && !fn_def_datum.sig.variadic {
+ let bound = fn_def_datum
+ .binders
+ .clone()
+ .substitute(builder.interner(), &substitution);
+ push_clauses_for_apply(
+ db,
+ builder,
+ well_known,
+ trait_id,
+ self_ty,
+ bound.inputs_and_output,
+ );
+ }
+ }
+ TyKind::Closure(closure_id, substitution) => {
+ let closure_kind = db.closure_kind(*closure_id, substitution);
+ let trait_matches = matches!(
+ (well_known, closure_kind),
+ (WellKnownTrait::Fn, ClosureKind::Fn)
+ | (WellKnownTrait::FnMut, ClosureKind::FnMut | ClosureKind::Fn)
+ | (WellKnownTrait::FnOnce, _)
+ );
+ if !trait_matches {
+ return;
+ }
+ let closure_inputs_and_output = db.closure_inputs_and_output(*closure_id, substitution);
+ push_clauses_for_apply(
+ db,
+ builder,
+ well_known,
+ trait_id,
+ self_ty,
+ closure_inputs_and_output,
+ );
+ }
+ TyKind::Function(fn_val) if fn_val.sig.safety == Safety::Safe && !fn_val.sig.variadic => {
+ let bound_ref = fn_val.clone().into_binders(interner);
+ builder.push_binders(bound_ref, |builder, orig_sub| {
+ // The last parameter represents the function return type
+ let (arg_sub, fn_output_ty) = orig_sub
+ .0
+ .as_slice(interner)
+ .split_at(orig_sub.0.len(interner) - 1);
+ let arg_sub = Substitution::from_iter(interner, arg_sub);
+ let output_ty = fn_output_ty[0].assert_ty_ref(interner).clone();
+
+ push_clauses(
+ db,
+ builder,
+ well_known,
+ trait_id,
+ self_ty.clone(),
+ arg_sub,
+ output_ty,
+ );
+ });
+ }
+ _ => {}
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/generator.rs b/vendor/chalk-solve/src/clauses/builtin_traits/generator.rs
new file mode 100644
index 000000000..67415bfd7
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/generator.rs
@@ -0,0 +1,76 @@
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::WellKnownTrait;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::cast::Cast;
+use chalk_ir::{AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind};
+
+/// Add implicit impls of the generator trait, i.e., add a clause that all generators implement
+/// `Generator` and clauses for `Generator`'s associated types.
+pub fn add_generator_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ self_ty: Ty<I>,
+) -> Result<(), Floundered> {
+ let interner = db.interner();
+
+ match self_ty.kind(interner) {
+ TyKind::Generator(id, substitution) => {
+ let generator_datum = db.generator_datum(*id);
+ let generator_io_datum = generator_datum
+ .input_output
+ .clone()
+ .substitute(interner, &substitution);
+
+ let trait_id = db.well_known_trait_id(WellKnownTrait::Generator).unwrap();
+ let trait_datum = db.trait_datum(trait_id);
+ assert_eq!(
+ trait_datum.associated_ty_ids.len(),
+ 2,
+ "Generator trait should have exactly two associated types, found {:?}",
+ trait_datum.associated_ty_ids
+ );
+
+ let substitution = Substitution::from_iter(
+ interner,
+ &[
+ self_ty.cast(interner),
+ generator_io_datum.resume_type.cast(interner),
+ ],
+ );
+
+ // generator: Generator<resume_type>
+ builder.push_fact(TraitRef {
+ trait_id,
+ substitution: substitution.clone(),
+ });
+
+ // `Generator::Yield`
+ let yield_id = trait_datum.associated_ty_ids[0];
+ let yield_alias = AliasTy::Projection(ProjectionTy {
+ associated_ty_id: yield_id,
+ substitution: substitution.clone(),
+ });
+ builder.push_fact(Normalize {
+ alias: yield_alias,
+ ty: generator_io_datum.yield_type,
+ });
+
+ // `Generator::Return`
+ let return_id = trait_datum.associated_ty_ids[1];
+ let return_alias = AliasTy::Projection(ProjectionTy {
+ associated_ty_id: return_id,
+ substitution,
+ });
+ builder.push_fact(Normalize {
+ alias: return_alias,
+ ty: generator_io_datum.return_type,
+ });
+
+ Ok(())
+ }
+
+ // Generator trait is non-enumerable
+ TyKind::InferenceVar(..) | TyKind::BoundVar(_) | TyKind::Alias(..) => Err(Floundered),
+ _ => Ok(()),
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/sized.rs b/vendor/chalk-solve/src/clauses/builtin_traits/sized.rs
new file mode 100644
index 000000000..3ed46d425
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/sized.rs
@@ -0,0 +1,124 @@
+use std::iter;
+
+use crate::clauses::builtin_traits::needs_impl_for_tys;
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::AdtKind;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::{
+ AdtId, CanonicalVarKinds, Floundered, Substitution, TyKind, TyVariableKind, VariableKind,
+};
+
+fn push_adt_sized_conditions<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ adt_id: AdtId<I>,
+ substitution: &Substitution<I>,
+) {
+ let adt_datum = db.adt_datum(adt_id);
+
+ // WF ensures that all enums are Sized, so we only have to consider structs.
+ if adt_datum.kind != AdtKind::Struct {
+ builder.push_fact(trait_ref);
+ return;
+ }
+
+ let interner = db.interner();
+
+ // To check if a struct S<..> is Sized, we only have to look at its last field.
+ // This is because the WF checks for ADTs require that all the other fields must be Sized.
+ let last_field_ty = adt_datum
+ .binders
+ .map_ref(|b| b.variants.clone())
+ .substitute(interner, substitution)
+ .into_iter()
+ .take(1) // We have a struct so we're guaranteed one variant
+ .flat_map(|mut v| v.fields.pop());
+
+ needs_impl_for_tys(db, builder, trait_ref, last_field_ty);
+}
+
+fn push_tuple_sized_conditions<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ arity: usize,
+ substitution: &Substitution<I>,
+) {
+ // Empty tuples are always Sized
+ if arity == 0 {
+ builder.push_fact(trait_ref);
+ return;
+ }
+
+ let interner = db.interner();
+
+ // To check if a tuple is Sized, we only have to look at its last element.
+ // This is because the WF checks for tuples require that all the other elements must be Sized.
+ let last_elem_ty = substitution
+ .iter(interner)
+ .last()
+ .unwrap()
+ .ty(interner)
+ .unwrap()
+ .clone();
+
+ needs_impl_for_tys(db, builder, trait_ref, iter::once(last_elem_ty));
+}
+
+pub fn add_sized_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ ty: TyKind<I>,
+ binders: &CanonicalVarKinds<I>,
+) -> Result<(), Floundered> {
+ match ty {
+ TyKind::Adt(adt_id, ref substitution) => {
+ push_adt_sized_conditions(db, builder, trait_ref, adt_id, substitution)
+ }
+ TyKind::Tuple(arity, ref substitution) => {
+ push_tuple_sized_conditions(db, builder, trait_ref, arity, substitution)
+ }
+ TyKind::Array(_, _)
+ | TyKind::Never
+ | TyKind::Closure(_, _)
+ | TyKind::FnDef(_, _)
+ | TyKind::Scalar(_)
+ | TyKind::Raw(_, _)
+ | TyKind::Generator(_, _)
+ | TyKind::GeneratorWitness(_, _)
+ | TyKind::Ref(_, _, _) => builder.push_fact(trait_ref),
+
+ TyKind::AssociatedType(_, _)
+ | TyKind::Slice(_)
+ | TyKind::OpaqueType(_, _)
+ | TyKind::Str
+ | TyKind::Foreign(_)
+ | TyKind::Error => {}
+
+ TyKind::Function(_)
+ | TyKind::InferenceVar(_, TyVariableKind::Float)
+ | TyKind::InferenceVar(_, TyVariableKind::Integer) => builder.push_fact(trait_ref),
+
+ TyKind::BoundVar(bound_var) => {
+ let var_kind = &binders.at(db.interner(), bound_var.index).kind;
+ match var_kind {
+ VariableKind::Ty(TyVariableKind::Integer)
+ | VariableKind::Ty(TyVariableKind::Float) => builder.push_fact(trait_ref),
+
+ // Don't know enough
+ VariableKind::Ty(TyVariableKind::General) => return Err(Floundered),
+
+ VariableKind::Const(_) | VariableKind::Lifetime => {}
+ }
+ }
+
+ // We don't know enough here
+ TyKind::InferenceVar(_, TyVariableKind::General) => return Err(Floundered),
+
+ // These would be handled elsewhere
+ TyKind::Placeholder(_) | TyKind::Dyn(_) | TyKind::Alias(_) => {}
+ }
+ Ok(())
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/tuple.rs b/vendor/chalk-solve/src/clauses/builtin_traits/tuple.rs
new file mode 100644
index 000000000..a62447827
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/tuple.rs
@@ -0,0 +1,30 @@
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::WellKnownTrait;
+use crate::{Interner, RustIrDatabase, TraitRef};
+use chalk_ir::{Floundered, Substitution, Ty, TyKind};
+
+/// Add implicit impl for the `Tuple` trait for all tuples
+pub fn add_tuple_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ self_ty: Ty<I>,
+) -> Result<(), Floundered> {
+ let interner = db.interner();
+
+ match self_ty.kind(interner) {
+ TyKind::Tuple(..) => {
+ let trait_id = db.well_known_trait_id(WellKnownTrait::Tuple).unwrap();
+
+ builder.push_fact(TraitRef {
+ trait_id,
+ substitution: Substitution::from1(interner, self_ty),
+ });
+
+ Ok(())
+ }
+
+ // Tuple trait is non-enumerable
+ TyKind::InferenceVar(..) | TyKind::BoundVar(_) | TyKind::Alias(..) => Err(Floundered),
+ _ => Ok(()),
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/builtin_traits/unsize.rs b/vendor/chalk-solve/src/clauses/builtin_traits/unsize.rs
new file mode 100644
index 000000000..6682735b6
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/builtin_traits/unsize.rs
@@ -0,0 +1,479 @@
+use std::collections::HashSet;
+use std::iter;
+use std::ops::ControlFlow;
+
+use crate::clauses::ClauseBuilder;
+use crate::rust_ir::AdtKind;
+use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait};
+use chalk_ir::{
+ cast::Cast,
+ interner::HasInterner,
+ visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
+ Binders, Const, ConstValue, DebruijnIndex, DomainGoal, DynTy, EqGoal, Goal, LifetimeOutlives,
+ QuantifiedWhereClauses, Substitution, TraitId, Ty, TyKind, TypeOutlives, WhereClause,
+};
+
+struct UnsizeParameterCollector<I: Interner> {
+ interner: I,
+ // FIXME should probably use a bitset instead
+ parameters: HashSet<usize>,
+}
+
+impl<I: Interner> TypeVisitor<I> for UnsizeParameterCollector<I> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ let interner = self.interner;
+
+ match ty.kind(interner) {
+ TyKind::BoundVar(bound_var) => {
+ // check if bound var refers to the outermost binder
+ if bound_var.debruijn.shifted_in() == outer_binder {
+ self.parameters.insert(bound_var.index);
+ }
+ ControlFlow::Continue(())
+ }
+ _ => ty.super_visit_with(self, outer_binder),
+ }
+ }
+
+ fn visit_const(&mut self, constant: &Const<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ let interner = self.interner;
+
+ if let ConstValue::BoundVar(bound_var) = constant.data(interner).value {
+ // check if bound var refers to the outermost binder
+ if bound_var.debruijn.shifted_in() == outer_binder {
+ self.parameters.insert(bound_var.index);
+ }
+ }
+ ControlFlow::Continue(())
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
+
+fn outer_binder_parameters_used<I: Interner>(
+ interner: I,
+ v: &Binders<impl TypeVisitable<I> + HasInterner>,
+) -> HashSet<usize> {
+ let mut visitor = UnsizeParameterCollector {
+ interner,
+ parameters: HashSet::new(),
+ };
+ v.visit_with(&mut visitor, DebruijnIndex::INNERMOST);
+ visitor.parameters
+}
+
+// has nothing to do with occurs check
+struct ParameterOccurenceCheck<'p, I: Interner> {
+ interner: I,
+ parameters: &'p HashSet<usize>,
+}
+
+impl<'p, I: Interner> TypeVisitor<I> for ParameterOccurenceCheck<'p, I> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ let interner = self.interner;
+
+ match ty.kind(interner) {
+ TyKind::BoundVar(bound_var) => {
+ if bound_var.debruijn.shifted_in() == outer_binder
+ && self.parameters.contains(&bound_var.index)
+ {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+ _ => ty.super_visit_with(self, outer_binder),
+ }
+ }
+
+ fn visit_const(&mut self, constant: &Const<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ let interner = self.interner;
+
+ match constant.data(interner).value {
+ ConstValue::BoundVar(bound_var) => {
+ if bound_var.debruijn.shifted_in() == outer_binder
+ && self.parameters.contains(&bound_var.index)
+ {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+ _ => ControlFlow::Continue(()),
+ }
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
+
+fn uses_outer_binder_params<I: Interner>(
+ interner: I,
+ v: &Binders<impl TypeVisitable<I> + HasInterner>,
+ parameters: &HashSet<usize>,
+) -> bool {
+ let mut visitor = ParameterOccurenceCheck {
+ interner,
+ parameters,
+ };
+
+ let flow = v.visit_with(&mut visitor, DebruijnIndex::INNERMOST);
+ matches!(flow, ControlFlow::Break(_))
+}
+
+fn principal_id<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ bounds: &Binders<QuantifiedWhereClauses<I>>,
+) -> Option<TraitId<I>> {
+ let interner = db.interner();
+
+ bounds
+ .skip_binders()
+ .iter(interner)
+ .filter_map(|b| b.trait_id())
+ .find(|&id| !db.trait_datum(id).is_auto_trait())
+}
+
+fn auto_trait_ids<'a, I: Interner>(
+ db: &'a dyn RustIrDatabase<I>,
+ bounds: &'a Binders<QuantifiedWhereClauses<I>>,
+) -> impl Iterator<Item = TraitId<I>> + 'a {
+ let interner = db.interner();
+
+ bounds
+ .skip_binders()
+ .iter(interner)
+ .filter_map(|clause| clause.trait_id())
+ .filter(move |&id| db.trait_datum(id).is_auto_trait())
+}
+
+pub fn add_unsize_program_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+ _ty: TyKind<I>,
+) {
+ let interner = db.interner();
+
+ let source_ty = trait_ref.self_type_parameter(interner);
+ let target_ty = trait_ref
+ .substitution
+ .at(interner, 1)
+ .assert_ty_ref(interner)
+ .clone();
+
+ let unsize_trait_id = trait_ref.trait_id;
+
+ // N.B. here rustc asserts that `TraitRef` is not a higher-ranked bound
+ // i.e. `for<'a> &'a T: Unsize<dyn Trait+'a>` is never provable.
+ //
+ // In chalk it would be awkward to implement and I am not sure
+ // there is a need for it, the original comment states that this restriction
+ // could be lifted.
+ //
+ // for more info visit `fn assemble_candidates_for_unsizing` and
+ // `fn confirm_builtin_unisize_candidate` in rustc.
+
+ match (source_ty.kind(interner), target_ty.kind(interner)) {
+ // dyn Trait + AutoX + 'a -> dyn Trait + AutoY + 'b
+ (
+ TyKind::Dyn(DynTy {
+ bounds: bounds_a,
+ lifetime: lifetime_a,
+ }),
+ TyKind::Dyn(DynTy {
+ bounds: bounds_b,
+ lifetime: lifetime_b,
+ }),
+ ) => {
+ let principal_a = principal_id(db, bounds_a);
+ let principal_b = principal_id(db, bounds_b);
+
+ let auto_trait_ids_a: Vec<_> = auto_trait_ids(db, bounds_a).collect();
+ let auto_trait_ids_b: Vec<_> = auto_trait_ids(db, bounds_b).collect();
+
+ let may_apply = principal_a == principal_b
+ && auto_trait_ids_b
+ .iter()
+ .all(|id_b| auto_trait_ids_a.iter().any(|id_a| id_a == id_b));
+
+ if !may_apply {
+ return;
+ }
+
+ // COMMENT FROM RUSTC:
+ // ------------------
+ // Require that the traits involved in this upcast are **equal**;
+ // only the **lifetime bound** is changed.
+ //
+ // This condition is arguably too strong -- it would
+ // suffice for the source trait to be a *subtype* of the target
+ // trait. In particular, changing from something like
+ // `for<'a, 'b> Foo<'a, 'b>` to `for<'a> Foo<'a, 'a>` should be
+ // permitted.
+ // <...>
+ // I've modified this to `.eq` because I want to continue rejecting
+ // that [`old-lub-glb-object.rs`] test (as we have
+ // done for quite some time) before we are firmly comfortable
+ // with what our behavior should be there. -nikomatsakis
+ // ------------------
+
+ // Construct a new trait object type by taking the source ty,
+ // filtering out auto traits of source that are not present in target
+ // and changing source lifetime to target lifetime.
+ //
+ // In order for the coercion to be valid, this new type
+ // should be equal to target type.
+ let new_source_ty = TyKind::Dyn(DynTy {
+ bounds: bounds_a.map_ref(|bounds| {
+ QuantifiedWhereClauses::from_iter(
+ interner,
+ bounds.iter(interner).filter(|bound| {
+ let trait_id = match bound.trait_id() {
+ Some(id) => id,
+ None => return true,
+ };
+
+ if auto_trait_ids_a.iter().all(|&id_a| id_a != trait_id) {
+ return true;
+ }
+ auto_trait_ids_b.iter().any(|&id_b| id_b == trait_id)
+ }),
+ )
+ }),
+ lifetime: lifetime_b.clone(),
+ })
+ .intern(interner);
+
+ // Check that new source is equal to target
+ let eq_goal = EqGoal {
+ a: new_source_ty.cast(interner),
+ b: target_ty.clone().cast(interner),
+ }
+ .cast(interner);
+
+ // Check that source lifetime outlives target lifetime
+ let lifetime_outlives_goal: Goal<I> = WhereClause::LifetimeOutlives(LifetimeOutlives {
+ a: lifetime_a.clone(),
+ b: lifetime_b.clone(),
+ })
+ .cast(interner);
+
+ builder.push_clause(trait_ref, [eq_goal, lifetime_outlives_goal].iter());
+ }
+
+ // T -> dyn Trait + 'a
+ (_, TyKind::Dyn(DynTy { bounds, lifetime })) => {
+ // Check if all traits in trait object are object safe
+ let object_safe_goals = bounds
+ .skip_binders()
+ .iter(interner)
+ .filter_map(|bound| bound.trait_id())
+ .map(|id| DomainGoal::ObjectSafe(id).cast(interner));
+
+ // Check that T implements all traits of the trait object
+ let source_ty_bounds = bounds
+ .clone()
+ .substitute(interner, &Substitution::from1(interner, source_ty.clone()));
+
+ // Check that T is sized because we can only make
+ // a trait object from a sized type
+ let self_sized_goal: WhereClause<_> = TraitRef {
+ trait_id: db
+ .well_known_trait_id(WellKnownTrait::Sized)
+ .expect("Expected Sized to be defined when proving Unsize"),
+ substitution: Substitution::from1(interner, source_ty.clone()),
+ }
+ .cast(interner);
+
+ // Check that `source_ty` outlives `'a`
+ let source_ty_outlives: Goal<_> = WhereClause::TypeOutlives(TypeOutlives {
+ ty: source_ty,
+ lifetime: lifetime.clone(),
+ })
+ .cast(interner);
+
+ builder.push_clause(
+ trait_ref,
+ source_ty_bounds
+ .iter(interner)
+ .map(|bound| bound.clone().cast::<Goal<I>>(interner))
+ .chain(object_safe_goals)
+ .chain(iter::once(self_sized_goal.cast(interner)))
+ .chain(iter::once(source_ty_outlives)),
+ );
+ }
+
+ (TyKind::Array(array_ty, _array_const), TyKind::Slice(slice_ty)) => {
+ let eq_goal = EqGoal {
+ a: array_ty.clone().cast(interner),
+ b: slice_ty.clone().cast(interner),
+ };
+
+ builder.push_clause(trait_ref, iter::once(eq_goal));
+ }
+
+ // Adt<T> -> Adt<U>
+ (TyKind::Adt(adt_id_a, substitution_a), TyKind::Adt(adt_id_b, substitution_b)) => {
+ if adt_id_a != adt_id_b {
+ return;
+ }
+
+ let adt_id = *adt_id_a;
+ let adt_datum = db.adt_datum(adt_id);
+
+ // Unsizing of enums is not allowed
+ if adt_datum.kind == AdtKind::Enum {
+ return;
+ }
+
+ // We have a `struct` so we're guaranteed a single variant
+ let fields_len = adt_datum
+ .binders
+ .skip_binders()
+ .variants
+ .last()
+ .unwrap()
+ .fields
+ .len();
+
+ if fields_len == 0 {
+ return;
+ }
+
+ let adt_tail_field = adt_datum
+ .binders
+ .map_ref(|bound| bound.variants.last().unwrap().fields.last().unwrap())
+ .cloned();
+
+ // Collect unsize parameters that last field contains and
+ // ensure there at least one of them.
+ let unsize_parameter_candidates =
+ outer_binder_parameters_used(interner, &adt_tail_field);
+
+ if unsize_parameter_candidates.is_empty() {
+ return;
+ }
+ // Ensure none of the other fields mention the parameters used
+ // in unsizing.
+ // We specifically want variables specified by the outermost binder
+ // i.e. the struct generic arguments binder.
+ if uses_outer_binder_params(
+ interner,
+ &adt_datum
+ .binders
+ .map_ref(|bound| &bound.variants.last().unwrap().fields[..fields_len - 1]),
+ &unsize_parameter_candidates,
+ ) {
+ return;
+ }
+
+ let parameters_a = substitution_a.as_slice(interner);
+ let parameters_b = substitution_b.as_slice(interner);
+ // Check that the source adt with the target's
+ // unsizing parameters is equal to the target.
+ // We construct a new substitution where if a parameter is used in the
+ // coercion (i.e. it's a non-lifetime struct parameter used by it's last field),
+ // then we take that parameter from target substitution, otherwise we take
+ // it from the source substitution.
+ //
+ // In order for the coercion to be valid, target struct and
+ // struct with this newly constructed substitution applied to it should be equal.
+ let substitution = Substitution::from_iter(
+ interner,
+ parameters_a.iter().enumerate().map(|(i, p)| {
+ if unsize_parameter_candidates.contains(&i) {
+ &parameters_b[i]
+ } else {
+ p
+ }
+ }),
+ );
+
+ let eq_goal = EqGoal {
+ a: TyKind::Adt(adt_id, substitution)
+ .intern(interner)
+ .cast(interner),
+ b: target_ty.clone().cast(interner),
+ }
+ .cast(interner);
+
+ // Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
+ let source_tail_field = adt_tail_field.clone().substitute(interner, substitution_a);
+ let target_tail_field = adt_tail_field.substitute(interner, substitution_b);
+
+ // Check that `TailField<T>: Unsize<TailField<U>>`
+ let last_field_unsizing_goal: Goal<I> = TraitRef {
+ trait_id: unsize_trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ [source_tail_field, target_tail_field].iter().cloned(),
+ ),
+ }
+ .cast(interner);
+
+ builder.push_clause(trait_ref, [eq_goal, last_field_unsizing_goal].iter());
+ }
+
+ // (.., T) -> (.., U)
+ (TyKind::Tuple(arity_a, substitution_a), TyKind::Tuple(arity_b, substitution_b)) => {
+ if arity_a != arity_b || *arity_a == 0 {
+ return;
+ }
+ let arity = arity_a;
+
+ let tail_ty_a = substitution_a.iter(interner).last().unwrap();
+ let tail_ty_b = substitution_b.iter(interner).last().unwrap();
+
+ // Check that the source tuple with the target's
+ // last element is equal to the target.
+ let new_tuple = TyKind::Tuple(
+ *arity,
+ Substitution::from_iter(
+ interner,
+ substitution_a
+ .iter(interner)
+ .take(arity - 1)
+ .chain(iter::once(tail_ty_b)),
+ ),
+ )
+ .cast(interner)
+ .intern(interner);
+
+ let eq_goal: Goal<I> = EqGoal {
+ a: new_tuple.cast(interner),
+ b: target_ty.clone().cast(interner),
+ }
+ .cast(interner);
+
+ // Check that `T: Unsize<U>`
+ let last_field_unsizing_goal: Goal<I> = TraitRef {
+ trait_id: unsize_trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ [tail_ty_a, tail_ty_b].iter().cloned(),
+ ),
+ }
+ .cast(interner);
+
+ builder.push_clause(trait_ref, [eq_goal, last_field_unsizing_goal].iter());
+ }
+
+ _ => (),
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/dyn_ty.rs b/vendor/chalk-solve/src/clauses/dyn_ty.rs
new file mode 100644
index 000000000..505da43f9
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/dyn_ty.rs
@@ -0,0 +1,81 @@
+use super::{builder::ClauseBuilder, generalize};
+use crate::RustIrDatabase;
+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
+/// traits. For example, a `dyn Write` type implements `Write` and so on.
+///
+/// To see how this works, consider as an example the type `dyn Fn(&u8)`. This
+/// is really shorthand for `dyn for<'a> Fn<(&'a u8), Output = ()>`, and we
+/// represent that type as something like this:
+///
+/// ```ignore
+/// dyn(exists<T> {
+/// forall<'a> { Implemented(T: Fn<'a>) },
+/// forall<'a> { AliasEq(<T as Fn<'a>>::Output, ()) },
+/// })
+/// ```
+///
+/// so what we will do is to generate one program clause for each of the
+/// conditions. Thus we get two program clauses:
+///
+/// ```ignore
+/// forall<'a> { Implemented(dyn Fn(&u8): Fn<(&'a u8)>) }
+/// ```
+///
+/// and
+///
+/// ```ignore
+/// forall<'a> { AliasEq(<dyn Fn(&u8) as Fn<'a>>::Output, ()) },
+/// ```
+pub(super) fn build_dyn_self_ty_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ self_ty: Ty<I>,
+) {
+ let interner = db.interner();
+ let dyn_ty = match self_ty.kind(interner) {
+ TyKind::Dyn(dyn_ty) => dyn_ty.clone(),
+ _ => return,
+ };
+ let generalized_dyn_ty = generalize::Generalize::apply(db.interner(), dyn_ty);
+
+ // Here, `self_ty` is the `dyn Fn(&u8)`, and `dyn_ty` is the `exists<T> { ..
+ // }` clauses shown above.
+
+ // Turn free BoundVars in the type into new existentials. E.g.
+ // we might get some `dyn Foo<?X>`, and we don't want to return
+ // a clause with a free variable. We can instead return a
+ // slightly more general clause by basically turning this into
+ // `exists<A> dyn Foo<A>`.
+
+ builder.push_binders(generalized_dyn_ty, |builder, dyn_ty| {
+ for exists_qwc in dyn_ty.bounds.map_ref(|r| r.iter(interner)) {
+ // Replace the `T` from `exists<T> { .. }` with `self_ty`,
+ // yielding clases like
+ //
+ // ```
+ // forall<'a> { Implemented(dyn Fn(&u8): Fn<(&'a u8)>) }
+ // ```
+ let qwc = exists_qwc
+ .cloned()
+ .substitute(interner, &[self_ty.clone().cast(interner)]);
+
+ 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/vendor/chalk-solve/src/clauses/env_elaborator.rs b/vendor/chalk-solve/src/clauses/env_elaborator.rs
new file mode 100644
index 000000000..29032a7ad
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/env_elaborator.rs
@@ -0,0 +1,107 @@
+use super::program_clauses::ToProgramClauses;
+use crate::clauses::builder::ClauseBuilder;
+use crate::clauses::{match_alias_ty, match_ty};
+use crate::DomainGoal;
+use crate::FromEnv;
+use crate::ProgramClause;
+use crate::RustIrDatabase;
+use crate::Ty;
+use crate::{debug_span, TyKind};
+use chalk_ir::interner::Interner;
+use chalk_ir::visit::{TypeVisitable, TypeVisitor};
+use chalk_ir::{DebruijnIndex, Environment};
+use rustc_hash::FxHashSet;
+use std::ops::ControlFlow;
+use tracing::instrument;
+
+/// When proving a `FromEnv` goal, we elaborate all `FromEnv` goals
+/// found in the environment.
+///
+/// For example, when `T: Clone` is in the environment, we can prove
+/// `T: Copy` by adding the clauses from `trait Clone`, which includes
+/// the rule `FromEnv(T: Copy) :- FromEnv(T: Clone)
+pub(super) fn elaborate_env_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ in_clauses: &[ProgramClause<I>],
+ out: &mut FxHashSet<ProgramClause<I>>,
+ environment: &Environment<I>,
+) {
+ let mut this_round = vec![];
+ let builder = &mut ClauseBuilder::new(db, &mut this_round);
+ let mut elaborater = EnvElaborator {
+ db,
+ builder,
+ environment,
+ };
+ in_clauses.visit_with(&mut elaborater, DebruijnIndex::INNERMOST);
+ out.extend(this_round);
+}
+
+struct EnvElaborator<'me, 'builder, I: Interner> {
+ db: &'me dyn RustIrDatabase<I>,
+ builder: &'builder mut ClauseBuilder<'me, I>,
+ environment: &'me Environment<I>,
+}
+
+impl<'me, 'builder, I: Interner> TypeVisitor<I> for EnvElaborator<'me, 'builder, I> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn interner(&self) -> I {
+ self.db.interner()
+ }
+ #[instrument(level = "debug", skip(self, _outer_binder))]
+ fn visit_ty(&mut self, ty: &Ty<I>, _outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ match ty.kind(self.interner()) {
+ TyKind::Alias(alias_ty) => match_alias_ty(self.builder, self.environment, alias_ty),
+ TyKind::Placeholder(_) => {}
+
+ // FIXME(#203) -- We haven't fully figured out the implied
+ // bounds story around `dyn Trait` types.
+ TyKind::Dyn(_) => (),
+
+ TyKind::Function(_) | TyKind::BoundVar(_) | TyKind::InferenceVar(_, _) => (),
+
+ _ => {
+ // This shouldn't fail because of the above clauses
+ match_ty(self.builder, self.environment, ty)
+ .map_err(|_| ())
+ .unwrap()
+ }
+ }
+ ControlFlow::Continue(())
+ }
+
+ fn visit_domain_goal(
+ &mut self,
+ domain_goal: &DomainGoal<I>,
+ outer_binder: DebruijnIndex,
+ ) -> ControlFlow<()> {
+ if let DomainGoal::FromEnv(from_env) = domain_goal {
+ debug_span!("visit_domain_goal", ?from_env);
+ match from_env {
+ FromEnv::Trait(trait_ref) => {
+ let trait_datum = self.db.trait_datum(trait_ref.trait_id);
+
+ trait_datum.to_program_clauses(self.builder, self.environment);
+
+ // If we know that `T: Iterator`, then we also know
+ // things about `<T as Iterator>::Item`, so push those
+ // implied bounds too:
+ for &associated_ty_id in &trait_datum.associated_ty_ids {
+ self.db
+ .associated_ty_data(associated_ty_id)
+ .to_program_clauses(self.builder, self.environment);
+ }
+ ControlFlow::Continue(())
+ }
+ FromEnv::Ty(ty) => ty.visit_with(self, outer_binder),
+ }
+ } else {
+ ControlFlow::Continue(())
+ }
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/generalize.rs b/vendor/chalk-solve/src/clauses/generalize.rs
new file mode 100644
index 000000000..bff05b369
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/generalize.rs
@@ -0,0 +1,99 @@
+//! This gets rid of free variables in a type by replacing them by fresh bound
+//! ones. We use this when building clauses that contain types passed to
+//! `program_clauses`; these may contain variables, and just copying those
+//! variables verbatim leads to problems. Instead, we return a slightly more
+//! general program clause, with new variables in those places. This can only
+//! happen with `dyn Trait` currently; that's the only case where we use the
+//! types passed to `program_clauses` in the clauses we generate.
+
+use chalk_derive::FallibleTypeFolder;
+use chalk_ir::{
+ fold::{TypeFoldable, TypeFolder},
+ interner::{HasInterner, Interner},
+ Binders, BoundVar, Const, ConstData, ConstValue, DebruijnIndex, Lifetime, LifetimeData, Ty,
+ TyKind, TyVariableKind, VariableKind, VariableKinds,
+};
+use rustc_hash::FxHashMap;
+
+#[derive(FallibleTypeFolder)]
+pub struct Generalize<I: Interner> {
+ binders: Vec<VariableKind<I>>,
+ mapping: FxHashMap<BoundVar, usize>,
+ interner: I,
+}
+
+impl<I: Interner> Generalize<I> {
+ pub fn apply<T>(interner: I, value: T) -> Binders<T>
+ where
+ T: HasInterner<Interner = I> + TypeFoldable<I>,
+ {
+ let mut generalize = Generalize {
+ binders: Vec::new(),
+ mapping: FxHashMap::default(),
+ interner,
+ };
+ let value = value
+ .try_fold_with(&mut generalize, DebruijnIndex::INNERMOST)
+ .unwrap();
+ Binders::new(
+ VariableKinds::from_iter(interner, generalize.binders),
+ value,
+ )
+ }
+}
+
+impl<I: Interner> TypeFolder<I> for Generalize<I> {
+ fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
+ self
+ }
+
+ fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty<I> {
+ let binder_vec = &mut self.binders;
+ let new_index = self.mapping.entry(bound_var).or_insert_with(|| {
+ let i = binder_vec.len();
+ binder_vec.push(VariableKind::Ty(TyVariableKind::General));
+ i
+ });
+ let new_var = BoundVar::new(outer_binder, *new_index);
+ TyKind::BoundVar(new_var).intern(TypeFolder::interner(self))
+ }
+
+ fn fold_free_var_const(
+ &mut self,
+ ty: Ty<I>,
+ bound_var: BoundVar,
+ outer_binder: DebruijnIndex,
+ ) -> Const<I> {
+ let binder_vec = &mut self.binders;
+ let new_index = self.mapping.entry(bound_var).or_insert_with(|| {
+ let i = binder_vec.len();
+ binder_vec.push(VariableKind::Const(ty.clone()));
+ i
+ });
+ let new_var = BoundVar::new(outer_binder, *new_index);
+ ConstData {
+ ty,
+ value: ConstValue::BoundVar(new_var),
+ }
+ .intern(TypeFolder::interner(self))
+ }
+
+ fn fold_free_var_lifetime(
+ &mut self,
+ bound_var: BoundVar,
+ outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let binder_vec = &mut self.binders;
+ let new_index = self.mapping.entry(bound_var).or_insert_with(|| {
+ let i = binder_vec.len();
+ binder_vec.push(VariableKind::Lifetime);
+ i
+ });
+ let new_var = BoundVar::new(outer_binder, *new_index);
+ LifetimeData::BoundVar(new_var).intern(TypeFolder::interner(self))
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/program_clauses.rs b/vendor/chalk-solve/src/clauses/program_clauses.rs
new file mode 100644
index 000000000..19811ff8b
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/program_clauses.rs
@@ -0,0 +1,921 @@
+use crate::clauses::builder::ClauseBuilder;
+use crate::rust_ir::*;
+use crate::split::Split;
+use chalk_ir::cast::{Cast, Caster};
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use std::iter;
+use tracing::instrument;
+
+/// 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.
+pub trait ToProgramClauses<I: Interner> {
+ fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>, environment: &Environment<I>);
+}
+
+impl<I: Interner> ToProgramClauses<I> for ImplDatum<I> {
+ /// Given `impl<T: Clone> Clone for Vec<T> { ... }`, generate:
+ ///
+ /// ```notrust
+ /// -- Rule Implemented-From-Impl
+ /// forall<T> {
+ /// Implemented(Vec<T>: Clone) :- Implemented(T: Clone).
+ /// }
+ /// ```
+ ///
+ /// For a negative impl like `impl... !Clone for ...`, however, we
+ /// generate nothing -- this is just a way to *opt out* from the
+ /// default auto trait impls, it doesn't have any positive effect
+ /// on its own.
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ if self.is_positive() {
+ let binders = self.binders.clone();
+ builder.push_binders(
+ binders,
+ |builder,
+ ImplDatumBound {
+ trait_ref,
+ where_clauses,
+ }| {
+ builder.push_clause(trait_ref, where_clauses);
+ },
+ );
+ }
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for AssociatedTyValue<I> {
+ /// Given the following trait:
+ ///
+ /// ```notrust
+ /// trait Iterable {
+ /// type IntoIter<'a>: 'a;
+ /// }
+ /// ```
+ ///
+ /// Then for the following impl:
+ /// ```notrust
+ /// impl<T> Iterable for Vec<T> where T: Clone {
+ /// type IntoIter<'a> = Iter<'a, T>;
+ /// }
+ /// ```
+ ///
+ /// we generate:
+ ///
+ /// ```notrust
+ /// -- Rule Normalize-From-Impl
+ /// forall<'a, T> {
+ /// Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
+ /// Implemented(T: Clone), // (1)
+ /// Implemented(Iter<'a, T>: 'a). // (2)
+ /// }
+ /// ```
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ let impl_datum = builder.db.impl_datum(self.impl_id);
+ let associated_ty = builder.db.associated_ty_data(self.associated_ty_id);
+
+ builder.push_binders(self.value.clone(), |builder, assoc_ty_value| {
+ let all_parameters = builder.placeholders_in_scope().to_vec();
+
+ // Get the projection for this associated type:
+ //
+ // * `impl_params`: `[!T]`
+ // * `projection`: `<Vec<!T> as Iterable>::Iter<'!a>`
+ let (impl_params, projection) = builder
+ .db
+ .impl_parameters_and_projection_from_associated_ty_value(&all_parameters, self);
+
+ // Assemble the full list of conditions for projection to be valid.
+ // This comes in two parts, marked as (1) and (2) in doc above:
+ //
+ // 1. require that the where clauses from the impl apply
+ let interner = builder.db.interner();
+ let impl_where_clauses = impl_datum
+ .binders
+ .map_ref(|b| &b.where_clauses)
+ .into_iter()
+ .map(|wc| wc.cloned().substitute(interner, impl_params));
+
+ // 2. any where-clauses from the `type` declaration in the trait: the
+ // parameters must be substituted with those of the impl
+ let assoc_ty_where_clauses = associated_ty
+ .binders
+ .map_ref(|b| &b.where_clauses)
+ .into_iter()
+ .map(|wc| wc.cloned().substitute(interner, &projection.substitution));
+
+ // Create the final program clause:
+ //
+ // ```notrust
+ // -- Rule Normalize-From-Impl
+ // forall<'a, T> {
+ // Normalize(<Vec<T> as Iterable>::IntoIter<'a> -> Iter<'a, T>>) :-
+ // Implemented(T: Clone), // (1)
+ // Implemented(Iter<'a, T>: 'a). // (2)
+ // }
+ // ```
+ builder.push_clause(
+ Normalize {
+ alias: AliasTy::Projection(projection.clone()),
+ ty: assoc_ty_value.ty,
+ },
+ impl_where_clauses.chain(assoc_ty_where_clauses),
+ );
+ });
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
+ /// Given `opaque type T<U>: A + B = HiddenTy where U: C;`, we generate:
+ ///
+ /// ```notrust
+ /// AliasEq(T<U> = HiddenTy) :- Reveal.
+ /// AliasEq(T<U> = !T<U>).
+ /// WF(T<U>) :- WF(U: C).
+ /// Implemented(!T<U>: A).
+ /// Implemented(!T<U>: B).
+ /// ```
+ /// where `!T<..>` is the placeholder for the unnormalized type `T<..>`.
+ #[instrument(level = "debug", skip(builder))]
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ builder.push_binders(self.bound.clone(), |builder, opaque_ty_bound| {
+ let interner = builder.interner();
+ let substitution = builder.substitution_in_scope();
+ let alias = AliasTy::Opaque(OpaqueTy {
+ opaque_ty_id: self.opaque_ty_id,
+ substitution: substitution.clone(),
+ });
+
+ let alias_placeholder_ty =
+ TyKind::OpaqueType(self.opaque_ty_id, substitution).intern(interner);
+
+ // AliasEq(T<..> = HiddenTy) :- Reveal.
+ builder.push_clause(
+ DomainGoal::Holds(
+ AliasEq {
+ alias: alias.clone(),
+ ty: builder.db.hidden_opaque_type(self.opaque_ty_id),
+ }
+ .cast(interner),
+ ),
+ iter::once(DomainGoal::Reveal),
+ );
+
+ // AliasEq(T<..> = !T<..>).
+ builder.push_fact(DomainGoal::Holds(
+ AliasEq {
+ alias,
+ ty: alias_placeholder_ty.clone(),
+ }
+ .cast(interner),
+ ));
+
+ // WF(!T<..>) :- WF(WC).
+ builder.push_binders(opaque_ty_bound.where_clauses, |builder, where_clauses| {
+ builder.push_clause(
+ WellFormed::Ty(alias_placeholder_ty.clone()),
+ where_clauses
+ .into_iter()
+ .map(|wc| wc.into_well_formed_goal(interner)),
+ );
+ });
+
+ 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 {
+ // 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(..) => {}
+ });
+ }
+ });
+ }
+}
+
+/// Generates the "well-formed" program clauses for an applicative type
+/// with the name `type_name`. For example, given a struct definition:
+///
+/// ```ignore
+/// struct Foo<T: Eq> { }
+/// ```
+///
+/// we would generate the clause:
+///
+/// ```notrust
+/// forall<T> {
+/// WF(Foo<T>) :- WF(T: Eq).
+/// }
+/// ```
+///
+/// # Parameters
+/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
+/// - type_name -- in our example above, the name `Foo`
+/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example)
+fn well_formed_program_clauses<'a, I, Wc>(
+ builder: &'a mut ClauseBuilder<'_, I>,
+ ty: Ty<I>,
+ where_clauses: Wc,
+) where
+ I: Interner,
+ Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
+{
+ let interner = builder.interner();
+ builder.push_clause(
+ WellFormed::Ty(ty),
+ where_clauses
+ .cloned()
+ .map(|qwc| qwc.into_well_formed_goal(interner)),
+ );
+}
+
+/// Generates the "fully visible" program clauses for an applicative type
+/// with the name `type_name`. For example, given a struct definition:
+///
+/// ```ignore
+/// struct Foo<T: Eq> { }
+/// ```
+///
+/// we would generate the clause:
+///
+/// ```notrust
+/// forall<T> {
+/// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
+/// }
+/// ```
+///
+/// # Parameters
+///
+/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
+/// - type_name -- in our example above, the name `Foo`
+fn fully_visible_program_clauses<I>(
+ builder: &mut ClauseBuilder<'_, I>,
+ ty: Ty<I>,
+ subst: &Substitution<I>,
+) where
+ I: Interner,
+{
+ let interner = builder.interner();
+ builder.push_clause(
+ DomainGoal::IsFullyVisible(ty),
+ subst
+ .type_parameters(interner)
+ .map(|typ| DomainGoal::IsFullyVisible(typ).cast::<Goal<_>>(interner)),
+ );
+}
+
+/// Generates the "implied bounds" clauses for an applicative
+/// type with the name `type_name`. For example, if `type_name`
+/// represents a struct `S` that is declared like:
+///
+/// ```ignore
+/// struct S<T> where T: Eq { }
+/// ```
+///
+/// then we would generate the rule:
+///
+/// ```notrust
+/// FromEnv(T: Eq) :- FromEnv(S<T>)
+/// ```
+///
+/// # Parameters
+///
+/// - builder -- the clause builder. We assume all the generic types from `S` are in scope.
+/// - type_name -- in our example above, the name `S`
+/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example).
+fn implied_bounds_program_clauses<'a, I, Wc>(
+ builder: &'a mut ClauseBuilder<'_, I>,
+ ty: &Ty<I>,
+ where_clauses: Wc,
+) where
+ I: Interner,
+ Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
+{
+ let interner = builder.interner();
+
+ for qwc in where_clauses {
+ builder.push_binders(qwc.clone(), |builder, wc| {
+ builder.push_clause(wc.into_from_env_goal(interner), Some(ty.clone().from_env()));
+ });
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for AdtDatum<I> {
+ /// Given the following type definition: `struct Foo<T: Eq> { }`, generate:
+ ///
+ /// ```notrust
+ /// -- Rule WellFormed-Type
+ /// forall<T> {
+ /// WF(Foo<T>) :- WF(T: Eq).
+ /// }
+ ///
+ /// -- Rule Implied-Bound-From-Type
+ /// forall<T> {
+ /// FromEnv(T: Eq) :- FromEnv(Foo<T>).
+ /// }
+ ///
+ /// forall<T> {
+ /// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
+ /// }
+ /// ```
+ ///
+ /// If the type `Foo` is marked `#[upstream]`, we also generate:
+ ///
+ /// ```notrust
+ /// forall<T> { IsUpstream(Foo<T>). }
+ /// ```
+ ///
+ /// Otherwise, if the type `Foo` is not marked `#[upstream]`, we generate:
+ /// ```notrust
+ /// forall<T> { IsLocal(Foo<T>). }
+ /// ```
+ ///
+ /// Given an `#[upstream]` type that is also fundamental:
+ ///
+ /// ```notrust
+ /// #[upstream]
+ /// #[fundamental]
+ /// struct Box<T, U> {}
+ /// ```
+ ///
+ /// We generate the following clauses:
+ ///
+ /// ```notrust
+ /// forall<T, U> { IsLocal(Box<T, U>) :- IsLocal(T). }
+ /// forall<T, U> { IsLocal(Box<T, U>) :- IsLocal(U). }
+ ///
+ /// forall<T, U> { IsUpstream(Box<T, U>) :- IsUpstream(T), IsUpstream(U). }
+ ///
+ /// // Generated for both upstream and local fundamental types
+ /// forall<T, U> { DownstreamType(Box<T, U>) :- DownstreamType(T). }
+ /// forall<T, U> { DownstreamType(Box<T, U>) :- DownstreamType(U). }
+ /// ```
+ ///
+ #[instrument(level = "debug", skip(builder))]
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ let interner = builder.interner();
+ let binders = self.binders.map_ref(|b| &b.where_clauses).cloned();
+
+ builder.push_binders(binders, |builder, where_clauses| {
+ let self_ty = TyKind::Adt(self.id, builder.substitution_in_scope()).intern(interner);
+
+ well_formed_program_clauses(builder, self_ty.clone(), where_clauses.iter());
+
+ implied_bounds_program_clauses(builder, &self_ty, where_clauses.iter());
+
+ fully_visible_program_clauses(
+ builder,
+ self_ty.clone(),
+ &builder.substitution_in_scope(),
+ );
+
+ // Types that are not marked `#[upstream]` satisfy IsLocal(Ty)
+ if !self.flags.upstream {
+ // `IsLocalTy(Ty)` depends *only* on whether the type
+ // is marked #[upstream] and nothing else
+ builder.push_fact(DomainGoal::IsLocal(self_ty.clone()));
+ } else if self.flags.fundamental {
+ // If a type is `#[upstream]`, but is also
+ // `#[fundamental]`, it satisfies IsLocal if and only
+ // if its parameters satisfy IsLocal
+ for type_param in builder.substitution_in_scope().type_parameters(interner) {
+ builder.push_clause(
+ DomainGoal::IsLocal(self_ty.clone()),
+ Some(DomainGoal::IsLocal(type_param)),
+ );
+ }
+ builder.push_clause(
+ DomainGoal::IsUpstream(self_ty.clone()),
+ builder
+ .substitution_in_scope()
+ .type_parameters(interner)
+ .map(|type_param| DomainGoal::IsUpstream(type_param)),
+ );
+ } else {
+ // The type is just upstream and not fundamental
+ builder.push_fact(DomainGoal::IsUpstream(self_ty.clone()));
+ }
+
+ if self.flags.fundamental {
+ assert!(
+ builder
+ .substitution_in_scope()
+ .type_parameters(interner)
+ .count()
+ >= 1,
+ "Only fundamental types with type parameters are supported"
+ );
+ for type_param in builder.substitution_in_scope().type_parameters(interner) {
+ builder.push_clause(
+ DomainGoal::DownstreamType(self_ty.clone()),
+ Some(DomainGoal::DownstreamType(type_param)),
+ );
+ }
+ }
+ });
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for FnDefDatum<I> {
+ /// Given the following function definition: `fn bar<T>() where T: Eq`, generate:
+ ///
+ /// ```notrust
+ /// -- Rule WellFormed-Type
+ /// forall<T> {
+ /// WF(bar<T>) :- WF(T: Eq)
+ /// }
+ ///
+ /// -- Rule Implied-Bound-From-Type
+ /// forall<T> {
+ /// FromEnv(T: Eq) :- FromEnv(bar<T>).
+ /// }
+ ///
+ /// forall<T> {
+ /// IsFullyVisible(bar<T>) :- IsFullyVisible(T).
+ /// }
+ /// ```
+ #[instrument(level = "debug", skip(builder))]
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ let interner = builder.interner();
+ let binders = self.binders.map_ref(|b| &b.where_clauses).cloned();
+
+ builder.push_binders(binders, |builder, where_clauses| {
+ let ty = TyKind::FnDef(self.id, builder.substitution_in_scope()).intern(interner);
+
+ well_formed_program_clauses(builder, ty.clone(), where_clauses.iter());
+
+ implied_bounds_program_clauses(builder, &ty, where_clauses.iter());
+
+ fully_visible_program_clauses(builder, ty, &builder.substitution_in_scope());
+ });
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> {
+ /// Given the following trait declaration: `trait Ord<T> where Self: Eq<T> { ... }`, generate:
+ ///
+ /// ```notrust
+ /// -- Rule WellFormed-TraitRef
+ /// forall<Self, T> {
+ /// WF(Self: Ord<T>) :- Implemented(Self: Ord<T>), WF(Self: Eq<T>).
+ /// }
+ /// ```
+ ///
+ /// and the reverse rules:
+ ///
+ /// ```notrust
+ /// -- Rule Implemented-From-Env
+ /// forall<Self, T> {
+ /// (Self: Ord<T>) :- FromEnv(Self: Ord<T>).
+ /// }
+ ///
+ /// -- Rule Implied-Bound-From-Trait
+ /// forall<Self, T> {
+ /// FromEnv(Self: Eq<T>) :- FromEnv(Self: Ord<T>).
+ /// }
+ /// ```
+ ///
+ /// As specified in the orphan rules, if a trait is not marked `#[upstream]`, the current crate
+ /// can implement it for any type. To represent that, we generate:
+ ///
+ /// ```notrust
+ /// // `Ord<T>` would not be `#[upstream]` when compiling `std`
+ /// forall<Self, T> { LocalImplAllowed(Self: Ord<T>). }
+ /// ```
+ ///
+ /// For traits that are `#[upstream]` (i.e. not in the current crate), the orphan rules dictate
+ /// that impls are allowed as long as at least one type parameter is local and each type
+ /// prior to that is fully visible. That means that each type prior to the first local
+ /// type cannot contain any of the type parameters of the impl.
+ ///
+ /// This rule is fairly complex, so we expand it and generate a program clause for each
+ /// possible case. This is represented as follows:
+ ///
+ /// ```notrust
+ /// // for `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
+ /// forall<Self, T, U, V> {
+ /// LocalImplAllowed(Self: Foo<T, U, V>) :- IsLocal(Self).
+ /// }
+ ///
+ /// forall<Self, T, U, V> {
+ /// LocalImplAllowed(Self: Foo<T, U, V>) :-
+ /// IsFullyVisible(Self),
+ /// IsLocal(T).
+ /// }
+ ///
+ /// forall<Self, T, U, V> {
+ /// LocalImplAllowed(Self: Foo<T, U, V>) :-
+ /// IsFullyVisible(Self),
+ /// IsFullyVisible(T),
+ /// IsLocal(U).
+ /// }
+ ///
+ /// forall<Self, T, U, V> {
+ /// LocalImplAllowed(Self: Foo<T, U, V>) :-
+ /// IsFullyVisible(Self),
+ /// IsFullyVisible(T),
+ /// IsFullyVisible(U),
+ /// IsLocal(V).
+ /// }
+ /// ```
+ ///
+ /// The overlap check uses compatible { ... } mode to ensure that it accounts for impls that
+ /// may exist in some other *compatible* world. For every upstream trait, we add a rule to
+ /// account for the fact that upstream crates are able to compatibly add impls of upstream
+ /// traits for upstream types.
+ ///
+ /// ```notrust
+ /// // For `#[upstream] trait Foo<T, U, V> where Self: Eq<T> { ... }`
+ /// forall<Self, T, U, V> {
+ /// Implemented(Self: Foo<T, U, V>) :-
+ /// Implemented(Self: Eq<T>), // where clauses
+ /// Compatible, // compatible modality
+ /// IsUpstream(Self),
+ /// IsUpstream(T),
+ /// IsUpstream(U),
+ /// IsUpstream(V),
+ /// CannotProve. // returns ambiguous
+ /// }
+ /// ```
+ ///
+ /// In certain situations, this is too restrictive. Consider the following code:
+ ///
+ /// ```notrust
+ /// /* In crate std */
+ /// trait Sized { }
+ /// struct str { }
+ ///
+ /// /* In crate bar (depends on std) */
+ /// trait Bar { }
+ /// impl Bar for str { }
+ /// impl<T> Bar for T where T: Sized { }
+ /// ```
+ ///
+ /// Here, because of the rules we've defined, these two impls overlap. The std crate is
+ /// upstream to bar, and thus it is allowed to compatibly implement Sized for str. If str
+ /// can implement Sized in a compatible future, these two impls definitely overlap since the
+ /// second impl covers all types that implement Sized.
+ ///
+ /// The solution we've got right now is to mark Sized as "fundamental" when it is defined.
+ /// This signals to the Rust compiler that it can rely on the fact that str does not
+ /// implement Sized in all contexts. A consequence of this is that we can no longer add an
+ /// implementation of Sized compatibly for str. This is the trade off you make when defining
+ /// a fundamental trait.
+ ///
+ /// To implement fundamental traits, we simply just do not add the rule above that allows
+ /// upstream types to implement upstream traits. Fundamental traits are not allowed to
+ /// compatibly do that.
+ fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>, environment: &Environment<I>) {
+ let interner = builder.interner();
+ let binders = self.binders.map_ref(|b| &b.where_clauses).cloned();
+ builder.push_binders(binders, |builder, where_clauses| {
+ let trait_ref = chalk_ir::TraitRef {
+ trait_id: self.id,
+ substitution: builder.substitution_in_scope(),
+ };
+
+ builder.push_clause(
+ trait_ref.clone().well_formed(),
+ where_clauses
+ .iter()
+ .cloned()
+ .map(|qwc| qwc.into_well_formed_goal(interner))
+ .casted::<Goal<_>>(interner)
+ .chain(Some(trait_ref.clone().cast(interner))),
+ );
+
+ // The number of parameters will always be at least 1
+ // because of the Self parameter that is automatically
+ // added to every trait. This is important because
+ // otherwise the added program clauses would not have any
+ // conditions.
+ let type_parameters: Vec<_> = trait_ref.type_parameters(interner).collect();
+
+ if environment.has_compatible_clause(interner) {
+ // Note: even though we do check for a `Compatible` clause here,
+ // we also keep it as a condition for the clauses below, purely
+ // for logical consistency. But really, it's not needed and could be
+ // removed.
+
+ // Drop trait can't have downstream implementation because it can only
+ // be implemented with the same genericity as the struct definition,
+ // i.e. Drop implementation for `struct S<T: Eq> {}` is forced to be
+ // `impl Drop<T: Eq> for S<T> { ... }`. That means that orphan rules
+ // prevent Drop from being implemented in downstream crates.
+ if self.well_known != Some(WellKnownTrait::Drop) {
+ // Add all cases for potential downstream impls that could exist
+ for i in 0..type_parameters.len() {
+ builder.push_clause(
+ trait_ref.clone(),
+ where_clauses
+ .iter()
+ .cloned()
+ .casted(interner)
+ .chain(iter::once(DomainGoal::Compatible.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))),
+ );
+ }
+ }
+
+ // Fundamental traits can be reasoned about negatively without any ambiguity, so no
+ // need for this rule if the trait is fundamental.
+ if !self.flags.fundamental {
+ builder.push_clause(
+ trait_ref.clone(),
+ where_clauses
+ .iter()
+ .cloned()
+ .casted(interner)
+ .chain(iter::once(DomainGoal::Compatible.cast(interner)))
+ .chain(
+ trait_ref
+ .type_parameters(interner)
+ .map(|ty| DomainGoal::IsUpstream(ty).cast(interner)),
+ )
+ .chain(iter::once(GoalData::CannotProve.intern(interner))),
+ );
+ }
+ }
+
+ // Orphan rules:
+ if !self.flags.upstream {
+ // Impls for traits declared locally always pass the impl rules
+ builder.push_fact(DomainGoal::LocalImplAllowed(trait_ref.clone()));
+ } else {
+ // Impls for remote traits must have a local type in the right place
+ for i in 0..type_parameters.len() {
+ builder.push_clause(
+ DomainGoal::LocalImplAllowed(trait_ref.clone()),
+ (0..i)
+ .map(|j| DomainGoal::IsFullyVisible(type_parameters[j].clone()))
+ .chain(Some(DomainGoal::IsLocal(type_parameters[i].clone()))),
+ );
+ }
+ }
+
+ // Reverse implied bound rules: given (e.g.) `trait Foo: Bar + Baz`,
+ // we create rules like:
+ //
+ // ```
+ // FromEnv(T: Bar) :- FromEnv(T: Foo)
+ // ```
+ //
+ // and
+ //
+ // ```
+ // FromEnv(T: Baz) :- FromEnv(T: Foo)
+ // ```
+ for qwc in where_clauses {
+ builder.push_binders(qwc, |builder, wc| {
+ builder.push_clause(
+ wc.into_from_env_goal(interner),
+ Some(trait_ref.clone().from_env()),
+ );
+ });
+ }
+
+ // Finally, for every trait `Foo` we make a rule
+ //
+ // ```
+ // Implemented(T: Foo) :- FromEnv(T: Foo)
+ // ```
+ builder.push_clause(trait_ref.clone(), Some(trait_ref.from_env()));
+ });
+ }
+}
+
+impl<I: Interner> ToProgramClauses<I> for AssociatedTyDatum<I> {
+ /// For each associated type, we define the "projection
+ /// equality" rules. There are always two; one for a successful normalization,
+ /// and one for the "fallback" notion of equality.
+ ///
+ /// Given: (here, `'a` and `T` represent zero or more parameters)
+ ///
+ /// ```notrust
+ /// trait Foo {
+ /// type Assoc<'a, T>: Bounds where WC;
+ /// }
+ /// ```
+ ///
+ /// we generate the 'fallback' rule:
+ ///
+ /// ```notrust
+ /// -- Rule AliasEq-Placeholder
+ /// forall<Self, 'a, T> {
+ /// AliasEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>).
+ /// }
+ /// ```
+ ///
+ /// and
+ ///
+ /// ```notrust
+ /// -- Rule AliasEq-Normalize
+ /// forall<Self, 'a, T, U> {
+ /// AliasEq(<T as Foo>::Assoc<'a, T> = U) :-
+ /// Normalize(<T as Foo>::Assoc -> U).
+ /// }
+ /// ```
+ ///
+ /// We used to generate an "elaboration" rule like this:
+ ///
+ /// ```notrust
+ /// forall<T> {
+ /// T: Foo :- exists<U> { AliasEq(<T as Foo>::Assoc = U) }.
+ /// }
+ /// ```
+ ///
+ /// but this caused problems with the recursive solver. In
+ /// particular, whenever normalization is possible, we cannot
+ /// solve that projection uniquely, since we can now elaborate
+ /// `AliasEq` to fallback *or* normalize it. So instead we
+ /// handle this kind of reasoning through the `FromEnv` predicate.
+ ///
+ /// We also generate rules specific to WF requirements and implied bounds:
+ ///
+ /// ```notrust
+ /// -- Rule WellFormed-AssocTy
+ /// forall<Self, 'a, T> {
+ /// WellFormed((Foo::Assoc)<Self, 'a, T>) :- WellFormed(Self: Foo), WellFormed(WC).
+ /// }
+ ///
+ /// -- Rule Implied-WC-From-AssocTy
+ /// forall<Self, 'a, T> {
+ /// FromEnv(WC) :- FromEnv((Foo::Assoc)<Self, 'a, T>).
+ /// }
+ ///
+ /// -- Rule Implied-Bound-From-AssocTy
+ /// forall<Self, 'a, T> {
+ /// FromEnv(<Self as Foo>::Assoc<'a,T>: Bounds) :- FromEnv(Self: Foo), WC.
+ /// }
+ ///
+ /// -- Rule Implied-Trait-From-AssocTy
+ /// forall<Self,'a, T> {
+ /// FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self, 'a,T>).
+ /// }
+ /// ```
+ fn to_program_clauses(
+ &self,
+ builder: &mut ClauseBuilder<'_, I>,
+ _environment: &Environment<I>,
+ ) {
+ let interner = builder.interner();
+ let binders = self.binders.clone();
+ builder.push_binders(
+ binders,
+ |builder,
+ AssociatedTyDatumBound {
+ where_clauses,
+ bounds,
+ }| {
+ let substitution = builder.substitution_in_scope();
+
+ let projection = ProjectionTy {
+ associated_ty_id: self.id,
+ substitution: substitution.clone(),
+ };
+ let projection_ty = AliasTy::Projection(projection.clone()).intern(interner);
+
+ // Retrieve the trait ref embedding the associated type
+ let trait_ref = builder.db.trait_ref_from_projection(&projection);
+
+ // Construct an application from the projection. So if we have `<T as Iterator>::Item`,
+ // we would produce `(Iterator::Item)<T>`.
+ let ty = TyKind::AssociatedType(self.id, substitution).intern(interner);
+
+ let projection_eq = AliasEq {
+ alias: AliasTy::Projection(projection.clone()),
+ ty: ty.clone(),
+ };
+
+ // Fallback rule. The solver uses this to move between the projection
+ // and placeholder type.
+ //
+ // forall<Self> {
+ // AliasEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>).
+ // }
+ builder.push_fact_with_priority(projection_eq, None, ClausePriority::Low);
+
+ // Well-formedness of projection type.
+ //
+ // forall<Self> {
+ // WellFormed((Foo::Assoc)<Self>) :- WellFormed(Self: Foo), WellFormed(WC).
+ // }
+ builder.push_clause(
+ WellFormed::Ty(ty.clone()),
+ iter::once(WellFormed::Trait(trait_ref.clone()).cast::<Goal<_>>(interner))
+ .chain(
+ where_clauses
+ .iter()
+ .cloned()
+ .map(|qwc| qwc.into_well_formed_goal(interner))
+ .casted(interner),
+ ),
+ );
+
+ // Assuming well-formedness of projection type means we can assume
+ // the trait ref as well. Mostly used in function bodies.
+ //
+ // forall<Self> {
+ // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>).
+ // }
+ builder.push_clause(FromEnv::Trait(trait_ref.clone()), Some(ty.from_env()));
+
+ // Reverse rule for where clauses.
+ //
+ // forall<Self> {
+ // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>).
+ // }
+ //
+ // This is really a family of clauses, one for each where clause.
+ for qwc in &where_clauses {
+ builder.push_binders(qwc.clone(), |builder, wc| {
+ builder.push_clause(
+ wc.into_from_env_goal(interner),
+ Some(FromEnv::Ty(ty.clone())),
+ );
+ });
+ }
+
+ // Reverse rule for implied bounds.
+ //
+ // forall<Self> {
+ // FromEnv(<Self as Foo>::Assoc: Bounds) :- FromEnv(Self: Foo), WC
+ // }
+ for quantified_bound in bounds {
+ builder.push_binders(quantified_bound, |builder, bound| {
+ for wc in bound.into_where_clauses(interner, projection_ty.clone()) {
+ builder.push_clause(
+ wc.into_from_env_goal(interner),
+ iter::once(
+ FromEnv::Trait(trait_ref.clone()).cast::<Goal<_>>(interner),
+ )
+ .chain(where_clauses.iter().cloned().casted(interner)),
+ );
+ }
+ });
+ }
+
+ // add new type parameter U
+ builder.push_bound_ty(|builder, ty| {
+ // `Normalize(<T as Foo>::Assoc -> U)`
+ let normalize = Normalize {
+ alias: AliasTy::Projection(projection.clone()),
+ ty: ty.clone(),
+ };
+
+ // `AliasEq(<T as Foo>::Assoc = U)`
+ let projection_eq = AliasEq {
+ alias: AliasTy::Projection(projection),
+ ty,
+ };
+
+ // Projection equality rule from above.
+ //
+ // forall<T, U> {
+ // AliasEq(<T as Foo>::Assoc = U) :-
+ // Normalize(<T as Foo>::Assoc -> U).
+ // }
+ builder.push_clause(projection_eq, Some(normalize));
+ });
+ },
+ );
+ }
+}
diff --git a/vendor/chalk-solve/src/clauses/super_traits.rs b/vendor/chalk-solve/src/clauses/super_traits.rs
new file mode 100644
index 000000000..3110b03e8
--- /dev/null
+++ b/vendor/chalk-solve/src/clauses/super_traits.rs
@@ -0,0 +1,118 @@
+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_trait_super_clauses<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ builder: &mut ClauseBuilder<'_, I>,
+ trait_ref: TraitRef<I>,
+) {
+ let interner = db.interner();
+ // 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);
+
+ 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<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ trait_id: TraitId<I>,
+) -> Binders<Vec<Binders<TraitRef<I>>>> {
+ 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<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ trait_ref: Binders<TraitRef<I>>,
+ seen_traits: &mut FxHashSet<TraitId<I>>,
+ trait_refs: &mut Vec<Binders<TraitRef<I>>>,
+ ) {
+ 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::<Vec<_>>()
+ })
+ // 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<Vec<>>` into a `Vec<Binders<>>` 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/vendor/chalk-solve/src/coherence.rs b/vendor/chalk-solve/src/coherence.rs
new file mode 100644
index 000000000..5528b9a21
--- /dev/null
+++ b/vendor/chalk-solve/src/coherence.rs
@@ -0,0 +1,149 @@
+use indexmap::IndexMap;
+use petgraph::prelude::*;
+use rustc_hash::FxHashMap;
+
+use crate::solve::Solver;
+use crate::RustIrDatabase;
+use chalk_ir::interner::Interner;
+use chalk_ir::{self, ImplId, TraitId};
+use std::fmt;
+use std::sync::Arc;
+
+pub mod orphan;
+mod solve;
+
+pub struct CoherenceSolver<'a, I: Interner> {
+ db: &'a dyn RustIrDatabase<I>,
+ solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
+ trait_id: TraitId<I>,
+}
+
+#[derive(Debug)]
+pub enum CoherenceError<I: Interner> {
+ OverlappingImpls(TraitId<I>),
+ FailedOrphanCheck(TraitId<I>),
+}
+
+impl<I: Interner> fmt::Display for CoherenceError<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ CoherenceError::OverlappingImpls(id) => {
+ write!(f, "overlapping impls of trait `{:?}`", id)
+ }
+ CoherenceError::FailedOrphanCheck(id) => {
+ write!(f, "impl for trait `{:?}` violates the orphan rules", id)
+ }
+ }
+ }
+}
+
+impl<I: Interner> std::error::Error for CoherenceError<I> {}
+
+/// Stores the specialization priorities for a set of impls.
+/// This basically encodes which impls specialize one another.
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct SpecializationPriorities<I: Interner> {
+ map: IndexMap<ImplId<I>, SpecializationPriority>,
+}
+
+impl<I: Interner> SpecializationPriorities<I> {
+ pub fn new() -> Self {
+ Self {
+ map: IndexMap::new(),
+ }
+ }
+
+ /// Lookup the priority of an impl in the set (panics if impl is not in set).
+ pub fn priority(&self, impl_id: ImplId<I>) -> SpecializationPriority {
+ self.map[&impl_id]
+ }
+
+ /// Store the priority of an impl (used during construction).
+ /// Panics if we have already stored the priority for this impl.
+ fn insert(&mut self, impl_id: ImplId<I>, p: SpecializationPriority) {
+ let old_value = self.map.insert(impl_id, p);
+ assert!(old_value.is_none());
+ }
+}
+
+/// Impls with higher priority take precedence over impls with lower
+/// priority (if both apply to the same types). Impls with equal
+/// priority should never apply to the same set of input types.
+#[derive(Copy, Clone, Default, PartialOrd, Ord, PartialEq, Eq, Debug)]
+pub struct SpecializationPriority(usize);
+
+impl<'a, I> CoherenceSolver<'a, I>
+where
+ I: Interner,
+{
+ /// Constructs a new `CoherenceSolver`.
+ pub fn new(
+ db: &'a dyn RustIrDatabase<I>,
+ solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
+ trait_id: TraitId<I>,
+ ) -> Self {
+ Self {
+ db,
+ solver_builder,
+ trait_id,
+ }
+ }
+
+ pub fn specialization_priorities(
+ &self,
+ ) -> Result<Arc<SpecializationPriorities<I>>, CoherenceError<I>> {
+ let mut result = SpecializationPriorities::<I>::new();
+
+ let forest = self.build_specialization_forest()?;
+
+ // TypeVisitable every root in the forest & set specialization
+ // priority for the tree that is the root of.
+ for root_idx in forest.externals(Direction::Incoming) {
+ self.set_priorities(root_idx, &forest, 0, &mut result);
+ }
+
+ Ok(Arc::new(result))
+ }
+
+ // Build the forest of specialization relationships.
+ fn build_specialization_forest(&self) -> Result<Graph<ImplId<I>, ()>, CoherenceError<I>> {
+ let mut forest = DiGraph::new();
+ let mut node_map = FxHashMap::default();
+
+ // Find all specializations. Record them in the forest
+ // by adding an edge from the less special to the more special.
+ self.visit_specializations_of_trait(|less_special, more_special| {
+ let less_special_node = *node_map
+ .entry(less_special)
+ .or_insert_with(|| forest.add_node(less_special));
+ let more_special_node = *node_map
+ .entry(more_special)
+ .or_insert_with(|| forest.add_node(more_special));
+ forest.update_edge(less_special_node, more_special_node, ());
+ })?;
+
+ Ok(forest)
+ }
+
+ // Recursively set priorities for those node and all of its children.
+ fn set_priorities(
+ &self,
+ idx: NodeIndex,
+ forest: &Graph<ImplId<I>, ()>,
+ p: usize,
+ map: &mut SpecializationPriorities<I>,
+ ) {
+ // Get the impl datum recorded at this node and reset its priority
+ {
+ let impl_id = forest
+ .node_weight(idx)
+ .expect("index should be a valid index into graph");
+ map.insert(*impl_id, SpecializationPriority(p));
+ }
+
+ // TypeVisitable all children of this node, setting their priority to this + 1
+ for child_idx in forest.neighbors(idx) {
+ self.set_priorities(child_idx, forest, p + 1, map);
+ }
+ }
+}
diff --git a/vendor/chalk-solve/src/coherence/orphan.rs b/vendor/chalk-solve/src/coherence/orphan.rs
new file mode 100644
index 000000000..f8e06b901
--- /dev/null
+++ b/vendor/chalk-solve/src/coherence/orphan.rs
@@ -0,0 +1,44 @@
+use crate::coherence::CoherenceError;
+use crate::ext::GoalExt;
+use crate::solve::Solver;
+use crate::RustIrDatabase;
+use chalk_ir::cast::*;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use tracing::{debug, instrument};
+
+// Test if a local impl violates the orphan rules.
+//
+// For `impl<T> Trait for MyType<T>` we generate:
+//
+// forall<T> { LocalImplAllowed(MyType<T>: Trait) }
+//
+// This must be provable in order to pass the orphan check.
+#[instrument(level = "debug", skip(db, solver))]
+pub fn perform_orphan_check<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ solver: &mut dyn Solver<I>,
+ impl_id: ImplId<I>,
+) -> Result<(), CoherenceError<I>> {
+ let impl_datum = db.impl_datum(impl_id);
+ debug!(?impl_datum);
+
+ let impl_allowed: Goal<I> = impl_datum
+ .binders
+ .map_ref(|bound_impl| {
+ // Ignoring the polarization of the impl's polarized trait ref
+ DomainGoal::LocalImplAllowed(bound_impl.trait_ref.clone())
+ })
+ .cast(db.interner());
+
+ let canonical_goal = &impl_allowed.into_closed_goal(db.interner());
+ let is_allowed = solver.solve(db, canonical_goal).is_some();
+ debug!("overlaps = {:?}", is_allowed);
+
+ if !is_allowed {
+ let trait_id = impl_datum.trait_id();
+ return Err(CoherenceError::FailedOrphanCheck(trait_id));
+ }
+
+ Ok(())
+}
diff --git a/vendor/chalk-solve/src/coherence/solve.rs b/vendor/chalk-solve/src/coherence/solve.rs
new file mode 100644
index 000000000..57dd81061
--- /dev/null
+++ b/vendor/chalk-solve/src/coherence/solve.rs
@@ -0,0 +1,260 @@
+use crate::coherence::{CoherenceError, CoherenceSolver};
+use crate::debug_span;
+use crate::ext::*;
+use crate::rust_ir::*;
+use crate::{goal_builder::GoalBuilder, Solution};
+use chalk_ir::cast::*;
+use chalk_ir::fold::shift::Shift;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use itertools::Itertools;
+use tracing::{debug, instrument};
+
+impl<I: Interner> CoherenceSolver<'_, I> {
+ pub(super) fn visit_specializations_of_trait(
+ &self,
+ mut record_specialization: impl FnMut(ImplId<I>, ImplId<I>),
+ ) -> Result<(), CoherenceError<I>> {
+ // Ignore impls for marker traits as they are allowed to overlap.
+ let trait_datum = self.db.trait_datum(self.trait_id);
+ if trait_datum.flags.marker {
+ return Ok(());
+ }
+
+ // Iterate over every pair of impls for the same trait.
+ let impls = self.db.local_impls_to_coherence_check(self.trait_id);
+ for (l_id, r_id) in impls.into_iter().tuple_combinations() {
+ let lhs = &self.db.impl_datum(l_id);
+ let rhs = &self.db.impl_datum(r_id);
+
+ // Two negative impls never overlap.
+ if !lhs.is_positive() && !rhs.is_positive() {
+ continue;
+ }
+
+ // Check if the impls overlap, then if they do, check if one specializes
+ // the other. Note that specialization can only run one way - if both
+ // specialization checks return *either* true or false, that's an error.
+ if !self.disjoint(lhs, rhs) {
+ match (self.specializes(l_id, r_id), self.specializes(r_id, l_id)) {
+ (true, false) => record_specialization(l_id, r_id),
+ (false, true) => record_specialization(r_id, l_id),
+ (_, _) => {
+ return Err(CoherenceError::OverlappingImpls(self.trait_id));
+ }
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ // Test if the set of types that these two impls apply to overlap. If the test succeeds, these
+ // two impls are disjoint.
+ //
+ // We combine the binders of the two impls & treat them as existential quantifiers. Then we
+ // attempt to unify the input types to the trait provided by each impl, as well as prove that
+ // the where clauses from both impls all hold. At the end, we apply the `compatible` modality
+ // and negate the query. Negating the query means that we are asking chalk to prove that no
+ // such overlapping impl exists. By applying `compatible { G }`, chalk attempts to prove that
+ // "there exists a compatible world where G is provable." When we negate compatible, it turns
+ // into the statement "for all compatible worlds, G is not provable." This is exactly what we
+ // want since we want to ensure that there is no overlap in *all* compatible worlds, not just
+ // that there is no overlap in *some* compatible world.
+ //
+ // Examples:
+ //
+ // Impls:
+ // impl<T> Foo for T { } // rhs
+ // impl Foo for i32 { } // lhs
+ // Generates:
+ // not { compatible { exists<T> { exists<> { T = i32 } } } }
+ //
+ // Impls:
+ // impl<T1, U> Foo<T1> for Vec<U> { } // rhs
+ // impl<T2> Foo<T2> for Vec<i32> { } // lhs
+ // Generates:
+ // not { compatible { exists<T1, U> { exists<T2> { Vec<U> = Vec<i32>, T1 = T2 } } } }
+ //
+ // Impls:
+ // impl<T> Foo for Vec<T> where T: Bar { }
+ // impl<U> Foo for Vec<U> where U: Baz { }
+ // Generates:
+ // not { compatible { exists<T> { exists<U> { Vec<T> = Vec<U>, T: Bar, U: Baz } } } }
+ //
+ #[instrument(level = "debug", skip(self))]
+ fn disjoint(&self, lhs: &ImplDatum<I>, rhs: &ImplDatum<I>) -> bool {
+ let interner = self.db.interner();
+
+ let (lhs_binders, lhs_bound) = lhs.binders.as_ref().into();
+ let (rhs_binders, rhs_bound) = rhs.binders.as_ref().into();
+
+ // Upshift the rhs variables in params to account for the joined binders
+ let lhs_params = lhs_bound
+ .trait_ref
+ .substitution
+ .as_slice(interner)
+ .iter()
+ .cloned();
+ let rhs_params = rhs_bound
+ .trait_ref
+ .substitution
+ .as_slice(interner)
+ .iter()
+ .map(|param| param.clone().shifted_in(interner));
+
+ // Create an equality goal for every input type the trait, attempting
+ // to unify the inputs to both impls with one another
+ let params_goals = lhs_params
+ .zip(rhs_params)
+ .map(|(a, b)| GoalData::EqGoal(EqGoal { a, b }).intern(interner));
+
+ // Upshift the rhs variables in where clauses
+ let lhs_where_clauses = lhs_bound.where_clauses.iter().cloned();
+ let rhs_where_clauses = rhs_bound
+ .where_clauses
+ .iter()
+ .map(|wc| wc.clone().shifted_in(interner));
+
+ // Create a goal for each clause in both where clauses
+ let wc_goals = lhs_where_clauses
+ .chain(rhs_where_clauses)
+ .map(|wc| wc.cast(interner));
+
+ // Join all the goals we've created together with And, then quantify them
+ // over the joined binders. This is our query.
+ let goal = Box::new(Goal::all(interner, params_goals.chain(wc_goals)))
+ .quantify(interner, QuantifierKind::Exists, lhs_binders)
+ .quantify(interner, QuantifierKind::Exists, rhs_binders)
+ .compatible(interner)
+ .negate(interner);
+
+ let canonical_goal = &goal.into_closed_goal(interner);
+ let mut fresh_solver = (self.solver_builder)();
+ let solution = fresh_solver.solve(self.db, canonical_goal);
+ let result = match solution {
+ // Goal was proven with a unique solution, so no impl was found that causes these two
+ // to overlap
+ Some(Solution::Unique(_)) => true,
+ // Goal was ambiguous, so there *may* be overlap
+ Some(Solution::Ambig(_)) |
+ // Goal cannot be proven, so there is some impl that causes overlap
+ None => false,
+ };
+ debug!("overlaps: result = {:?}", result);
+ result
+ }
+
+ // Creates a goal which, if provable, means "more special" impl specializes the "less special" one.
+ //
+ // # General rule
+ //
+ // Given the more special impl:
+ //
+ // ```ignore
+ // impl<P0..Pn> SomeTrait<T1..Tm> for T0 where WC_more
+ // ```
+ //
+ // and less special impl
+ //
+ // ```ignore
+ // impl<Q0..Qo> SomeTrait<U1..Um> for U0 where WC_less
+ // ```
+ //
+ // create the goal:
+ //
+ // ```ignore
+ // forall<P0..Pn> {
+ // if (WC_more) {}
+ // exists<Q0..Qo> {
+ // T0 = U0, ..., Tm = Um,
+ // WC_less
+ // }
+ // }
+ // }
+ // ```
+ //
+ // # Example
+ //
+ // Given:
+ //
+ // * more: `impl<T: Clone> Foo for Vec<T>`
+ // * less: `impl<U: Clone> Foo for U`
+ //
+ // Resulting goal:
+ //
+ // ```ignore
+ // forall<T> {
+ // if (T: Clone) {
+ // exists<U> {
+ // Vec<T> = U, U: Clone
+ // }
+ // }
+ // }
+ // ```
+ #[instrument(level = "debug", skip(self))]
+ fn specializes(&self, less_special_id: ImplId<I>, more_special_id: ImplId<I>) -> bool {
+ let more_special = &self.db.impl_datum(more_special_id);
+ let less_special = &self.db.impl_datum(less_special_id);
+ debug_span!("specializes", ?less_special, ?more_special);
+
+ let interner = self.db.interner();
+
+ let gb = &mut GoalBuilder::new(self.db);
+
+ // forall<P0..Pn> { ... }
+ let goal = gb.forall(
+ &more_special.binders,
+ less_special_id,
+ |gb, _, more_special_impl, less_special_id| {
+ // if (WC_more) { ... }
+ gb.implies(more_special_impl.where_clauses.iter().cloned(), |gb| {
+ let less_special = &gb.db().impl_datum(less_special_id);
+
+ // exists<Q0..Qn> { ... }
+ gb.exists(
+ &less_special.binders,
+ more_special_impl.trait_ref.clone(),
+ |gb, _, less_special_impl, more_special_trait_ref| {
+ let interner = gb.interner();
+
+ // T0 = U0, ..., Tm = Um
+ let params_goals = more_special_trait_ref
+ .substitution
+ .as_slice(interner)
+ .iter()
+ .cloned()
+ .zip(
+ less_special_impl
+ .trait_ref
+ .substitution
+ .as_slice(interner)
+ .iter()
+ .cloned(),
+ )
+ .map(|(a, b)| GoalData::EqGoal(EqGoal { a, b }).intern(interner));
+
+ // <less_special_wc_goals> = where clauses from the less special impl
+ let less_special_wc_goals = less_special_impl
+ .where_clauses
+ .iter()
+ .cloned()
+ .casted(interner);
+
+ // <equality_goals> && WC_less
+ gb.all(params_goals.chain(less_special_wc_goals))
+ },
+ )
+ })
+ },
+ );
+
+ let canonical_goal = &goal.into_closed_goal(interner);
+ let mut fresh_solver = (self.solver_builder)();
+ let result = fresh_solver.has_unique_solution(self.db, canonical_goal);
+
+ debug!("specializes: result = {:?}", result);
+
+ result
+ }
+}
diff --git a/vendor/chalk-solve/src/coinductive_goal.rs b/vendor/chalk-solve/src/coinductive_goal.rs
new file mode 100644
index 000000000..cdb5cca10
--- /dev/null
+++ b/vendor/chalk-solve/src/coinductive_goal.rs
@@ -0,0 +1,43 @@
+use crate::RustIrDatabase;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+
+pub trait IsCoinductive<I: Interner> {
+ /// A goal G has coinductive semantics if proving G is allowed to
+ /// assume G is true (very roughly speaking). In the case of
+ /// chalk-ir, this is true for goals of the form `T: AutoTrait`,
+ /// or if it is of the form `WellFormed(T: Trait)` where `Trait`
+ /// is any trait. The latter is needed for dealing with WF
+ /// requirements and cyclic traits, which generates cycles in the
+ /// proof tree which must not be rejected but instead must be
+ /// treated as a success.
+ fn is_coinductive(&self, db: &dyn RustIrDatabase<I>) -> bool;
+}
+
+impl<I: Interner> IsCoinductive<I> for Goal<I> {
+ fn is_coinductive(&self, db: &dyn RustIrDatabase<I>) -> bool {
+ let interner = db.interner();
+ match self.data(interner) {
+ GoalData::DomainGoal(DomainGoal::Holds(wca)) => match wca {
+ WhereClause::Implemented(tr) => {
+ db.trait_datum(tr.trait_id).is_auto_trait()
+ || db.trait_datum(tr.trait_id).is_coinductive_trait()
+ }
+ WhereClause::AliasEq(..) => false,
+ WhereClause::LifetimeOutlives(..) => false,
+ WhereClause::TypeOutlives(..) => false,
+ },
+ GoalData::DomainGoal(DomainGoal::WellFormed(WellFormed::Trait(..))) => true,
+ GoalData::Quantified(QuantifierKind::ForAll, goal) => {
+ goal.skip_binders().is_coinductive(db)
+ }
+ _ => false,
+ }
+ }
+}
+
+impl<I: Interner> IsCoinductive<I> for UCanonical<InEnvironment<Goal<I>>> {
+ fn is_coinductive(&self, db: &dyn RustIrDatabase<I>) -> bool {
+ self.canonical.value.goal.is_coinductive(db)
+ }
+}
diff --git a/vendor/chalk-solve/src/display.rs b/vendor/chalk-solve/src/display.rs
new file mode 100644
index 000000000..bb1f7a3c5
--- /dev/null
+++ b/vendor/chalk-solve/src/display.rs
@@ -0,0 +1,224 @@
+use std::{
+ borrow::Borrow,
+ fmt::{Display, Result},
+ sync::Arc,
+};
+
+use crate::rust_ir::*;
+use chalk_ir::{interner::Interner, *};
+use itertools::Itertools;
+
+use crate::{logging_db::RecordedItemId, split::Split, RustIrDatabase};
+
+#[macro_use]
+mod utils;
+
+mod bounds;
+mod identifiers;
+mod items;
+mod render_trait;
+mod state;
+mod stub;
+mod ty;
+
+use self::render_trait::*;
+pub use self::state::*;
+pub use self::utils::sanitize_debug_name;
+
+use self::utils::as_display;
+
+fn write_item<F, I, T>(f: &mut F, ws: &InternalWriterState<'_, I>, v: &T) -> Result
+where
+ F: std::fmt::Write + ?Sized,
+ I: Interner,
+ T: RenderAsRust<I>,
+{
+ writeln!(f, "{}", v.display(ws))
+}
+
+/// Writes stubs for items which were referenced by name, but for which we
+/// didn't directly access. For instance, traits mentioned in where bounds which
+/// are only usually checked during well-formedness, when we weren't recording
+/// well-formedness.
+///
+/// The "stub" nature of this means it writes output with the right names and
+/// the right number of generics, but nothing else. Where clauses, bounds, and
+/// fields are skipped. Associated types are ???? skipped.
+///
+/// `RecordedItemId::Impl` is not supported.
+pub fn write_stub_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result
+where
+ F: std::fmt::Write + ?Sized,
+ I: Interner,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ T: IntoIterator<Item = RecordedItemId<I>>,
+{
+ let wrapped_db = &ws.wrap_db_ref(|db| stub::StubWrapper::new(db.borrow()));
+
+ write_items(f, wrapped_db, ids)
+}
+
+/// Writes out each item recorded by a [`LoggingRustIrDatabase`].
+///
+/// [`LoggingRustIrDatabase`]: crate::logging_db::LoggingRustIrDatabase
+pub fn write_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result
+where
+ F: std::fmt::Write + ?Sized,
+ I: Interner,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ T: IntoIterator<Item = RecordedItemId<I>>,
+{
+ for id in ids {
+ match id {
+ RecordedItemId::Impl(id) => {
+ let v = ws.db().impl_datum(id);
+ write_item(f, &InternalWriterState::new(ws), &*v)?;
+ }
+ RecordedItemId::Adt(id) => {
+ let v = ws.db().adt_datum(id);
+ write_item(f, &InternalWriterState::new(ws), &*v)?;
+ }
+ RecordedItemId::Trait(id) => {
+ let v = ws.db().trait_datum(id);
+ write_item(f, &InternalWriterState::new(ws), &*v)?;
+ }
+ RecordedItemId::OpaqueTy(id) => {
+ let v = ws.db().opaque_ty_data(id);
+ write_item(f, &InternalWriterState::new(ws), &*v)?;
+ }
+ RecordedItemId::FnDef(id) => {
+ let v = ws.db().fn_def_datum(id);
+ write_item(f, &InternalWriterState::new(ws), &*v)?;
+ }
+ RecordedItemId::Generator(id) => {
+ let generator = ws.db().generator_datum(id);
+ let witness = ws.db().generator_witness_datum(id);
+ write_item(f, &InternalWriterState::new(ws), &(&*generator, &*witness))?;
+ }
+ }
+ }
+ Ok(())
+}
+
+/// Displays a set of bounds, all targeting `Self`, as just the trait names,
+/// separated by `+`.
+///
+/// For example, a list of quantified where clauses which would normally be
+/// displayed as:
+///
+/// ```notrust
+/// Self: A, Self: B, Self: C
+/// ```
+///
+/// Is instead displayed by this function as:
+///
+/// ```notrust
+/// A + B + C
+/// ```
+///
+/// Shared between the `Trait` in `dyn Trait` and [`OpaqueTyDatum`] bounds.
+fn display_self_where_clauses_as_bounds<'a, I: Interner>(
+ s: &'a InternalWriterState<'a, I>,
+ bounds: &'a [QuantifiedWhereClause<I>],
+) -> impl Display + 'a {
+ as_display(move |f| {
+ let interner = s.db().interner();
+ write!(
+ f,
+ "{}",
+ bounds
+ .iter()
+ .map(|bound| {
+ as_display(|f| {
+ // each individual trait can have a forall
+ let s = &s.add_debrujin_index(None);
+ if !bound.binders.is_empty(interner) {
+ write!(
+ f,
+ "forall<{}> ",
+ s.binder_var_display(&bound.binders)
+ .collect::<Vec<_>>()
+ .join(", ")
+ )?;
+ }
+ match &bound.skip_binders() {
+ WhereClause::Implemented(trait_ref) => display_type_with_generics(
+ s,
+ trait_ref.trait_id,
+ &trait_ref.substitution.as_slice(interner)[1..],
+ )
+ .fmt(f),
+ WhereClause::AliasEq(alias_eq) => match &alias_eq.alias {
+ AliasTy::Projection(projection_ty) => {
+ let (assoc_ty_datum, trait_params, assoc_type_params) =
+ s.db().split_projection(projection_ty);
+ display_trait_with_assoc_ty_value(
+ s,
+ assoc_ty_datum,
+ &trait_params[1..],
+ assoc_type_params,
+ &alias_eq.ty,
+ )
+ .fmt(f)
+ }
+ AliasTy::Opaque(opaque) => opaque.display(s).fmt(f),
+ },
+ WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f),
+ WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f),
+ }
+ })
+ .to_string()
+ })
+ .format(" + ")
+ )
+ })
+}
+
+/// Displays a type with its parameters - something like `AsRef<T>`,
+/// OpaqueTyName<U>, or `AdtName<Value>`.
+///
+/// This is shared between where bounds, OpaqueTy, & dyn Trait.
+fn display_type_with_generics<'a, I: Interner>(
+ s: &'a InternalWriterState<'a, I>,
+ trait_name: impl RenderAsRust<I> + 'a,
+ trait_params: impl IntoIterator<Item = &'a GenericArg<I>> + 'a,
+) -> impl Display + 'a {
+ use std::fmt::Write;
+ let trait_params = trait_params.into_iter().map(|param| param.display(s));
+ let mut trait_params_str = String::new();
+ write_joined_non_empty_list!(trait_params_str, "<{}>", trait_params, ", ").unwrap();
+ as_display(move |f| write!(f, "{}{}", trait_name.display(s), trait_params_str))
+}
+
+/// Displays a trait with its parameters and a single associated type -
+/// something like `IntoIterator<Item=T>`.
+///
+/// This is shared between where bounds & dyn Trait.
+fn display_trait_with_assoc_ty_value<'a, I: Interner>(
+ s: &'a InternalWriterState<'a, I>,
+ assoc_ty_datum: Arc<AssociatedTyDatum<I>>,
+ trait_params: &'a [GenericArg<I>],
+ assoc_ty_params: &'a [GenericArg<I>],
+ assoc_ty_value: &'a Ty<I>,
+) -> impl Display + 'a {
+ as_display(move |f| {
+ write!(f, "{}<", assoc_ty_datum.trait_id.display(s))?;
+ write_joined_non_empty_list!(
+ f,
+ "{}, ",
+ trait_params.iter().map(|param| param.display(s)),
+ ", "
+ )?;
+ write!(f, "{}", assoc_ty_datum.id.display(s))?;
+ write_joined_non_empty_list!(
+ f,
+ "<{}>",
+ assoc_ty_params.iter().map(|param| param.display(s)),
+ ", "
+ )?;
+ write!(f, "={}>", assoc_ty_value.display(s))?;
+ Ok(())
+ })
+}
diff --git a/vendor/chalk-solve/src/display/bounds.rs b/vendor/chalk-solve/src/display/bounds.rs
new file mode 100644
index 000000000..3c6bfde14
--- /dev/null
+++ b/vendor/chalk-solve/src/display/bounds.rs
@@ -0,0 +1,168 @@
+//! Writer logic for `where` clauses and other bounds.
+//!
+//! Contains logic for writing the various forms of `Foo: Bar`.
+use std::fmt::{Display, Formatter, Result};
+
+use crate::rust_ir::*;
+use chalk_ir::{interner::Interner, *};
+use itertools::Itertools;
+
+use super::{
+ display_trait_with_assoc_ty_value, display_type_with_generics, render_trait::RenderAsRust,
+ state::InternalWriterState,
+};
+use crate::split::Split;
+
+impl<I: Interner> RenderAsRust<I> for InlineBound<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ match self {
+ // Foo: Vec<T>
+ InlineBound::TraitBound(trait_bound) => trait_bound.fmt(s, f),
+ // Foo: Iterator<Item=Foo>
+ InlineBound::AliasEqBound(eq_bound) => eq_bound.fmt(s, f),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for TraitBound<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ display_type_with_generics(s, self.trait_id, &self.args_no_self).fmt(f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AliasEqBound<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ display_trait_with_assoc_ty_value(
+ s,
+ s.db().associated_ty_data(self.associated_ty_id),
+ &self.trait_bound.args_no_self,
+ &self.parameters,
+ &self.value,
+ )
+ .fmt(f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for QuantifiedWhereClause<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ let s = &s.add_debrujin_index(None);
+ if !self.binders.is_empty(interner) {
+ write!(
+ f,
+ "forall<{}> ",
+ s.binder_var_display(&self.binders).format(", ")
+ )?;
+ }
+ self.skip_binders().fmt(s, f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for QuantifiedInlineBound<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ let s = &s.add_debrujin_index(None);
+ if !self.binders.is_empty(interner) {
+ write!(
+ f,
+ "forall<{}> ",
+ s.binder_var_display(&self.binders).format(", ")
+ )?;
+ }
+ self.skip_binders().fmt(s, f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Vec<QuantifiedWhereClause<I>> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ write!(
+ f,
+ "{}",
+ self.iter()
+ .map(|where_clause| { format!("{}{}", s.indent(), where_clause.display(s)) })
+ .format(",\n")
+ )?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for WhereClause<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ match self {
+ WhereClause::Implemented(trait_ref) => trait_ref.fmt(s, f),
+ WhereClause::AliasEq(alias_eq) => alias_eq.fmt(s, f),
+ WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f),
+ WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f),
+ }
+ }
+}
+
+/// This renders `TraitRef` as a clause in a where clause, as opposed to its
+/// usage in other places.
+impl<I: Interner> RenderAsRust<I> for TraitRef<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ write!(
+ f,
+ "{}: {}",
+ self.self_type_parameter(interner).display(s),
+ display_type_with_generics(
+ s,
+ self.trait_id,
+ &self.substitution.as_slice(interner)[1..]
+ )
+ )
+ }
+}
+
+/// This renders `AliasEq` as a clause in a where clause, as opposed to its
+/// usage in other places.
+impl<I: Interner> RenderAsRust<I> for AliasEq<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // we have: X: Y<A1, A2, A3, Z<B1, B2, B3>=D>
+ // B1, B2, B3, X, A1, A2, A3 are put into alias_eq.alias.substitution
+ // D is alias_eq.ty
+ // Z is alias_eq.alias.associated_ty_id
+ // Y is also packed into alias_eq.alias.associated_ty_id
+ // Now, we split out A*, Y/Z and B*:
+ // trait_params is X, A1, A2, A3,
+ // assoc_type_params is B1, B2, B3,
+ // assoc_ty_datum stores info about Y and Z.
+ match &self.alias {
+ AliasTy::Projection(projection_ty) => {
+ let (assoc_ty_datum, trait_params, assoc_type_params) =
+ s.db().split_projection(projection_ty);
+ // An alternate form might be `<{} as {}<{}>>::{}<{}> = {}` (with same
+ // parameter ordering). This alternate form would require type equality
+ // constraints (https://github.com/rust-lang/rust/issues/20041).
+ write!(
+ f,
+ "{}: {}",
+ trait_params[0].display(s),
+ display_trait_with_assoc_ty_value(
+ s,
+ assoc_ty_datum,
+ &trait_params[1..],
+ assoc_type_params,
+ &self.ty
+ ),
+ )
+ }
+ AliasTy::Opaque(opaque) => write!(f, "{}", opaque.display(s)),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for LifetimeOutlives<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ // a': 'b
+ write!(f, "{}: {}", self.a.display(s), self.b.display(s))
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for TypeOutlives<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ // T: 'a
+ write!(f, "{}: {}", self.ty.display(s), self.lifetime.display(s))
+ }
+}
diff --git a/vendor/chalk-solve/src/display/identifiers.rs b/vendor/chalk-solve/src/display/identifiers.rs
new file mode 100644
index 000000000..81a08d71b
--- /dev/null
+++ b/vendor/chalk-solve/src/display/identifiers.rs
@@ -0,0 +1,54 @@
+//! Writer logic for simple IDs
+//!
+//! `RenderAsRust` impls for identifiers which are either too small or too
+//! shared to belong anywhere else belong here.
+use std::fmt::{Formatter, Result};
+
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+
+use super::{render_trait::RenderAsRust, state::InternalWriterState};
+
+impl<I: Interner> RenderAsRust<I> for AdtId<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // TODO: use debug methods?
+ write!(
+ f,
+ "{}",
+ s.alias_for_adt_id_name(self.0, s.db().adt_name(*self))
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for TraitId<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // TODO: use debug methods?
+ write!(
+ f,
+ "{}",
+ s.alias_for_id_name(self.0, s.db().trait_name(*self))
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AssocTypeId<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // TODO: use debug methods?
+ write!(
+ f,
+ "{}",
+ s.alias_for_id_name(self.0, s.db().assoc_type_name(*self))
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for OpaqueTyId<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // TODO: use debug methods?
+ write!(
+ f,
+ "{}",
+ s.alias_for_id_name(self.0, s.db().opaque_type_name(*self))
+ )
+ }
+}
diff --git a/vendor/chalk-solve/src/display/items.rs b/vendor/chalk-solve/src/display/items.rs
new file mode 100644
index 000000000..00387a07b
--- /dev/null
+++ b/vendor/chalk-solve/src/display/items.rs
@@ -0,0 +1,503 @@
+//! Writer logic for top level items.
+//!
+//! Contains code specific to top-level items and other structures specific to a
+//! single top-level item.
+
+use std::fmt::{Formatter, Result};
+
+use crate::rust_ir::*;
+use crate::split::Split;
+use chalk_ir::interner::Interner;
+use itertools::Itertools;
+
+use super::{
+ display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust,
+ state::InternalWriterState,
+};
+
+/// Used in `AdtDatum` and `TraitDatum` to write n flags from a flags struct
+/// to a writer. Each flag field turns into an if expression + write!, so we can
+/// just list the names and not repeat this pattern over and over.
+///
+/// This macro will error if unknown flags are specified. This will also error
+/// if any flags are missing.
+///
+/// # Usage
+///
+/// ```rust,ignore
+/// write_flags!(f, self.flags, XFlags { red, green })
+/// ```
+///
+/// Turns into
+///
+/// ```rust,ignore
+/// match self.flags {
+/// XFlags { red, green } => {
+/// if red {
+/// write!(f, "#[red]")?;
+/// }
+/// if green {
+/// write!(f, "#[green]")?;
+/// }
+/// }
+/// }
+/// ```
+macro_rules! write_flags {
+ ($writer:ident, $val:expr, $struct_name:ident { $($n:ident $(: $extra_arg:tt)?),* }) => {
+ match $val {
+ // if any fields are missing, the destructuring will error
+ $struct_name {
+ $($n,)*
+ } => {
+ $(if $n {
+ write!($writer, "#[{}]\n", write_flags!(@default $n $(: $extra_arg)*))?;
+ })*
+ }
+ }
+ };
+ (@default $n:ident : $name:literal) => {
+ $name
+ };
+ (@default $n:ident ) => {
+ stringify!($n)
+ };
+}
+
+impl<'a, I: Interner> RenderAsRust<I> for (&'a GeneratorDatum<I>, &'a GeneratorWitnessDatum<I>) {
+ fn fmt(&self, _s: &InternalWriterState<'_, I>, _f: &'_ mut Formatter<'_>) -> Result {
+ unimplemented!()
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AdtDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // When support for Self in structs is added, self_binding should be
+ // changed to Some(0)
+ let s = &s.add_debrujin_index(None);
+ let value = self.binders.skip_binders();
+
+ // flags
+ write_flags!(
+ f,
+ self.flags,
+ AdtFlags {
+ // Ordering matters
+ upstream,
+ fundamental,
+ phantom_data
+ }
+ );
+
+ // repr
+ let repr = s.db().adt_repr(self.id);
+
+ if repr.c {
+ write!(f, "#[repr(C)]")?;
+ }
+ if repr.packed {
+ write!(f, "#[repr(packed)]")?;
+ }
+ if let Some(t) = &repr.int {
+ write!(f, "#[repr({})]", t.display(s))?;
+ }
+
+ // name
+ match self.kind {
+ AdtKind::Struct => write!(f, "struct {}", self.id.display(s),)?,
+ AdtKind::Enum => write!(f, "enum {}", self.id.display(s),)?,
+ AdtKind::Union => write!(f, "union {}", self.id.display(s),)?,
+ }
+ write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.binders.binders), ", ")?;
+
+ // where clauses
+ if !value.where_clauses.is_empty() {
+ let s = &s.add_indent();
+ write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?;
+ } else {
+ write!(f, " ")?;
+ }
+
+ // body
+ write!(f, "{{")?;
+ let s = &s.add_indent();
+ match self.kind {
+ AdtKind::Struct | AdtKind::Union => {
+ write_joined_non_empty_list!(
+ f,
+ "\n{}\n",
+ value.variants[0]
+ .fields
+ .iter()
+ .enumerate()
+ .map(|(idx, field)| {
+ format!("{}field_{}: {}", s.indent(), idx, field.display(s))
+ }),
+ ",\n"
+ )?;
+ }
+ AdtKind::Enum => {
+ for (variant_idx, variant) in value.variants.iter().enumerate() {
+ write!(f, "\n{}variant_{} {{", s.indent(), variant_idx)?;
+ let s = &s.add_indent();
+ write_joined_non_empty_list!(
+ f,
+ "\n{}\n",
+ variant.fields.iter().enumerate().map(|(idx, field)| {
+ format!("{}field_{}: {}", s.indent(), idx, field.display(s))
+ }),
+ ",\n"
+ )?;
+ write!(f, "{}}},", s.indent())?;
+ }
+ }
+ }
+ write!(f, "}}")?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Polarity {
+ fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ if !self.is_positive() {
+ write!(f, "!")?;
+ }
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for TraitDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let s = &s.add_debrujin_index(Some(0));
+ let value = self.binders.skip_binders();
+
+ // flags
+ write_flags!(
+ f,
+ self.flags,
+ TraitFlags {
+ auto,
+ marker,
+ upstream,
+ fundamental,
+ non_enumerable,
+ coinductive
+ }
+ );
+
+ // object safe
+ if s.db().is_object_safe(self.id) {
+ writeln!(f, "#[object_safe]")?;
+ }
+
+ // well-known
+ if let Some(well_known) = self.well_known {
+ let name = match well_known {
+ WellKnownTrait::Sized => "sized",
+ WellKnownTrait::Copy => "copy",
+ WellKnownTrait::Clone => "clone",
+ WellKnownTrait::Drop => "drop",
+ WellKnownTrait::FnOnce => "fn_once",
+ WellKnownTrait::FnMut => "fn_mut",
+ WellKnownTrait::Fn => "fn",
+ WellKnownTrait::Unsize => "unsize",
+ WellKnownTrait::Unpin => "unpin",
+ WellKnownTrait::CoerceUnsized => "coerce_unsized",
+ WellKnownTrait::DiscriminantKind => "discriminant_kind",
+ WellKnownTrait::Generator => "generator",
+ WellKnownTrait::DispatchFromDyn => "dispatch_from_dyn",
+ WellKnownTrait::Tuple => "tuple_trait",
+ };
+ writeln!(f, "#[lang({})]", name)?;
+ }
+
+ // trait declaration
+ let binders = s.binder_var_display(&self.binders.binders).skip(1);
+ write!(f, "trait {}", self.id.display(s))?;
+ write_joined_non_empty_list!(f, "<{}>", binders, ", ")?;
+
+ // where clauses
+ if !value.where_clauses.is_empty() {
+ let s = &s.add_indent();
+ write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?;
+ } else {
+ write!(f, " ")?;
+ }
+
+ // body
+ write!(f, "{{")?;
+ let s = &s.add_indent();
+ write_joined_non_empty_list!(
+ f,
+ "\n{}\n",
+ self.associated_ty_ids.iter().map(|assoc_ty_id| {
+ let assoc_ty_data = s.db().associated_ty_data(*assoc_ty_id);
+ format!("{}{}", s.indent(), (*assoc_ty_data).display(s))
+ }),
+ "\n"
+ )?;
+ write!(f, "}}")?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for ImplDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+
+ let s = &s.add_debrujin_index(None);
+ let binders = s.binder_var_display(&self.binders.binders);
+ let value = self.binders.skip_binders();
+
+ // annotations
+ // #[upstream]
+ // ^^^^^^^^^^^
+ // impl<T> Foo<T> for Bar<T> where T: Baz { }
+ if self.impl_type == ImplType::External {
+ writeln!(f, "#[upstream]")?;
+ }
+
+ // impl keyword
+ // impl<T> Foo<T> for Bar<T> where T: Baz { }
+ // ^^^^
+ write!(f, "impl")?;
+ let trait_ref = &value.trait_ref;
+
+ // generic binders
+ // impl<T> Foo<T> for Bar<T> where T: Baz
+ // ^^^
+ write_joined_non_empty_list!(f, "<{}>", binders, ", ")?;
+
+ // trait, type and parameters
+ // impl<T> Foo<T> for Bar<T> where T: Baz { }
+ // ^^^^^^^^^^^^^^^^^
+ let full_trait_name = display_type_with_generics(
+ s,
+ trait_ref.trait_id,
+ // Ignore automatically added Self parameter by skipping first parameter
+ &trait_ref.substitution.as_slice(interner)[1..],
+ );
+ write!(
+ f,
+ " {}{} for {}",
+ self.polarity.display(s),
+ full_trait_name,
+ trait_ref.self_type_parameter(interner).display(s)
+ )?;
+
+ // where clauses
+ // impl<T> Foo<T> for Bar<T> where T: Baz { }
+ // ^^^^^^^^^^^^
+ if !value.where_clauses.is_empty() {
+ let s = &s.add_indent();
+ write!(f, "\nwhere\n{}\n", value.where_clauses.display(s))?;
+ } else {
+ write!(f, " ")?;
+ }
+
+ // body
+ // impl<T> Foo<T> for Bar<T> where T: Baz { }
+ // ^^^
+ write!(f, "{{")?;
+ {
+ let s = &s.add_indent();
+ let assoc_ty_values = self.associated_ty_value_ids.iter().map(|assoc_ty_value| {
+ s.db()
+ .associated_ty_value(*assoc_ty_value)
+ .display(s)
+ .to_string()
+ });
+ write_joined_non_empty_list!(f, "\n{}\n", assoc_ty_values, "\n")?;
+ }
+ write!(f, "}}")?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for OpaqueTyDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ let s = &s.add_debrujin_index(None);
+ let bounds = self.bound.skip_binders();
+ write!(f, "opaque type {}", self.opaque_ty_id.display(s))?;
+ write_joined_non_empty_list!(f, "<{}>", s.binder_var_display(&self.bound.binders), ", ")?;
+ {
+ let s = &s.add_debrujin_index(Some(0));
+ let clauses = bounds.bounds.skip_binders();
+ write!(
+ f,
+ ": {} = ",
+ display_self_where_clauses_as_bounds(s, clauses)
+ )?;
+ }
+ write!(
+ f,
+ "{};",
+ s.db().hidden_opaque_type(self.opaque_ty_id).display(s)
+ )?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AssociatedTyDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // In lowering, a completely new empty environment is created for each
+ // AssociatedTyDatum, and it's given generic parameters for each generic
+ // parameter that its trait had. We want to map the new binders for
+ // those generic parameters back into their original names. To do that,
+ // first find their original names (trait_binder_names), then the names
+ // they have inside the AssociatedTyDatum (assoc_ty_names_for_trait_params),
+ // and then add that mapping to the WriterState when writing bounds and
+ // where clauses.
+ let trait_datum = s.db().trait_datum(self.trait_id);
+ // inverted Debrujin indices for the trait's parameters in the trait
+ // environment
+ let trait_param_names_in_trait_env = s.binder_var_indices(&trait_datum.binders.binders);
+ let s = &s.add_debrujin_index(None);
+ // inverted Debrujin indices for the trait's parameters in the
+ // associated type environment
+ let param_names_in_assoc_ty_env = s
+ .binder_var_indices(&self.binders.binders)
+ .collect::<Vec<_>>();
+ // inverted Debrujin indices to render the trait's parameters in the
+ // associated type environment
+ let (trait_param_names_in_assoc_ty_env, _) = s
+ .db()
+ .split_associated_ty_parameters(&param_names_in_assoc_ty_env, self);
+
+ let s = &s.add_parameter_mapping(
+ trait_param_names_in_assoc_ty_env.iter().copied(),
+ trait_param_names_in_trait_env,
+ );
+
+ // rendered names for the associated type's generics in the associated
+ // type environment
+ let binder_display_in_assoc_ty = s
+ .binder_var_display(&self.binders.binders)
+ .collect::<Vec<_>>();
+
+ let (_, assoc_ty_params) = s
+ .db()
+ .split_associated_ty_parameters(&binder_display_in_assoc_ty, self);
+ write!(f, "type {}", self.id.display(s))?;
+ write_joined_non_empty_list!(f, "<{}>", assoc_ty_params, ", ")?;
+
+ let datum_bounds = &self.binders.skip_binders();
+
+ if !datum_bounds.bounds.is_empty() {
+ write!(f, ": ")?;
+ }
+
+ // bounds is `A: V, B: D, C = E`?
+ // type Foo<A: V, B:D, C = E>: X + Y + Z;
+ let bounds = datum_bounds
+ .bounds
+ .iter()
+ .map(|bound| bound.display(s).to_string())
+ .format(" + ");
+ write!(f, "{}", bounds)?;
+
+ // where_clause is 'X: Y, Z: D'
+ // type Foo<...>: ... where X: Y, Z: D;
+
+ // note: it's a quantified clause b/c we could have `for<'a> T: Foo<'a>`
+ // within 'where'
+ if !datum_bounds.where_clauses.is_empty() {
+ let where_s = &s.add_indent();
+ let where_clauses = datum_bounds.where_clauses.display(where_s);
+ write!(f, "\n{}where\n{}", s.indent(), where_clauses)?;
+ }
+ write!(f, ";")?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AssociatedTyValue<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // see comments for a similar empty env operation in AssociatedTyDatum's
+ // impl of RenderAsRust.
+ let assoc_ty_data = s.db().associated_ty_data(self.associated_ty_id);
+ let impl_datum = s.db().impl_datum(self.impl_id);
+
+ let impl_param_names_in_impl_env = s.binder_var_indices(&impl_datum.binders.binders);
+
+ let s = &s.add_debrujin_index(None);
+ let value = self.value.skip_binders();
+
+ let param_names_in_assoc_ty_value_env = s
+ .binder_var_indices(&self.value.binders)
+ .collect::<Vec<_>>();
+
+ let (impl_params_in_assoc_ty_value_env, _assoc_ty_value_params) = s
+ .db()
+ .split_associated_ty_value_parameters(&param_names_in_assoc_ty_value_env, self);
+
+ let s = &s.add_parameter_mapping(
+ impl_params_in_assoc_ty_value_env.iter().cloned(),
+ impl_param_names_in_impl_env,
+ );
+
+ let display_params = s
+ .binder_var_display(&self.value.binders)
+ .collect::<Vec<_>>();
+
+ let (_impl_display, assoc_ty_value_display) = s
+ .db()
+ .split_associated_ty_value_parameters(&display_params, self);
+
+ write!(f, "{}type {}", s.indent(), assoc_ty_data.id.display(s))?;
+ write_joined_non_empty_list!(f, "<{}>", assoc_ty_value_display, ", ")?;
+ write!(f, " = {};", value.ty.display(s))?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for FnDefDatum<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ let s = &s.add_debrujin_index(None);
+ let bound_datum = self.binders.skip_binders();
+
+ // declaration
+ // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
+ // ^^^^^^
+ write!(f, "fn {}", s.db().fn_def_name(self.id))?;
+
+ // binders
+ // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
+ // ^^^
+ let binders = s.binder_var_display(&self.binders.binders);
+ write_joined_non_empty_list!(f, "<{}>", binders, ", ")?;
+
+ {
+ let s = &s.add_debrujin_index(None);
+ let inputs_and_output = bound_datum.inputs_and_output.skip_binders();
+
+ // arguments
+ // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
+ // ^^^^^^^^^^^^^^^^^^^
+ let arguments = inputs_and_output
+ .argument_types
+ .iter()
+ .enumerate()
+ .map(|(idx, arg)| format!("arg_{}: {}", idx, arg.display(s)))
+ .format(", ");
+
+ write!(f, "({})", arguments)?;
+
+ // return Type
+ // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
+ // ^^^^^^^^^^^^^
+ write!(f, " -> {}", inputs_and_output.return_type.display(s))?;
+ }
+
+ // where clause
+ // fn foo<T>(arg: u32, arg2: T) -> Result<T> where T: Bar
+ // ^^^^^^^^^^^^
+ if !bound_datum.where_clauses.is_empty() {
+ let s = &s.add_indent();
+ write!(f, "\nwhere\n{}", bound_datum.where_clauses.display(s))?;
+ }
+
+ write!(f, ";")?;
+
+ Ok(())
+ }
+}
diff --git a/vendor/chalk-solve/src/display/render_trait.rs b/vendor/chalk-solve/src/display/render_trait.rs
new file mode 100644
index 000000000..a565f076c
--- /dev/null
+++ b/vendor/chalk-solve/src/display/render_trait.rs
@@ -0,0 +1,30 @@
+//! `RenderAsRust` trait and related utils.
+use std::fmt::{Display, Formatter, Result};
+
+use chalk_ir::interner::Interner;
+
+use super::state::InternalWriterState;
+
+/// Displays `RenderAsRust` data.
+///
+/// This is a utility struct for making `RenderAsRust` nice to use with rust format macros.
+pub(in crate::display) struct DisplayRenderAsRust<'a, I: Interner, T> {
+ s: &'a InternalWriterState<'a, I>,
+ rar: &'a T,
+}
+
+impl<I: Interner, T: RenderAsRust<I>> Display for DisplayRenderAsRust<'_, I, T> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ self.rar.fmt(self.s, f)
+ }
+}
+
+pub(in crate::display) trait RenderAsRust<I: Interner> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result;
+ fn display<'a>(&'a self, s: &'a InternalWriterState<'a, I>) -> DisplayRenderAsRust<'a, I, Self>
+ where
+ Self: Sized,
+ {
+ DisplayRenderAsRust { s, rar: self }
+ }
+}
diff --git a/vendor/chalk-solve/src/display/state.rs b/vendor/chalk-solve/src/display/state.rs
new file mode 100644
index 000000000..fed2f5ca5
--- /dev/null
+++ b/vendor/chalk-solve/src/display/state.rs
@@ -0,0 +1,352 @@
+//! Persistent state passed down between writers.
+//!
+//! This is essentially `InternalWriterState` and other things supporting that.
+use core::hash::Hash;
+use std::{
+ borrow::Borrow,
+ collections::BTreeMap,
+ fmt::{Debug, Display, Formatter, Result},
+ marker::PhantomData,
+ rc::Rc,
+ sync::{Arc, Mutex},
+};
+
+use crate::RustIrDatabase;
+use chalk_ir::{interner::Interner, *};
+use indexmap::IndexMap;
+use itertools::Itertools;
+
+/// Like a BoundVar, but with the debrujin index inverted so as to create a
+/// canonical name we can use anywhere for each bound variable.
+///
+/// In BoundVar, the innermost bound variables have debrujin index `0`, and
+/// each further out BoundVar has a debrujin index `1` higher.
+///
+/// In InvertedBoundVar, the outermost variables have inverted_debrujin_idx `0`,
+/// and the innermost have their depth, not the other way around.
+#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
+pub struct InvertedBoundVar {
+ /// The inverted debrujin index. Corresponds roughly to an inverted `DebrujinIndex::depth`.
+ inverted_debrujin_idx: i64,
+ /// The index within the debrujin index. Corresponds to `BoundVar::index`.
+ within_idx: IndexWithinBinding,
+}
+
+impl Display for InvertedBoundVar {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ write!(f, "_{}_{}", self.inverted_debrujin_idx, self.within_idx)
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+enum UnifiedId<I: Interner> {
+ AdtId(I::InternedAdtId),
+ DefId(I::DefId),
+}
+
+#[derive(Debug)]
+pub struct IdAliasStore<T> {
+ /// Map from the DefIds we've encountered to a u32 alias id unique to all ids
+ /// the same name.
+ aliases: IndexMap<T, u32>,
+ /// Map from each name to the next unused u32 alias id.
+ next_unused_for_name: BTreeMap<String, u32>,
+}
+
+impl<T> Default for IdAliasStore<T> {
+ fn default() -> Self {
+ IdAliasStore {
+ aliases: IndexMap::default(),
+ next_unused_for_name: BTreeMap::default(),
+ }
+ }
+}
+
+impl<T: Copy + Eq + Hash> IdAliasStore<T> {
+ fn alias_for_id_name(&mut self, id: T, name: String) -> String {
+ let next_unused_for_name = &mut self.next_unused_for_name;
+ let alias = *self.aliases.entry(id).or_insert_with(|| {
+ let next_unused: &mut u32 = next_unused_for_name.entry(name.clone()).or_default();
+ let id = *next_unused;
+ *next_unused += 1;
+ id
+ });
+ // If there are no conflicts, keep the name the same so that we don't
+ // need name-agnostic equality in display tests.
+ if alias == 0 {
+ name
+ } else {
+ format!("{}_{}", name, alias)
+ }
+ }
+}
+
+#[derive(Debug)]
+struct IdAliases<I: Interner> {
+ id_aliases: IdAliasStore<UnifiedId<I>>,
+}
+
+impl<I: Interner> Default for IdAliases<I> {
+ fn default() -> Self {
+ IdAliases {
+ id_aliases: IdAliasStore::default(),
+ }
+ }
+}
+
+/// Writer state which persists across multiple writes.
+///
+/// Currently, this means keeping track of what IDs have been given what names,
+/// including deduplication information.
+///
+/// This data is stored using interior mutability - clones will point to the same underlying
+/// data.
+///
+/// Uses a separate type, `P`, for the database stored inside to account for
+/// `Arc` or wrapping other storage mediums.
+#[derive(Debug)]
+pub struct WriterState<I, DB: ?Sized, P = DB>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ pub(super) db: P,
+ id_aliases: Arc<Mutex<IdAliases<I>>>,
+ _phantom: PhantomData<DB>,
+}
+
+impl<I, DB: ?Sized, P> Clone for WriterState<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + Clone,
+ I: Interner,
+{
+ fn clone(&self) -> Self {
+ WriterState {
+ db: self.db.clone(),
+ id_aliases: self.id_aliases.clone(),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl<I, DB: ?Sized, P> WriterState<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ pub fn new(db: P) -> Self {
+ WriterState {
+ db,
+ id_aliases: Arc::new(Mutex::new(IdAliases::default())),
+ _phantom: PhantomData,
+ }
+ }
+
+ /// Returns a new version of self containing a wrapped database which
+ /// references the outer data.
+ ///
+ /// `f` will be run on the internal database, and the returned result will
+ /// wrap the result from `f`. For consistency, `f` should always contain the
+ /// given database, and must keep the same ID<->item relationships.
+ pub(super) fn wrap_db_ref<'a, DB2: ?Sized, P2, F>(&'a self, f: F) -> WriterState<I, DB2, P2>
+ where
+ DB2: RustIrDatabase<I>,
+ P2: Borrow<DB2>,
+ // We need to pass in `&'a P` specifically to guarantee that the `&P`
+ // can outlive the function body, and thus that it's safe to store `&P`
+ // in `P2`.
+ F: FnOnce(&'a P) -> P2,
+ {
+ WriterState {
+ db: f(&self.db),
+ id_aliases: self.id_aliases.clone(),
+ _phantom: PhantomData,
+ }
+ }
+
+ pub(crate) fn db(&self) -> &DB {
+ self.db.borrow()
+ }
+}
+
+/// Writer state for a single write call, persistent only as long as necessary
+/// to write a single item.
+///
+/// Stores things necessary for .
+#[derive(Clone, Debug)]
+pub(super) struct InternalWriterState<'a, I: Interner> {
+ persistent_state: WriterState<I, dyn RustIrDatabase<I> + 'a, &'a dyn RustIrDatabase<I>>,
+ indent_level: usize,
+ debrujin_indices_deep: u32,
+ // lowered_(inverted_debrujin_idx, index) -> src_correct_(inverted_debrujin_idx, index)
+ remapping: Rc<BTreeMap<InvertedBoundVar, InvertedBoundVar>>,
+ // the inverted_bound_var which maps to "Self"
+ self_mapping: Option<InvertedBoundVar>,
+}
+
+type IndexWithinBinding = usize;
+
+impl<'a, I: Interner> InternalWriterState<'a, I> {
+ pub fn new<DB, P>(persistent_state: &'a WriterState<I, DB, P>) -> Self
+ where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ {
+ InternalWriterState {
+ persistent_state: persistent_state
+ .wrap_db_ref(|db| db.borrow() as &dyn RustIrDatabase<I>),
+ indent_level: 0,
+ debrujin_indices_deep: 0,
+ remapping: Rc::new(BTreeMap::new()),
+ self_mapping: None,
+ }
+ }
+
+ pub(super) fn db(&self) -> &dyn RustIrDatabase<I> {
+ self.persistent_state.db
+ }
+
+ pub(super) fn add_indent(&self) -> Self {
+ InternalWriterState {
+ indent_level: self.indent_level + 1,
+ ..self.clone()
+ }
+ }
+
+ pub(super) fn indent(&self) -> impl Display {
+ std::iter::repeat(" ").take(self.indent_level).format("")
+ }
+
+ pub(super) fn alias_for_adt_id_name(&self, id: I::InternedAdtId, name: String) -> impl Display {
+ self.persistent_state
+ .id_aliases
+ .lock()
+ .unwrap()
+ .id_aliases
+ .alias_for_id_name(UnifiedId::AdtId(id), name)
+ }
+
+ pub(super) fn alias_for_id_name(&self, id: I::DefId, name: String) -> impl Display {
+ self.persistent_state
+ .id_aliases
+ .lock()
+ .unwrap()
+ .id_aliases
+ .alias_for_id_name(UnifiedId::DefId(id), name)
+ }
+
+ /// Adds a level of debrujin index, and possibly a "Self" parameter.
+ ///
+ /// This should be called whenever recursing into the value within a
+ /// [`Binders`].
+ ///
+ /// If `self_binding` is `Some`, then it will introduce a new variable named
+ /// `Self` with the within-debrujin index given within and the innermost
+ /// debrujian index after increasing debrujin index.
+ #[must_use = "this returns a new `InternalWriterState`, and does not modify the existing one"]
+ pub(super) fn add_debrujin_index(&self, self_binding: Option<IndexWithinBinding>) -> Self {
+ let mut new_state = self.clone();
+ new_state.debrujin_indices_deep += 1;
+ new_state.self_mapping = self_binding
+ .map(|idx| new_state.indices_for_introduced_bound_var(idx))
+ .or(self.self_mapping);
+ new_state
+ }
+
+ /// Adds parameter remapping.
+ ///
+ /// Each of the parameters in `lowered_vars` will be mapped to its
+ /// corresponding variable in `original_vars` when printed through the
+ /// `InternalWriterState` returned from this method.
+ ///
+ /// `lowered_vars` and `original_vars` must have the same length.
+ pub(super) fn add_parameter_mapping(
+ &self,
+ lowered_vars: impl Iterator<Item = InvertedBoundVar>,
+ original_vars: impl Iterator<Item = InvertedBoundVar>,
+ ) -> Self {
+ let remapping = self
+ .remapping
+ .iter()
+ .map(|(a, b)| (*a, *b))
+ .chain(lowered_vars.zip(original_vars))
+ .collect::<BTreeMap<_, _>>();
+
+ InternalWriterState {
+ remapping: Rc::new(remapping),
+ ..self.clone()
+ }
+ }
+
+ /// Inverts the debrujin index so as to create a canonical name we can
+ /// anywhere for each bound variable.
+ ///
+ /// See [`InvertedBoundVar`][InvertedBoundVar].
+ pub(super) fn invert_debrujin_idx(
+ &self,
+ debrujin_idx: u32,
+ index: IndexWithinBinding,
+ ) -> InvertedBoundVar {
+ InvertedBoundVar {
+ inverted_debrujin_idx: (self.debrujin_indices_deep as i64) - (debrujin_idx as i64),
+ within_idx: index,
+ }
+ }
+
+ pub(super) fn apply_mappings(&self, b: InvertedBoundVar) -> impl Display {
+ let remapped = self.remapping.get(&b).copied().unwrap_or(b);
+ if self.self_mapping == Some(remapped) {
+ "Self".to_owned()
+ } else {
+ remapped.to_string()
+ }
+ }
+
+ pub(super) fn indices_for_bound_var(&self, b: &BoundVar) -> InvertedBoundVar {
+ self.invert_debrujin_idx(b.debruijn.depth(), b.index)
+ }
+
+ pub(super) fn indices_for_introduced_bound_var(
+ &self,
+ idx: IndexWithinBinding,
+ ) -> InvertedBoundVar {
+ // freshly introduced bound vars will always have debrujin index of 0,
+ // they're always "innermost".
+ self.invert_debrujin_idx(0, idx)
+ }
+
+ pub(super) fn display_bound_var(&self, b: &BoundVar) -> impl Display {
+ self.apply_mappings(self.indices_for_bound_var(b))
+ }
+
+ pub(super) fn name_for_introduced_bound_var(&self, idx: IndexWithinBinding) -> impl Display {
+ self.apply_mappings(self.indices_for_introduced_bound_var(idx))
+ }
+
+ pub(super) fn binder_var_indices<'b>(
+ &'b self,
+ binders: &'b VariableKinds<I>,
+ ) -> impl Iterator<Item = InvertedBoundVar> + 'b {
+ binders
+ .iter(self.db().interner())
+ .enumerate()
+ .map(move |(idx, _param)| self.indices_for_introduced_bound_var(idx))
+ }
+
+ pub(super) fn binder_var_display<'b>(
+ &'b self,
+ binders: &'b VariableKinds<I>,
+ ) -> impl Iterator<Item = String> + 'b {
+ binders
+ .iter(self.db().interner())
+ .zip(self.binder_var_indices(binders))
+ .map(move |(parameter, var)| match parameter {
+ VariableKind::Ty(_) => format!("{}", self.apply_mappings(var)),
+ VariableKind::Lifetime => format!("'{}", self.apply_mappings(var)),
+ VariableKind::Const(_ty) => format!("const {}", self.apply_mappings(var)),
+ })
+ }
+}
diff --git a/vendor/chalk-solve/src/display/stub.rs b/vendor/chalk-solve/src/display/stub.rs
new file mode 100644
index 000000000..ec209bc91
--- /dev/null
+++ b/vendor/chalk-solve/src/display/stub.rs
@@ -0,0 +1,268 @@
+//! Contains a `LoggingIrDatabase` which returns stub versions of everything
+//! queried.
+use std::sync::Arc;
+
+use crate::rust_ir::{GeneratorDatum, GeneratorWitnessDatum};
+use crate::{
+ rust_ir::{
+ AdtDatumBound, AdtKind, AdtVariantDatum, AssociatedTyDatumBound, FnDefDatumBound,
+ OpaqueTyDatumBound, TraitDatumBound,
+ },
+ RustIrDatabase,
+};
+use chalk_ir::{
+ interner::Interner, Binders, CanonicalVarKinds, GeneratorId, Substitution, Ty,
+ UnificationDatabase, VariableKinds, Variances,
+};
+
+#[derive(Debug)]
+pub struct StubWrapper<'a, DB> {
+ db: &'a DB,
+}
+
+impl<'a, DB> StubWrapper<'a, DB> {
+ pub fn new(db: &'a DB) -> Self {
+ StubWrapper { db }
+ }
+}
+
+impl<I: Interner, DB: RustIrDatabase<I>> UnificationDatabase<I> for StubWrapper<'_, DB> {
+ fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
+ self.db.unification_database().fn_def_variance(fn_def_id)
+ }
+
+ fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
+ self.db.unification_database().adt_variance(adt_id)
+ }
+}
+
+impl<I: Interner, DB: RustIrDatabase<I>> RustIrDatabase<I> for StubWrapper<'_, DB> {
+ fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
+ self.db.custom_clauses()
+ }
+
+ fn associated_ty_data(
+ &self,
+ ty: chalk_ir::AssocTypeId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::AssociatedTyDatum<I>> {
+ let mut v = (*self.db.associated_ty_data(ty)).clone();
+ v.binders = Binders::new(
+ v.binders.binders.clone(),
+ AssociatedTyDatumBound {
+ where_clauses: Vec::new(),
+ bounds: Vec::new(),
+ },
+ );
+ Arc::new(v)
+ }
+
+ fn trait_datum(
+ &self,
+ trait_id: chalk_ir::TraitId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::TraitDatum<I>> {
+ let mut v = (*self.db.trait_datum(trait_id)).clone();
+ v.binders = Binders::new(
+ v.binders.binders.clone(),
+ TraitDatumBound {
+ where_clauses: Vec::new(),
+ },
+ );
+ Arc::new(v)
+ }
+
+ fn adt_datum(&self, adt_id: chalk_ir::AdtId<I>) -> std::sync::Arc<crate::rust_ir::AdtDatum<I>> {
+ let mut v = (*self.db.adt_datum(adt_id)).clone();
+ let variants = match v.kind {
+ AdtKind::Struct | AdtKind::Union => vec![AdtVariantDatum { fields: vec![] }],
+ AdtKind::Enum => vec![],
+ };
+ v.binders = Binders::new(
+ v.binders.binders.clone(),
+ AdtDatumBound {
+ variants,
+ where_clauses: Vec::new(),
+ },
+ );
+ Arc::new(v)
+ }
+
+ fn adt_repr(&self, id: chalk_ir::AdtId<I>) -> std::sync::Arc<crate::rust_ir::AdtRepr<I>> {
+ self.db.adt_repr(id)
+ }
+
+ fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> {
+ self.db.adt_size_align(id)
+ }
+
+ fn fn_def_datum(
+ &self,
+ fn_def_id: chalk_ir::FnDefId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::FnDefDatum<I>> {
+ let mut v = (*self.db.fn_def_datum(fn_def_id)).clone();
+ v.binders = Binders::new(
+ v.binders.binders.clone(),
+ FnDefDatumBound {
+ inputs_and_output: v.binders.skip_binders().inputs_and_output.clone(),
+ where_clauses: Vec::new(),
+ },
+ );
+ Arc::new(v)
+ }
+
+ fn impl_datum(
+ &self,
+ _impl_id: chalk_ir::ImplId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::ImplDatum<I>> {
+ unreachable!("impl items should never be stubbed")
+ }
+
+ fn associated_ty_value(
+ &self,
+ _id: crate::rust_ir::AssociatedTyValueId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::AssociatedTyValue<I>> {
+ unreachable!("associated type values should never be stubbed")
+ }
+
+ fn opaque_ty_data(
+ &self,
+ id: chalk_ir::OpaqueTyId<I>,
+ ) -> std::sync::Arc<crate::rust_ir::OpaqueTyDatum<I>> {
+ let mut v = (*self.db.opaque_ty_data(id)).clone();
+ v.bound = Binders::new(
+ v.bound.binders,
+ OpaqueTyDatumBound {
+ bounds: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()),
+ where_clauses: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()),
+ },
+ );
+ Arc::new(v)
+ }
+
+ fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<I>) -> chalk_ir::Ty<I> {
+ // Return a unit since the particular hidden type doesn't matter (If it
+ // did matter, it would have been recorded)
+ chalk_ir::TyKind::Tuple(0, Substitution::empty(self.db.interner()))
+ .intern(self.db.interner())
+ }
+
+ fn impls_for_trait(
+ &self,
+ _trait_id: chalk_ir::TraitId<I>,
+ _parameters: &[chalk_ir::GenericArg<I>],
+ _binders: &CanonicalVarKinds<I>,
+ ) -> Vec<chalk_ir::ImplId<I>> {
+ // We panic here because the returned ids may not be collected,
+ // resulting in unresolvable names.
+ unimplemented!("stub display code should call this")
+ }
+
+ fn local_impls_to_coherence_check(
+ &self,
+ trait_id: chalk_ir::TraitId<I>,
+ ) -> Vec<chalk_ir::ImplId<I>> {
+ self.db.local_impls_to_coherence_check(trait_id)
+ }
+
+ fn impl_provided_for(
+ &self,
+ _auto_trait_id: chalk_ir::TraitId<I>,
+ _ty: &chalk_ir::TyKind<I>,
+ ) -> bool {
+ // We panic here because the returned ids may not be collected,
+ // resulting in unresolvable names.
+ unimplemented!("stub display code should call this")
+ }
+
+ fn well_known_trait_id(
+ &self,
+ well_known_trait: crate::rust_ir::WellKnownTrait,
+ ) -> Option<chalk_ir::TraitId<I>> {
+ self.db.well_known_trait_id(well_known_trait)
+ }
+
+ fn program_clauses_for_env(
+ &self,
+ environment: &chalk_ir::Environment<I>,
+ ) -> chalk_ir::ProgramClauses<I> {
+ self.db.program_clauses_for_env(environment)
+ }
+
+ fn interner(&self) -> I {
+ self.db.interner()
+ }
+
+ fn is_object_safe(&self, trait_id: chalk_ir::TraitId<I>) -> bool {
+ self.db.is_object_safe(trait_id)
+ }
+
+ fn closure_kind(
+ &self,
+ _closure_id: chalk_ir::ClosureId<I>,
+ _substs: &chalk_ir::Substitution<I>,
+ ) -> crate::rust_ir::ClosureKind {
+ unimplemented!("cannot stub closures")
+ }
+
+ fn closure_inputs_and_output(
+ &self,
+ _closure_id: chalk_ir::ClosureId<I>,
+ _substs: &chalk_ir::Substitution<I>,
+ ) -> chalk_ir::Binders<crate::rust_ir::FnDefInputsAndOutputDatum<I>> {
+ unimplemented!("cannot stub closures")
+ }
+
+ fn closure_upvars(
+ &self,
+ _closure_id: chalk_ir::ClosureId<I>,
+ _substs: &chalk_ir::Substitution<I>,
+ ) -> chalk_ir::Binders<chalk_ir::Ty<I>> {
+ unimplemented!("cannot stub closures")
+ }
+
+ fn generator_datum(&self, _generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
+ unimplemented!("cannot stub generator")
+ }
+
+ fn generator_witness_datum(
+ &self,
+ _generator_id: GeneratorId<I>,
+ ) -> Arc<GeneratorWitnessDatum<I>> {
+ unimplemented!("cannot stub generator witness")
+ }
+
+ fn closure_fn_substitution(
+ &self,
+ _closure_id: chalk_ir::ClosureId<I>,
+ _substs: &chalk_ir::Substitution<I>,
+ ) -> chalk_ir::Substitution<I> {
+ unimplemented!("cannot stub closures")
+ }
+
+ fn unification_database(&self) -> &dyn UnificationDatabase<I> {
+ self
+ }
+
+ fn trait_name(&self, trait_id: chalk_ir::TraitId<I>) -> String {
+ self.db.trait_name(trait_id)
+ }
+
+ fn adt_name(&self, struct_id: chalk_ir::AdtId<I>) -> String {
+ self.db.adt_name(struct_id)
+ }
+
+ fn assoc_type_name(&self, assoc_ty_id: chalk_ir::AssocTypeId<I>) -> String {
+ self.db.assoc_type_name(assoc_ty_id)
+ }
+
+ fn opaque_type_name(&self, opaque_ty_id: chalk_ir::OpaqueTyId<I>) -> String {
+ self.db.opaque_type_name(opaque_ty_id)
+ }
+
+ fn fn_def_name(&self, fn_def_id: chalk_ir::FnDefId<I>) -> String {
+ self.db.fn_def_name(fn_def_id)
+ }
+
+ fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
+ self.db.discriminant_type(ty)
+ }
+}
diff --git a/vendor/chalk-solve/src/display/ty.rs b/vendor/chalk-solve/src/display/ty.rs
new file mode 100644
index 000000000..b0186652e
--- /dev/null
+++ b/vendor/chalk-solve/src/display/ty.rs
@@ -0,0 +1,303 @@
+//! Writer logic for types.
+//!
+//! Contains the highly-recursive logic for writing `TyKind` and its variants.
+use std::fmt::{Formatter, Result};
+
+use crate::split::Split;
+use chalk_ir::{interner::Interner, *};
+use itertools::Itertools;
+
+use super::{
+ display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust,
+ state::InternalWriterState,
+};
+
+impl<I: Interner> RenderAsRust<I> for TyKind<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ match self {
+ TyKind::Adt(sid, substitution) => {
+ write!(f, "{}", sid.display(s))?;
+ let parameters = substitution.as_slice(interner);
+ let parameters = parameters.iter().map(|param| param.display(s));
+ write_joined_non_empty_list!(f, "<{}>", parameters, ", ")
+ }
+ TyKind::AssociatedType(assoc_type_id, substitution) => {
+ // (Iterator::Item)(x)
+ // should be written in Rust as <X as Iterator>::Item
+ let datum = s.db().associated_ty_data(*assoc_type_id);
+ assert!(
+ substitution
+ .iter(interner)
+ .filter_map(move |p| p.ty(interner))
+ .count()
+ >= 1,
+ "AssociatedType should have at least 1 parameter"
+ );
+ write!(
+ f,
+ "<{} as {}>::{}",
+ substitution
+ .iter(interner)
+ .filter_map(move |p| p.ty(interner))
+ .next()
+ .unwrap()
+ .display(s),
+ datum.trait_id.display(s),
+ datum.id.display(s),
+ )?;
+ let params = substitution.as_slice(interner);
+ write_joined_non_empty_list!(
+ f,
+ "<{}>",
+ params[1..].iter().map(|ty| ty.display(s)),
+ ","
+ )
+ }
+ TyKind::Scalar(scalar) => write!(f, "{}", scalar.display(s)),
+ TyKind::Tuple(arity, substitution) => {
+ write!(
+ f,
+ "({}{})",
+ substitution
+ .as_slice(interner)
+ .iter()
+ .map(|p| p.display(s))
+ .format(", "),
+ if *arity == 1 {
+ // need trailing single comma
+ ","
+ } else {
+ ""
+ }
+ )
+ }
+ TyKind::OpaqueType(opaque_ty_id, substitution) => write!(
+ f,
+ "{}",
+ display_type_with_generics(s, *opaque_ty_id, substitution.as_slice(interner))
+ ),
+ TyKind::Raw(mutability, ty) => match mutability {
+ Mutability::Mut => write!(f, "*mut {}", ty.display(s)),
+ Mutability::Not => write!(f, "*const {}", ty.display(s)),
+ },
+ TyKind::Ref(mutability, lifetime, ty) => match mutability {
+ Mutability::Mut => write!(f, "&{} mut {}", lifetime.display(s), ty.display(s)),
+ Mutability::Not => write!(f, "&{} {}", lifetime.display(s), ty.display(s)),
+ },
+ TyKind::Str => write!(f, "str"),
+ TyKind::Slice(ty) => write!(f, "[{}]", ty.display(s)),
+ TyKind::Error => write!(f, "{{error}}"),
+ TyKind::Never => write!(f, "!"),
+
+ // FIXME: write out valid types for these variants
+ TyKind::FnDef(..) => write!(f, "<fn_def>"),
+ TyKind::Closure(..) => write!(f, "<closure>"),
+ TyKind::Foreign(..) => write!(f, "<foreign>"),
+ TyKind::Generator(..) => write!(f, "<generator>"),
+ TyKind::GeneratorWitness(..) => write!(f, "<generator_witness>"),
+
+ TyKind::Array(ty, const_) => write!(f, "[{}; {}]", ty.display(s), const_.display(s),),
+ TyKind::Dyn(dyn_ty) => {
+ // the lifetime needs to be outside of the bounds, so we
+ // introduce a new scope for the bounds
+ {
+ let s = &s.add_debrujin_index(None);
+ // dyn_ty.bounds.binders creates a Self binding for the trait
+ let bounds = dyn_ty.bounds.skip_binders();
+
+ write!(
+ f,
+ "dyn {}",
+ display_self_where_clauses_as_bounds(s, bounds.as_slice(interner)),
+ )?;
+ }
+
+ write!(f, " + {}", dyn_ty.lifetime.display(s))?;
+ Ok(())
+ }
+ TyKind::BoundVar(bound_var) => write!(f, "{}", s.display_bound_var(bound_var)),
+ TyKind::InferenceVar(_, _) => write!(f, "_"),
+ TyKind::Alias(alias_ty) => alias_ty.fmt(s, f),
+ TyKind::Function(func) => func.fmt(s, f),
+ TyKind::Placeholder(_) => write!(f, "<placeholder>"),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for AliasTy<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ match self {
+ AliasTy::Projection(projection_ty) => projection_ty.fmt(s, f),
+ AliasTy::Opaque(opaque_ty) => opaque_ty.fmt(s, f),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for ProjectionTy<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // <X as Y<A1, A2, A3>>::Z<B1, B2, B3>
+
+ // Now, we split out A*, Y/Z and B*:
+ // trait_params is X, A1, A2, A3,
+ // assoc_type_params is B1, B2, B3,
+ // assoc_ty_datum stores info about Y and Z.
+ let (assoc_ty_datum, trait_params, assoc_type_params) = s.db().split_projection(self);
+ write!(
+ f,
+ "<{} as {}>::{}",
+ trait_params[0].display(s),
+ display_type_with_generics(s, assoc_ty_datum.trait_id, &trait_params[1..]),
+ assoc_ty_datum.id.display(s),
+ )?;
+ write_joined_non_empty_list!(
+ f,
+ "<{}>",
+ assoc_type_params.iter().map(|param| param.display(s)),
+ ", "
+ )?;
+ Ok(())
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for OpaqueTy<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ write!(
+ f,
+ "{}",
+ display_type_with_generics(s, self.opaque_ty_id, self.substitution.as_slice(interner),)
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for FnPointer<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ let interner = s.db().interner();
+ let s = &s.add_debrujin_index(None);
+ if self.num_binders > 0 {
+ write!(
+ f,
+ "for<{}> ",
+ (0..self.num_binders)
+ .map(|n| format!("'{}", s.name_for_introduced_bound_var(n)))
+ .format(", ")
+ )?;
+ }
+ let parameters = self.substitution.0.as_slice(interner);
+ write!(
+ f,
+ "fn({}) -> {}",
+ parameters[..parameters.len() - 1]
+ .iter()
+ .map(|param| param.display(s))
+ .format(", "),
+ parameters[parameters.len() - 1].display(s),
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Scalar {
+ fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ use chalk_ir::{FloatTy::*, IntTy::*, UintTy::*};
+ write!(
+ f,
+ "{}",
+ match self {
+ Scalar::Bool => "bool",
+ Scalar::Char => "char",
+ Scalar::Int(int) => match int {
+ Isize => "isize",
+ I8 => "i8",
+ I16 => "i16",
+ I32 => "i32",
+ I64 => "i64",
+ I128 => "i128",
+ },
+ Scalar::Uint(uint) => match uint {
+ Usize => "usize",
+ U8 => "u8",
+ U16 => "u16",
+ U32 => "u32",
+ U64 => "u64",
+ U128 => "u128",
+ },
+ Scalar::Float(float) => match float {
+ F32 => "f32",
+ F64 => "f64",
+ },
+ }
+ )
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for LifetimeData<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ match self {
+ LifetimeData::BoundVar(v) => write!(f, "'{}", s.display_bound_var(v)),
+ LifetimeData::InferenceVar(_) => write!(f, "'_"),
+ LifetimeData::Placeholder(ix) => {
+ write!(f, "'_placeholder_{}_{}", ix.ui.counter, ix.idx)
+ }
+ LifetimeData::Static => write!(f, "'static"),
+ LifetimeData::Erased => write!(f, "'_"),
+ // Matching the void ensures at compile time that this code is
+ // unreachable
+ LifetimeData::Phantom(void, _) => match *void {},
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for ConstData<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ write!(f, "{}", self.value.display(s))
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for ConstValue<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ match self {
+ ConstValue::BoundVar(v) => write!(f, "{}", s.display_bound_var(v)),
+ ConstValue::InferenceVar(_) => write!(f, "_"),
+ ConstValue::Placeholder(_) => write!(f, "<const placeholder>"),
+ ConstValue::Concrete(value) => write!(f, "{:?}", value.interned),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for GenericArgData<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ match self {
+ GenericArgData::Ty(ty) => write!(f, "{}", ty.display(s)),
+ GenericArgData::Lifetime(lt) => write!(f, "{}", lt.display(s)),
+ GenericArgData::Const(const_ty) => write!(f, "{}", const_ty.display(s)),
+ }
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Ty<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // delegate to TyKind
+ self.kind(s.db().interner()).fmt(s, f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Lifetime<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // delegate to LifetimeData
+ self.data(s.db().interner()).fmt(s, f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for Const<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
+ self.data(s.db().interner()).fmt(s, f)
+ }
+}
+
+impl<I: Interner> RenderAsRust<I> for GenericArg<I> {
+ fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
+ // delegate to GenericArgData
+ self.data(s.db().interner()).fmt(s, f)
+ }
+}
diff --git a/vendor/chalk-solve/src/display/utils.rs b/vendor/chalk-solve/src/display/utils.rs
new file mode 100644
index 000000000..306605616
--- /dev/null
+++ b/vendor/chalk-solve/src/display/utils.rs
@@ -0,0 +1,51 @@
+//! Render utilities which don't belong anywhere else.
+use std::fmt::{Display, Formatter, Result};
+
+pub fn as_display<F: Fn(&mut Formatter<'_>) -> Result>(f: F) -> impl Display {
+ struct ClosureDisplay<F: Fn(&mut Formatter<'_>) -> Result>(F);
+
+ impl<F: Fn(&mut Formatter<'_>) -> Result> Display for ClosureDisplay<F> {
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
+ self.0(f)
+ }
+ }
+
+ ClosureDisplay(f)
+}
+
+macro_rules! write_joined_non_empty_list {
+ ($f:expr,$template:tt,$list:expr,$sep:expr) => {{
+ let mut x = $list.into_iter().peekable();
+ if x.peek().is_some() {
+ write!($f, $template, x.format($sep))
+ } else {
+ Ok(())
+ }
+ }};
+}
+
+/// Processes a name given by an [`Interner`][chalk_ir::interner::Interner] debug
+/// method into something usable by the `display` module.
+///
+/// This is specifically useful when implementing
+/// [`RustIrDatabase`][crate::RustIrDatabase] `name_*` methods.
+pub fn sanitize_debug_name(func: impl Fn(&mut Formatter<'_>) -> Option<Result>) -> String {
+ use std::fmt::Write;
+
+ // First, write the debug method contents to a String.
+ let mut debug_out = String::new();
+ // ignore if the result is `None`, as we can just as easily tell by looking
+ // to see if anything was written to `debug_out`.
+ write!(
+ debug_out,
+ "{}",
+ as_display(|fmt| { func(fmt).unwrap_or(Ok(())) })
+ )
+ .expect("expected writing to a String to succeed");
+ if debug_out.is_empty() {
+ return "Unknown".to_owned();
+ }
+
+ // now the actual sanitization
+ debug_out.replace(|c: char| !c.is_ascii_alphanumeric(), "_")
+}
diff --git a/vendor/chalk-solve/src/ext.rs b/vendor/chalk-solve/src/ext.rs
new file mode 100644
index 000000000..9cb8b774a
--- /dev/null
+++ b/vendor/chalk-solve/src/ext.rs
@@ -0,0 +1,113 @@
+use crate::infer::InferenceTable;
+use chalk_ir::fold::TypeFoldable;
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::*;
+
+pub trait CanonicalExt<T: HasInterner, I: Interner> {
+ fn map<OP, U>(self, interner: I, op: OP) -> Canonical<U>
+ where
+ OP: FnOnce(T) -> U,
+ T: TypeFoldable<I>,
+ U: TypeFoldable<I>,
+ U: HasInterner<Interner = I>;
+}
+
+impl<T, I> CanonicalExt<T, I> for Canonical<T>
+where
+ T: HasInterner<Interner = I>,
+ I: Interner,
+{
+ /// Maps the contents using `op`, but preserving the binders.
+ ///
+ /// NB. `op` will be invoked with an instantiated version of the
+ /// canonical value, where inference variables (from a fresh
+ /// inference context) are used in place of the quantified free
+ /// variables. The result should be in terms of those same
+ /// inference variables and will be re-canonicalized.
+ fn map<OP, U>(self, interner: I, op: OP) -> Canonical<U>
+ where
+ OP: FnOnce(T) -> U,
+ T: TypeFoldable<I>,
+ U: TypeFoldable<I>,
+ U: HasInterner<Interner = I>,
+ {
+ // Subtle: It is only quite rarely correct to apply `op` and
+ // just re-use our existing binders. For that to be valid, the
+ // result of `op` would have to ensure that it re-uses all the
+ // existing free variables and in the same order. Otherwise,
+ // the canonical form would be different: the variables might
+ // be numbered differently, or some may not longer be used.
+ // This would mean that two canonical values could no longer
+ // be compared with `Eq`, which defeats a key invariant of the
+ // `Canonical` type (indeed, its entire reason for existence).
+ let mut infer = InferenceTable::new();
+ let snapshot = infer.snapshot();
+ let instantiated_value = infer.instantiate_canonical(interner, self);
+ let mapped_value = op(instantiated_value);
+ let result = infer.canonicalize(interner, mapped_value);
+ infer.rollback_to(snapshot);
+ result.quantified
+ }
+}
+
+pub trait GoalExt<I: Interner> {
+ fn into_peeled_goal(self, interner: I) -> UCanonical<InEnvironment<Goal<I>>>;
+ fn into_closed_goal(self, interner: I) -> UCanonical<InEnvironment<Goal<I>>>;
+}
+
+impl<I: Interner> GoalExt<I> for Goal<I> {
+ /// Returns a canonical goal in which the outermost `exists<>` and
+ /// `forall<>` quantifiers (as well as implications) have been
+ /// "peeled" and are converted into free universal or existential
+ /// variables. Assumes that this goal is a "closed goal" which
+ /// does not -- at present -- contain any variables. Useful for
+ /// REPLs and tests but not much else.
+ fn into_peeled_goal(self, interner: I) -> UCanonical<InEnvironment<Goal<I>>> {
+ let mut infer = InferenceTable::new();
+ let peeled_goal = {
+ let mut env_goal = InEnvironment::new(&Environment::new(interner), self);
+ loop {
+ let InEnvironment { environment, goal } = env_goal;
+ match goal.data(interner) {
+ GoalData::Quantified(QuantifierKind::ForAll, subgoal) => {
+ let subgoal =
+ infer.instantiate_binders_universally(interner, subgoal.clone());
+ env_goal = InEnvironment::new(&environment, subgoal);
+ }
+
+ GoalData::Quantified(QuantifierKind::Exists, subgoal) => {
+ let subgoal =
+ infer.instantiate_binders_existentially(interner, subgoal.clone());
+ env_goal = InEnvironment::new(&environment, subgoal);
+ }
+
+ GoalData::Implies(wc, subgoal) => {
+ let new_environment =
+ environment.add_clauses(interner, wc.iter(interner).cloned());
+ env_goal = InEnvironment::new(&new_environment, Goal::clone(subgoal));
+ }
+
+ _ => break InEnvironment::new(&environment, goal),
+ }
+ }
+ };
+ let canonical = infer.canonicalize(interner, peeled_goal).quantified;
+ InferenceTable::u_canonicalize(interner, &canonical).quantified
+ }
+
+ /// Given a goal with no free variables (a "closed" goal), creates
+ /// a canonical form suitable for solving. This is a suitable
+ /// choice if you don't actually care about the values of any of
+ /// the variables within; otherwise, you might want
+ /// `into_peeled_goal`.
+ ///
+ /// # Panics
+ ///
+ /// Will panic if this goal does in fact contain free variables.
+ fn into_closed_goal(self, interner: I) -> UCanonical<InEnvironment<Goal<I>>> {
+ let mut infer = InferenceTable::new();
+ let env_goal = InEnvironment::new(&Environment::new(interner), self);
+ let canonical_goal = infer.canonicalize(interner, env_goal).quantified;
+ InferenceTable::u_canonicalize(interner, &canonical_goal).quantified
+ }
+}
diff --git a/vendor/chalk-solve/src/goal_builder.rs b/vendor/chalk-solve/src/goal_builder.rs
new file mode 100644
index 000000000..aa5c9c9eb
--- /dev/null
+++ b/vendor/chalk-solve/src/goal_builder.rs
@@ -0,0 +1,152 @@
+use crate::RustIrDatabase;
+use cast::CastTo;
+use chalk_ir::cast::Cast;
+use chalk_ir::cast::Caster;
+use chalk_ir::*;
+use fold::shift::Shift;
+use fold::TypeFoldable;
+use interner::{HasInterner, Interner};
+
+pub struct GoalBuilder<'i, I: Interner> {
+ db: &'i dyn RustIrDatabase<I>,
+}
+
+impl<'i, I: Interner> GoalBuilder<'i, I> {
+ pub fn new(db: &'i dyn RustIrDatabase<I>) -> Self {
+ GoalBuilder { db }
+ }
+
+ /// Returns the database within the goal builder.
+ pub fn db(&self) -> &'i dyn RustIrDatabase<I> {
+ self.db
+ }
+
+ /// Returns the interner within the goal builder.
+ pub fn interner(&self) -> I {
+ self.db.interner()
+ }
+
+ /// Creates a goal that ensures all of the goals from the `goals`
+ /// iterator are met (e.g., `goals[0] && ... && goals[N]`).
+ pub fn all<GS, G>(&mut self, goals: GS) -> Goal<I>
+ where
+ GS: IntoIterator<Item = G>,
+ G: CastTo<Goal<I>>,
+ {
+ Goal::all(self.interner(), goals.into_iter().casted(self.interner()))
+ }
+
+ /// Creates a goal `clauses => goal`. The clauses are given as an iterator
+ /// and the goal is returned via the contained closure.
+ pub fn implies<CS, C, G>(&mut self, clauses: CS, goal: impl FnOnce(&mut Self) -> G) -> Goal<I>
+ where
+ CS: IntoIterator<Item = C>,
+ C: CastTo<ProgramClause<I>>,
+ G: CastTo<Goal<I>>,
+ {
+ GoalData::Implies(
+ ProgramClauses::from_iter(self.interner(), clauses),
+ goal(self).cast(self.interner()),
+ )
+ .intern(self.interner())
+ }
+
+ /// Given a bound value `binders` like `<P0..Pn> V`,
+ /// creates a goal `forall<Q0..Qn> { G }` where
+ /// the goal `G` is created by invoking a helper
+ /// function `body`.
+ ///
+ /// # Parameters to `body`
+ ///
+ /// `body` will be invoked with:
+ ///
+ /// * the goal builder `self`
+ /// * the substitution `Q0..Qn`
+ /// * the bound value `[P0..Pn => Q0..Qn] V` instantiated
+ /// with the substitution
+ /// * the value `passthru`, appropriately shifted so that
+ /// any debruijn indices within account for the new binder
+ ///
+ /// # Why is `body` a function and not a closure?
+ ///
+ /// This is to ensure that `body` doesn't accidentally reference
+ /// values from the environment whose debruijn indices do not
+ /// account for the new binder being created.
+ pub fn forall<G, B, P>(
+ &mut self,
+ binders: &Binders<B>,
+ passthru: P,
+ body: fn(&mut Self, Substitution<I>, &B, P) -> G,
+ ) -> Goal<I>
+ where
+ B: HasInterner<Interner = I>,
+ P: TypeFoldable<I>,
+ G: CastTo<Goal<I>>,
+ {
+ self.quantified(QuantifierKind::ForAll, binders, passthru, body)
+ }
+
+ /// Like [`GoalBuilder::forall`], but for a `exists<Q0..Qn> { G }` goal.
+ pub fn exists<G, B, P>(
+ &mut self,
+ binders: &Binders<B>,
+ passthru: P,
+ body: fn(&mut Self, Substitution<I>, &B, P) -> G,
+ ) -> Goal<I>
+ where
+ B: HasInterner<Interner = I>,
+ P: TypeFoldable<I>,
+ G: CastTo<Goal<I>>,
+ {
+ self.quantified(QuantifierKind::Exists, binders, passthru, body)
+ }
+
+ /// A combined helper functon for the various methods
+ /// to create `forall` and `exists` goals. See:
+ ///
+ /// * [`GoalBuilder::forall`]
+ /// * [`GoalBuilder::exists`]
+ ///
+ /// for details.
+ fn quantified<G, B, P>(
+ &mut self,
+ quantifier_kind: QuantifierKind,
+ binders: &Binders<B>,
+ passthru: P,
+ body: fn(&mut Self, Substitution<I>, &B, P) -> G,
+ ) -> Goal<I>
+ where
+ B: HasInterner<Interner = I>,
+ P: TypeFoldable<I>,
+ G: CastTo<Goal<I>>,
+ {
+ let interner = self.interner();
+
+ // Make an identity mapping `[0 => ^0.0, 1 => ^0.1, ..]`
+ // and so forth. This substitution is mapping from the `<P0..Pn>` variables
+ // in `binders` to the corresponding `P0..Pn` variables we're about to
+ // introduce in the form of a `forall<P0..Pn>` goal. Of course, it's
+ // actually an identity mapping, since this `forall` will be the innermost
+ // debruijn binder and so forth, so there's no actual reason to
+ // *do* the substitution, since it would effectively just be a clone.
+ let substitution = Substitution::from_iter(
+ interner,
+ binders
+ .binders
+ .iter(interner)
+ .enumerate()
+ .map(|p| p.to_generic_arg(interner)),
+ );
+
+ // Shift passthru into one level of binder, to account for the `forall<P0..Pn>`
+ // we are about to introduce.
+ let passthru_shifted = passthru.shifted_in(self.interner());
+
+ // Invoke `body` function, which returns a goal, and wrap that goal in the binders
+ // from `binders`, and finally a `forall` or `exists` goal.
+ let bound_goal = binders.map_ref(|bound_value| {
+ body(self, substitution, bound_value, passthru_shifted).cast(interner)
+ });
+ GoalData::Quantified(quantifier_kind, bound_goal).intern(interner)
+ }
+}
diff --git a/vendor/chalk-solve/src/infer.rs b/vendor/chalk-solve/src/infer.rs
new file mode 100644
index 000000000..6ede065e0
--- /dev/null
+++ b/vendor/chalk-solve/src/infer.rs
@@ -0,0 +1,212 @@
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::*;
+use chalk_ir::{cast::Cast, fold::TypeFoldable};
+use tracing::debug;
+
+mod canonicalize;
+pub(crate) mod instantiate;
+mod invert;
+mod test;
+pub mod ucanonicalize;
+pub mod unify;
+mod var;
+
+use self::var::*;
+
+#[derive(Clone)]
+pub struct InferenceTable<I: Interner> {
+ unify: ena::unify::InPlaceUnificationTable<EnaVariable<I>>,
+ vars: Vec<EnaVariable<I>>,
+ max_universe: UniverseIndex,
+}
+
+pub struct InferenceSnapshot<I: Interner> {
+ unify_snapshot: ena::unify::Snapshot<ena::unify::InPlace<EnaVariable<I>>>,
+ max_universe: UniverseIndex,
+ vars: Vec<EnaVariable<I>>,
+}
+
+#[allow(type_alias_bounds)]
+pub type ParameterEnaVariable<I: Interner> = WithKind<I, EnaVariable<I>>;
+
+impl<I: Interner> InferenceTable<I> {
+ /// Create an empty inference table with no variables.
+ pub fn new() -> Self {
+ InferenceTable {
+ unify: ena::unify::UnificationTable::new(),
+ vars: vec![],
+ max_universe: UniverseIndex::root(),
+ }
+ }
+
+ /// Creates a new inference table, pre-populated with
+ /// `num_universes` fresh universes. Instantiates the canonical
+ /// value `canonical` within those universes (which must not
+ /// reference any universe greater than `num_universes`). Returns
+ /// the substitution mapping from each canonical binder to its
+ /// corresponding existential variable, along with the
+ /// instantiated result.
+ pub fn from_canonical<T>(
+ interner: I,
+ num_universes: usize,
+ canonical: Canonical<T>,
+ ) -> (Self, Substitution<I>, T)
+ where
+ T: HasInterner<Interner = I> + TypeFoldable<I> + Clone,
+ {
+ let mut table = InferenceTable::new();
+
+ assert!(num_universes >= 1); // always have U0
+ for _ in 1..num_universes {
+ table.new_universe();
+ }
+
+ let subst = table.fresh_subst(interner, canonical.binders.as_slice(interner));
+ let value = subst.apply(canonical.value, interner);
+ // let value = canonical.value.fold_with(&mut &subst, 0).unwrap();
+
+ (table, subst, value)
+ }
+
+ /// Creates and returns a fresh universe that is distinct from all
+ /// others created within this inference table. This universe is
+ /// able to see all previously created universes (though hopefully
+ /// it is only brought into contact with its logical *parents*).
+ pub fn new_universe(&mut self) -> UniverseIndex {
+ let u = self.max_universe.next();
+ self.max_universe = u;
+ debug!("created new universe: {:?}", u);
+ u
+ }
+
+ /// Creates a new inference variable and returns its index. The
+ /// kind of the variable should be known by the caller, but is not
+ /// tracked directly by the inference table.
+ pub fn new_variable(&mut self, ui: UniverseIndex) -> EnaVariable<I> {
+ let var = self.unify.new_key(InferenceValue::Unbound(ui));
+ self.vars.push(var);
+ debug!(?var, ?ui, "created new variable");
+ var
+ }
+
+ /// Takes a "snapshot" of the current state of the inference
+ /// table. Later, you must invoke either `rollback_to` or
+ /// `commit` with that snapshot. Snapshots can be nested, but you
+ /// must respect a stack discipline (i.e., rollback or commit
+ /// snapshots in reverse order of that with which they were
+ /// created).
+ pub fn snapshot(&mut self) -> InferenceSnapshot<I> {
+ let unify_snapshot = self.unify.snapshot();
+ let vars = self.vars.clone();
+ let max_universe = self.max_universe;
+ InferenceSnapshot {
+ unify_snapshot,
+ max_universe,
+ vars,
+ }
+ }
+
+ /// Restore the table to the state it had when the snapshot was taken.
+ pub fn rollback_to(&mut self, snapshot: InferenceSnapshot<I>) {
+ self.unify.rollback_to(snapshot.unify_snapshot);
+ self.vars = snapshot.vars;
+ self.max_universe = snapshot.max_universe;
+ }
+
+ /// Make permanent the changes made since the snapshot was taken.
+ pub fn commit(&mut self, snapshot: InferenceSnapshot<I>) {
+ self.unify.commit(snapshot.unify_snapshot);
+ }
+
+ pub fn normalize_ty_shallow(&mut self, interner: I, leaf: &Ty<I>) -> Option<Ty<I>> {
+ // An integer/float type variable will never normalize to another
+ // variable; but a general type variable might normalize to an
+ // integer/float variable. So we potentially need to normalize twice to
+ // get at the actual value.
+ self.normalize_ty_shallow_inner(interner, leaf)
+ .map(|ty| self.normalize_ty_shallow_inner(interner, &ty).unwrap_or(ty))
+ }
+
+ fn normalize_ty_shallow_inner(&mut self, interner: I, leaf: &Ty<I>) -> Option<Ty<I>> {
+ self.probe_var(leaf.inference_var(interner)?)
+ .map(|p| p.assert_ty_ref(interner).clone())
+ }
+
+ pub fn normalize_lifetime_shallow(
+ &mut self,
+ interner: I,
+ leaf: &Lifetime<I>,
+ ) -> Option<Lifetime<I>> {
+ self.probe_var(leaf.inference_var(interner)?)
+ .map(|p| p.assert_lifetime_ref(interner).clone())
+ }
+
+ pub fn normalize_const_shallow(&mut self, interner: I, leaf: &Const<I>) -> Option<Const<I>> {
+ self.probe_var(leaf.inference_var(interner)?)
+ .map(|p| p.assert_const_ref(interner).clone())
+ }
+
+ pub fn ty_root(&mut self, interner: I, leaf: &Ty<I>) -> Option<Ty<I>> {
+ Some(
+ self.unify
+ .find(leaf.inference_var(interner)?)
+ .to_ty(interner),
+ )
+ }
+
+ pub fn lifetime_root(&mut self, interner: I, leaf: &Lifetime<I>) -> Option<Lifetime<I>> {
+ Some(
+ self.unify
+ .find(leaf.inference_var(interner)?)
+ .to_lifetime(interner),
+ )
+ }
+
+ /// Finds the root inference var for the given variable.
+ ///
+ /// The returned variable will be exactly equivalent to the given
+ /// variable except in name. All variables which have been unified to
+ /// eachother (but don't yet have a value) have the same "root".
+ ///
+ /// This is useful for `DeepNormalizer`.
+ pub fn inference_var_root(&mut self, var: InferenceVar) -> InferenceVar {
+ self.unify.find(var).into()
+ }
+
+ /// If type `leaf` is a free inference variable, and that variable has been
+ /// bound, returns `Some(P)` where `P` is the parameter to which it has been bound.
+ pub fn probe_var(&mut self, leaf: InferenceVar) -> Option<GenericArg<I>> {
+ match self.unify.probe_value(EnaVariable::from(leaf)) {
+ InferenceValue::Unbound(_) => None,
+ InferenceValue::Bound(val) => Some(val),
+ }
+ }
+
+ /// Given an unbound variable, returns its universe.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the variable is bound.
+ fn universe_of_unbound_var(&mut self, var: EnaVariable<I>) -> UniverseIndex {
+ match self.unify.probe_value(var) {
+ InferenceValue::Unbound(ui) => ui,
+ InferenceValue::Bound(_) => panic!("var_universe invoked on bound variable"),
+ }
+ }
+}
+
+pub trait ParameterEnaVariableExt<I: Interner> {
+ fn to_generic_arg(&self, interner: I) -> GenericArg<I>;
+}
+
+impl<I: Interner> ParameterEnaVariableExt<I> for ParameterEnaVariable<I> {
+ fn to_generic_arg(&self, interner: I) -> GenericArg<I> {
+ // we are matching on kind, so skipping it is fine
+ let ena_variable = self.skip_kind();
+ match &self.kind {
+ VariableKind::Ty(kind) => ena_variable.to_ty_with_kind(interner, *kind).cast(interner),
+ VariableKind::Lifetime => ena_variable.to_lifetime(interner).cast(interner),
+ VariableKind::Const(ty) => ena_variable.to_const(interner, ty.clone()).cast(interner),
+ }
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/canonicalize.rs b/vendor/chalk-solve/src/infer/canonicalize.rs
new file mode 100644
index 000000000..ddec0515d
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/canonicalize.rs
@@ -0,0 +1,237 @@
+use crate::debug_span;
+use chalk_derive::FallibleTypeFolder;
+use chalk_ir::fold::shift::Shift;
+use chalk_ir::fold::{TypeFoldable, TypeFolder};
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::*;
+use std::cmp::max;
+use tracing::{debug, instrument};
+
+use super::{InferenceTable, ParameterEnaVariable};
+
+impl<I: Interner> InferenceTable<I> {
+ /// Given a value `value` with variables in it, replaces those variables
+ /// with their instantiated values; any variables not yet instantiated are
+ /// replaced with a small integer index 0..N in order of appearance. The
+ /// result is a canonicalized representation of `value`.
+ ///
+ /// Example:
+ ///
+ /// ?22: Foo<?23>
+ ///
+ /// would be quantified to
+ ///
+ /// Canonical { value: `?0: Foo<?1>`, binders: [ui(?22), ui(?23)] }
+ ///
+ /// where `ui(?22)` and `ui(?23)` are the universe indices of `?22` and
+ /// `?23` respectively.
+ ///
+ /// A substitution mapping from the free variables to their re-bound form is
+ /// also returned.
+ pub fn canonicalize<T>(&mut self, interner: I, value: T) -> Canonicalized<T>
+ where
+ T: TypeFoldable<I>,
+ T: HasInterner<Interner = I>,
+ {
+ debug_span!("canonicalize", "{:#?}", value);
+ let mut q = Canonicalizer {
+ table: self,
+ free_vars: Vec::new(),
+ max_universe: UniverseIndex::root(),
+ interner,
+ };
+ let value = value
+ .try_fold_with(&mut q, DebruijnIndex::INNERMOST)
+ .unwrap();
+ let free_vars = q.free_vars.clone();
+
+ Canonicalized {
+ quantified: Canonical {
+ value,
+ binders: q.into_binders(),
+ },
+ free_vars,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct Canonicalized<T: HasInterner> {
+ /// The canonicalized result.
+ pub quantified: Canonical<T>,
+
+ /// The free existential variables, along with the universes they inhabit.
+ pub free_vars: Vec<ParameterEnaVariable<T::Interner>>,
+}
+
+#[derive(FallibleTypeFolder)]
+struct Canonicalizer<'q, I: Interner> {
+ table: &'q mut InferenceTable<I>,
+ free_vars: Vec<ParameterEnaVariable<I>>,
+ max_universe: UniverseIndex,
+ interner: I,
+}
+
+impl<'q, I: Interner> Canonicalizer<'q, I> {
+ fn into_binders(self) -> CanonicalVarKinds<I> {
+ let Canonicalizer {
+ table,
+ free_vars,
+ interner,
+ ..
+ } = self;
+ CanonicalVarKinds::from_iter(
+ interner,
+ free_vars
+ .into_iter()
+ .map(|p_v| p_v.map(|v| table.universe_of_unbound_var(v))),
+ )
+ }
+
+ fn add(&mut self, free_var: ParameterEnaVariable<I>) -> usize {
+ self.max_universe = max(
+ self.max_universe,
+ self.table.universe_of_unbound_var(*free_var.skip_kind()),
+ );
+
+ self.free_vars
+ .iter()
+ .position(|v| v.skip_kind() == free_var.skip_kind())
+ .unwrap_or_else(|| {
+ let next_index = self.free_vars.len();
+ self.free_vars.push(free_var);
+ next_index
+ })
+ }
+}
+
+impl<'i, I: Interner> TypeFolder<I> for Canonicalizer<'i, I> {
+ fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
+ self
+ }
+
+ fn fold_free_placeholder_ty(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Ty<I> {
+ let interner = self.interner;
+ self.max_universe = max(self.max_universe, universe.ui);
+ universe.to_ty(interner)
+ }
+
+ fn fold_free_placeholder_lifetime(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let interner = self.interner;
+ self.max_universe = max(self.max_universe, universe.ui);
+ universe.to_lifetime(interner)
+ }
+
+ fn fold_free_placeholder_const(
+ &mut self,
+ ty: Ty<I>,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Const<I> {
+ let interner = self.interner;
+ self.max_universe = max(self.max_universe, universe.ui);
+ universe.to_const(interner, ty)
+ }
+
+ fn forbid_free_vars(&self) -> bool {
+ true
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn fold_inference_ty(
+ &mut self,
+ var: InferenceVar,
+ kind: TyVariableKind,
+ outer_binder: DebruijnIndex,
+ ) -> Ty<I> {
+ let interner = self.interner;
+ match self.table.probe_var(var) {
+ Some(ty) => {
+ let ty = ty.assert_ty_ref(interner);
+ debug!("bound to {:?}", ty);
+ ty.clone()
+ .fold_with(self, DebruijnIndex::INNERMOST)
+ .shifted_in_from(interner, outer_binder)
+ }
+ None => {
+ // If this variable is not yet bound, find its
+ // canonical index `root_var` in the union-find table,
+ // and then map `root_var` to a fresh index that is
+ // unique to this quantification.
+ let free_var =
+ ParameterEnaVariable::new(VariableKind::Ty(kind), self.table.unify.find(var));
+
+ let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var));
+ debug!(position=?bound_var, "not yet unified");
+ TyKind::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner)
+ }
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn fold_inference_lifetime(
+ &mut self,
+ var: InferenceVar,
+ outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let interner = self.interner;
+ match self.table.probe_var(var) {
+ Some(l) => {
+ let l = l.assert_lifetime_ref(interner);
+ debug!("bound to {:?}", l);
+ l.clone()
+ .fold_with(self, DebruijnIndex::INNERMOST)
+ .shifted_in_from(interner, outer_binder)
+ }
+ None => {
+ let free_var =
+ ParameterEnaVariable::new(VariableKind::Lifetime, self.table.unify.find(var));
+ let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var));
+ debug!(position=?bound_var, "not yet unified");
+ LifetimeData::BoundVar(bound_var.shifted_in_from(outer_binder)).intern(interner)
+ }
+ }
+ }
+
+ #[instrument(level = "debug", skip(self, ty))]
+ fn fold_inference_const(
+ &mut self,
+ ty: Ty<I>,
+ var: InferenceVar,
+ outer_binder: DebruijnIndex,
+ ) -> Const<I> {
+ let interner = self.interner;
+ match self.table.probe_var(var) {
+ Some(c) => {
+ let c = c.assert_const_ref(interner);
+ debug!("bound to {:?}", c);
+ c.clone()
+ .fold_with(self, DebruijnIndex::INNERMOST)
+ .shifted_in_from(interner, outer_binder)
+ }
+ None => {
+ let free_var = ParameterEnaVariable::new(
+ VariableKind::Const(ty.clone()),
+ self.table.unify.find(var),
+ );
+ let bound_var = BoundVar::new(DebruijnIndex::INNERMOST, self.add(free_var));
+ debug!(position = ?bound_var, "not yet unified");
+ bound_var
+ .shifted_in_from(outer_binder)
+ .to_const(interner, ty)
+ }
+ }
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/instantiate.rs b/vendor/chalk-solve/src/infer/instantiate.rs
new file mode 100644
index 000000000..161271f23
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/instantiate.rs
@@ -0,0 +1,111 @@
+use chalk_ir::fold::*;
+use chalk_ir::interner::HasInterner;
+use std::fmt::Debug;
+use tracing::instrument;
+
+use super::*;
+
+impl<I: Interner> InferenceTable<I> {
+ /// Given the binders from a canonicalized value C, returns a
+ /// substitution S mapping each free variable in C to a fresh
+ /// inference variable. This substitution can then be applied to
+ /// C, which would be equivalent to
+ /// `self.instantiate_canonical(v)`.
+ pub(super) fn fresh_subst(
+ &mut self,
+ interner: I,
+ binders: &[CanonicalVarKind<I>],
+ ) -> Substitution<I> {
+ Substitution::from_iter(
+ interner,
+ binders.iter().map(|kind| {
+ let param_infer_var = kind.map_ref(|&ui| self.new_variable(ui));
+ param_infer_var.to_generic_arg(interner)
+ }),
+ )
+ }
+
+ /// Variant on `instantiate` that takes a `Canonical<T>`.
+ pub fn instantiate_canonical<T>(&mut self, interner: I, bound: Canonical<T>) -> T
+ where
+ T: HasInterner<Interner = I> + TypeFoldable<I> + Debug,
+ {
+ let subst = self.fresh_subst(interner, bound.binders.as_slice(interner));
+ subst.apply(bound.value, interner)
+ }
+
+ /// Instantiates `arg` with fresh existential variables in the
+ /// given universe; the kinds of the variables are implied by
+ /// `binders`. This is used to apply a universally quantified
+ /// clause like `forall X, 'Y. P => Q`. Here the `binders`
+ /// argument is referring to `X, 'Y`.
+ fn instantiate_in<T>(
+ &mut self,
+ interner: I,
+ universe: UniverseIndex,
+ binders: impl Iterator<Item = VariableKind<I>>,
+ arg: T,
+ ) -> T
+ where
+ T: TypeFoldable<I>,
+ {
+ let binders: Vec<_> = binders
+ .map(|pk| CanonicalVarKind::new(pk, universe))
+ .collect();
+ let subst = self.fresh_subst(interner, &binders);
+ subst.apply(arg, interner)
+ }
+
+ /// Variant on `instantiate_in` that takes a `Binders<T>`.
+ #[instrument(level = "debug", skip(self, interner))]
+ pub fn instantiate_binders_existentially<T>(&mut self, interner: I, arg: Binders<T>) -> T
+ where
+ T: TypeFoldable<I> + HasInterner<Interner = I>,
+ {
+ let (value, binders) = arg.into_value_and_skipped_binders();
+
+ let max_universe = self.max_universe;
+ self.instantiate_in(
+ interner,
+ max_universe,
+ binders.iter(interner).cloned(),
+ value,
+ )
+ }
+
+ #[instrument(level = "debug", skip(self, interner))]
+ pub fn instantiate_binders_universally<T>(&mut self, interner: I, arg: Binders<T>) -> T
+ where
+ T: TypeFoldable<I> + HasInterner<Interner = I>,
+ {
+ let (value, binders) = arg.into_value_and_skipped_binders();
+
+ let mut lazy_ui = None;
+ let mut ui = || {
+ lazy_ui.unwrap_or_else(|| {
+ let ui = self.new_universe();
+ lazy_ui = Some(ui);
+ ui
+ })
+ };
+ let parameters: Vec<_> = binders
+ .iter(interner)
+ .cloned()
+ .enumerate()
+ .map(|(idx, pk)| {
+ let placeholder_idx = PlaceholderIndex { ui: ui(), idx };
+ match pk {
+ VariableKind::Lifetime => {
+ let lt = placeholder_idx.to_lifetime(interner);
+ lt.cast(interner)
+ }
+ VariableKind::Ty(_) => placeholder_idx.to_ty(interner).cast(interner),
+ VariableKind::Const(ty) => {
+ placeholder_idx.to_const(interner, ty).cast(interner)
+ }
+ }
+ })
+ .collect();
+ Subst::apply(interner, &parameters, value)
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/invert.rs b/vendor/chalk-solve/src/infer/invert.rs
new file mode 100644
index 000000000..e5bc3590c
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/invert.rs
@@ -0,0 +1,174 @@
+use chalk_derive::FallibleTypeFolder;
+use chalk_ir::fold::shift::Shift;
+use chalk_ir::fold::{TypeFoldable, TypeFolder};
+use chalk_ir::interner::HasInterner;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use rustc_hash::FxHashMap;
+
+use super::canonicalize::Canonicalized;
+use super::{EnaVariable, InferenceTable};
+
+impl<I: Interner> InferenceTable<I> {
+ /// Converts `value` into a "negation" value -- meaning one that,
+ /// if we can find any answer to it, then the negation fails. For
+ /// goals that do not contain any free variables, then this is a
+ /// no-op operation.
+ ///
+ /// If `value` contains any existential variables that have not
+ /// yet been assigned a value, then this function will return
+ /// `None`, indicating that we cannot prove negation for this goal
+ /// yet. This follows the approach in Clark's original
+ /// [negation-as-failure paper][1], where negative goals are only
+ /// permitted if they contain no free (existential) variables.
+ ///
+ /// [1]: https://www.doc.ic.ac.uk/~klc/NegAsFailure.pdf
+ ///
+ /// Restricting free existential variables is done because the
+ /// semantics of such queries is not what you expect: it basically
+ /// treats the existential as a universal. For example, consider:
+ ///
+ /// ```rust,ignore
+ /// struct Vec<T> {}
+ /// struct i32 {}
+ /// struct u32 {}
+ /// trait Foo {}
+ /// impl Foo for Vec<u32> {}
+ /// ```
+ ///
+ /// If we ask `exists<T> { not { Vec<T>: Foo } }`, what should happen?
+ /// If we allow negative queries to be definitively answered even when
+ /// they contain free variables, we will get a definitive *no* to the
+ /// entire goal! From a logical perspective, that's just wrong: there
+ /// does exists a `T` such that `not { Vec<T>: Foo }`, namely `i32`. The
+ /// problem is that the proof search procedure is actually trying to
+ /// prove something stronger, that there is *no* such `T`.
+ ///
+ /// An additional complication arises around free universal
+ /// variables. Consider a query like `not { !0 = !1 }`, where
+ /// `!0` and `!1` are placeholders for universally quantified
+ /// types (i.e., `TyKind::Placeholder`). If we just tried to
+ /// prove `!0 = !1`, we would get false, because those types
+ /// cannot be unified -- this would then allow us to conclude that
+ /// `not { !0 = !1 }`, i.e., `forall<X, Y> { not { X = Y } }`, but
+ /// this is clearly not true -- what if X were to be equal to Y?
+ ///
+ /// Interestingly, the semantics of existential variables turns
+ /// out to be exactly what we want here. So, in addition to
+ /// forbidding existential variables in the original query, the
+ /// `negated` query also converts all universals *into*
+ /// existentials. Hence `negated` applies to `!0 = !1` would yield
+ /// `exists<X,Y> { X = Y }` (note that a canonical, i.e. closed,
+ /// result is returned). Naturally this has a solution, and hence
+ /// `not { !0 = !1 }` fails, as we expect.
+ ///
+ /// (One could imagine converting free existentials into
+ /// universals, rather than forbidding them altogether. This would
+ /// be conceivable, but overly strict. For example, the goal
+ /// `exists<T> { not { ?T: Clone }, ?T = Vec<i32> }` would come
+ /// back as false, when clearly this is true. This is because we
+ /// would wind up proving that `?T: Clone` can *never* be
+ /// satisfied (which is false), when we only really care about
+ /// `?T: Clone` in the case where `?T = Vec<i32>`. The current
+ /// version would delay processing the negative goal (i.e., return
+ /// `None`) until the second unification has occurred.)
+ pub fn invert<T>(&mut self, interner: I, value: T) -> Option<T>
+ where
+ T: TypeFoldable<I> + HasInterner<Interner = I>,
+ {
+ let Canonicalized {
+ free_vars,
+ quantified,
+ ..
+ } = self.canonicalize(interner, value);
+
+ // If the original contains free existential variables, give up.
+ if !free_vars.is_empty() {
+ return None;
+ }
+
+ // If this contains free universal variables, replace them with existentials.
+ assert!(quantified.binders.is_empty(interner));
+ let inverted = quantified
+ .value
+ .try_fold_with(&mut Inverter::new(interner, self), DebruijnIndex::INNERMOST)
+ .unwrap();
+ Some(inverted)
+ }
+
+ /// As `negated_instantiated`, but canonicalizes before
+ /// returning. Just a convenience function.
+ pub fn invert_then_canonicalize<T>(&mut self, interner: I, value: T) -> Option<Canonical<T>>
+ where
+ T: TypeFoldable<I> + HasInterner<Interner = I>,
+ {
+ let snapshot = self.snapshot();
+ let result = self.invert(interner, value);
+ let result = result.map(|r| self.canonicalize(interner, r).quantified);
+ self.rollback_to(snapshot);
+ result
+ }
+}
+
+#[derive(FallibleTypeFolder)]
+struct Inverter<'q, I: Interner> {
+ table: &'q mut InferenceTable<I>,
+ inverted_ty: FxHashMap<PlaceholderIndex, EnaVariable<I>>,
+ inverted_lifetime: FxHashMap<PlaceholderIndex, EnaVariable<I>>,
+ interner: I,
+}
+
+impl<'q, I: Interner> Inverter<'q, I> {
+ fn new(interner: I, table: &'q mut InferenceTable<I>) -> Self {
+ Inverter {
+ table,
+ inverted_ty: FxHashMap::default(),
+ inverted_lifetime: FxHashMap::default(),
+ interner,
+ }
+ }
+}
+
+impl<'i, I: Interner> TypeFolder<I> for Inverter<'i, I> {
+ fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
+ self
+ }
+
+ fn fold_free_placeholder_ty(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Ty<I> {
+ let table = &mut self.table;
+ self.inverted_ty
+ .entry(universe)
+ .or_insert_with(|| table.new_variable(universe.ui))
+ .to_ty(TypeFolder::interner(self))
+ .shifted_in(TypeFolder::interner(self))
+ }
+
+ fn fold_free_placeholder_lifetime(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let table = &mut self.table;
+ self.inverted_lifetime
+ .entry(universe)
+ .or_insert_with(|| table.new_variable(universe.ui))
+ .to_lifetime(TypeFolder::interner(self))
+ .shifted_in(TypeFolder::interner(self))
+ }
+
+ fn forbid_free_vars(&self) -> bool {
+ true
+ }
+
+ fn forbid_inference_vars(&self) -> bool {
+ true
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/test.rs b/vendor/chalk-solve/src/infer/test.rs
new file mode 100644
index 000000000..2ac35f027
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/test.rs
@@ -0,0 +1,422 @@
+#![cfg(test)]
+
+use super::unify::RelationResult;
+use super::*;
+use chalk_integration::interner::ChalkIr;
+use chalk_integration::{arg, lifetime, ty};
+
+// We just use a vec of 20 `Invariant`, since this is zipped and no substs are
+// longer than this
+#[derive(Debug)]
+struct TestDatabase;
+impl UnificationDatabase<ChalkIr> for TestDatabase {
+ fn fn_def_variance(&self, _fn_def_id: FnDefId<ChalkIr>) -> Variances<ChalkIr> {
+ Variances::from_iter(ChalkIr, [Variance::Invariant; 20].iter().copied())
+ }
+
+ fn adt_variance(&self, _adt_id: AdtId<ChalkIr>) -> Variances<ChalkIr> {
+ Variances::from_iter(ChalkIr, [Variance::Invariant; 20].iter().copied())
+ }
+}
+
+#[test]
+fn universe_error() {
+ // exists(A -> forall(X -> A = X)) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn cycle_error() {
+ // exists(A -> A = foo A) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr a)),
+ )
+ .unwrap_err();
+
+ // exists(A -> A = for<'a> A)
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(function 1 (infer 0)),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn cycle_indirect() {
+ // exists(A -> A = foo B, A = B) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U0).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_error_indirect_1() {
+ // exists(A -> forall(X -> exists(B -> B = X, A = B))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_error_indirect_2() {
+ // exists(A -> forall(X -> exists(B -> B = A, B = X))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &b,
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn universe_promote() {
+ // exists(A -> forall(X -> exists(B -> A = foo(B), A = foo(i32)))) ---> OK
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (apply (item 1))),
+ )
+ .unwrap();
+}
+
+#[test]
+fn universe_promote_bad() {
+ // exists(A -> forall(X -> exists(B -> A = foo(B), B = X))) ---> error
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+ let b = table.new_variable(U1).to_ty(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (expr b)),
+ )
+ .unwrap();
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &b,
+ &ty!(placeholder 1),
+ )
+ .unwrap_err();
+}
+
+#[test]
+fn projection_eq() {
+ // exists(A -> A = Item0<<A as Item1>::foo>)
+ // ^^^^^^^^^^^^ Can A repeat here? For now,
+ // we say no, but it's an interesting question.
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let environment0 = Environment::new(interner);
+ let a = table.new_variable(U0).to_ty(interner);
+
+ // expect an error ("cycle during unification")
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &a,
+ &ty!(apply (item 0) (projection (item 1) (expr a))),
+ )
+ .unwrap_err();
+}
+
+const U0: UniverseIndex = UniverseIndex { counter: 0 };
+const U1: UniverseIndex = UniverseIndex { counter: 1 };
+const U2: UniverseIndex = UniverseIndex { counter: 2 };
+
+fn make_table() -> InferenceTable<ChalkIr> {
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let _ = table.new_universe(); // U1
+ let _ = table.new_universe(); // U2
+ table
+}
+
+#[test]
+fn quantify_simple() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let _ = table.new_variable(U0);
+ let _ = table.new_variable(U1);
+ let _ = table.new_variable(U2);
+
+ assert_eq!(
+ table
+ .canonicalize(interner, ty!(apply (item 0) (infer 2) (infer 1) (infer 0)))
+ .quantified,
+ Canonical {
+ value: ty!(apply (item 0) (bound 0) (bound 1) (bound 2)),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U2),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U1),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn quantify_bound() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let environment0 = Environment::new(interner);
+
+ let v0 = table.new_variable(U0).to_ty(interner);
+ let v1 = table.new_variable(U1).to_ty(interner);
+ let v2a = table.new_variable(U2).to_ty(interner);
+ let v2b = table.new_variable(U2).to_ty(interner);
+
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &v2b,
+ &ty!(apply (item 1) (expr v1) (expr v0)),
+ )
+ .unwrap();
+
+ assert_eq!(
+ table
+ .canonicalize(
+ interner,
+ ty!(apply (item 0) (expr v2b) (expr v2a) (expr v1) (expr v0))
+ )
+ .quantified,
+ Canonical {
+ value: ty!(apply (item 0) (apply (item 1) (bound 0) (bound 1)) (bound 2) (bound 0) (bound 1)),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U1),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U2),
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn quantify_ty_under_binder() {
+ let interner = ChalkIr;
+ let mut table = make_table();
+ let v0 = table.new_variable(U0);
+ let v1 = table.new_variable(U0);
+ let _r2 = table.new_variable(U0);
+
+ // Unify v0 and v1.
+ let environment0 = Environment::new(interner);
+ table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &v0.to_ty(interner),
+ &v1.to_ty(interner),
+ )
+ .unwrap();
+
+ // Here: the `function` introduces 3 binders, so in the result,
+ // `(bound 3)` references the first canonicalized inference
+ // variable. -- note that `infer 0` and `infer 1` have been
+ // unified above, as well.
+ assert_eq!(
+ table
+ .canonicalize(
+ interner,
+ ty!(function 3 (apply (item 0) (bound 1) (infer 0) (infer 1) (lifetime (infer 2))))
+ )
+ .quantified,
+ Canonical {
+ value: ty!(function 3 (apply (item 0) (bound 1) (bound 1 0) (bound 1 0) (lifetime (bound 1 1)))),
+ binders: CanonicalVarKinds::from_iter(
+ interner,
+ vec![
+ CanonicalVarKind::new(VariableKind::Ty(TyVariableKind::General), U0),
+ CanonicalVarKind::new(VariableKind::Lifetime, U0)
+ ]
+ ),
+ }
+ );
+}
+
+#[test]
+fn lifetime_constraint_indirect() {
+ let interner = ChalkIr;
+ let mut table: InferenceTable<ChalkIr> = InferenceTable::new();
+ let _ = table.new_universe(); // U1
+
+ let _t_0 = table.new_variable(U0);
+ let _l_1 = table.new_variable(U1);
+
+ let environment0 = Environment::new(interner);
+
+ // Here, we unify '?1 (the lifetime variable in universe 1) with
+ // '!1.
+ let t_a = ty!(apply (item 0) (lifetime (placeholder 1)));
+ let t_b = ty!(apply (item 0) (lifetime (infer 1)));
+ let RelationResult { goals } = table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &t_a,
+ &t_b,
+ )
+ .unwrap();
+ assert!(goals.is_empty());
+
+ // Here, we try to unify `?0` (the type variable in universe 0)
+ // with something that involves `'?1`. Since `'?1` has been
+ // unified with `'!1`, and `'!1` is not visible from universe 0,
+ // we will replace `'!1` with a new variable `'?2` and introduce a
+ // (likely unsatisfiable) constraint relating them.
+ let t_c = ty!(infer 0);
+ let RelationResult { goals } = table
+ .relate(
+ interner,
+ &TestDatabase,
+ &environment0,
+ Variance::Invariant,
+ &t_c,
+ &t_b,
+ )
+ .unwrap();
+ assert_eq!(goals.len(), 2);
+ assert_eq!(
+ format!("{:?}", goals[0]),
+ "InEnvironment { environment: Env([]), goal: \'?2: \'!1_0 }",
+ );
+ assert_eq!(
+ format!("{:?}", goals[1]),
+ "InEnvironment { environment: Env([]), goal: \'!1_0: \'?2 }",
+ );
+}
diff --git a/vendor/chalk-solve/src/infer/ucanonicalize.rs b/vendor/chalk-solve/src/infer/ucanonicalize.rs
new file mode 100644
index 000000000..b44880e37
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/ucanonicalize.rs
@@ -0,0 +1,336 @@
+use crate::debug_span;
+use chalk_derive::FallibleTypeFolder;
+use chalk_ir::fold::{TypeFoldable, TypeFolder};
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::visit::{TypeVisitable, TypeVisitor};
+use chalk_ir::*;
+use std::ops::ControlFlow;
+
+use super::InferenceTable;
+
+impl<I: Interner> InferenceTable<I> {
+ pub fn u_canonicalize<T>(interner: I, value0: &Canonical<T>) -> UCanonicalized<T>
+ where
+ T: Clone + HasInterner<Interner = I> + TypeFoldable<I> + TypeVisitable<I>,
+ T: HasInterner<Interner = I>,
+ {
+ debug_span!("u_canonicalize", "{:#?}", value0);
+
+ // First, find all the universes that appear in `value`.
+ let mut universes = UniverseMap::new();
+
+ for universe in value0.binders.iter(interner) {
+ universes.add(*universe.skip_kind());
+ }
+
+ value0.value.visit_with(
+ &mut UCollector {
+ universes: &mut universes,
+ interner,
+ },
+ DebruijnIndex::INNERMOST,
+ );
+
+ // Now re-map the universes found in value. We have to do this
+ // in a second pass because it is only then that we know the
+ // full set of universes found in the original value.
+ let value1 = value0
+ .value
+ .clone()
+ .try_fold_with(
+ &mut UMapToCanonical {
+ universes: &universes,
+ interner,
+ },
+ DebruijnIndex::INNERMOST,
+ )
+ .unwrap();
+ let binders = CanonicalVarKinds::from_iter(
+ interner,
+ value0
+ .binders
+ .iter(interner)
+ .map(|pk| pk.map_ref(|&ui| universes.map_universe_to_canonical(ui).unwrap())),
+ );
+
+ UCanonicalized {
+ quantified: UCanonical {
+ universes: universes.num_canonical_universes(),
+ canonical: Canonical {
+ value: value1,
+ binders,
+ },
+ },
+ universes,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct UCanonicalized<T: HasInterner> {
+ /// The canonicalized result.
+ pub quantified: UCanonical<T>,
+
+ /// A map between the universes in `quantified` and the original universes
+ pub universes: UniverseMap,
+}
+
+pub trait UniverseMapExt {
+ fn add(&mut self, universe: UniverseIndex);
+ fn map_universe_to_canonical(&self, universe: UniverseIndex) -> Option<UniverseIndex>;
+ fn map_universe_from_canonical(&self, universe: UniverseIndex) -> UniverseIndex;
+ fn map_from_canonical<T, I>(&self, interner: I, canonical_value: &Canonical<T>) -> Canonical<T>
+ where
+ T: Clone + TypeFoldable<I> + HasInterner<Interner = I>,
+ T: HasInterner<Interner = I>,
+ I: Interner;
+}
+impl UniverseMapExt for UniverseMap {
+ fn add(&mut self, universe: UniverseIndex) {
+ if let Err(i) = self.universes.binary_search(&universe) {
+ self.universes.insert(i, universe);
+ }
+ }
+
+ /// Given a universe U that appeared in our original value, return
+ /// the universe to use in the u-canonical value. This is done by
+ /// looking for the index I of U in `self.universes`. We will
+ /// return the universe with "counter" I. This effectively
+ /// "compresses" the range of universes to things from
+ /// `0..self.universes.len()`. If the universe is not present in the map,
+ /// we return `None`.
+ fn map_universe_to_canonical(&self, universe: UniverseIndex) -> Option<UniverseIndex> {
+ self.universes
+ .binary_search(&universe)
+ .ok()
+ .map(|index| UniverseIndex { counter: index })
+ }
+
+ /// Given a "canonical universe" -- one found in the
+ /// `u_canonicalize` result -- returns the original universe that
+ /// it corresponded to.
+ fn map_universe_from_canonical(&self, universe: UniverseIndex) -> UniverseIndex {
+ if universe.counter < self.universes.len() {
+ self.universes[universe.counter]
+ } else {
+ // If this universe is out of bounds, we assume an
+ // implicit `forall` binder, effectively, and map to a
+ // "big enough" universe in the original space. See
+ // comments on `map_from_canonical` for a detailed
+ // explanation.
+ let difference = universe.counter - self.universes.len();
+ let max_counter = self.universes.last().unwrap().counter;
+ let new_counter = max_counter + difference + 1;
+ UniverseIndex {
+ counter: new_counter,
+ }
+ }
+ }
+
+ /// Returns a mapped version of `value` where the universes have
+ /// been translated from canonical universes into the original
+ /// universes.
+ ///
+ /// In some cases, `value` may contain fresh universes that are
+ /// not described in the original map. This occurs when we return
+ /// region constraints -- for example, if we were to process a
+ /// constraint like `for<'a> 'a == 'b`, where `'b` is an inference
+ /// variable, that would generate a region constraint that `!2 ==
+ /// ?0`. (This constraint is typically not, as it happens,
+ /// satisfiable, but it may be, depending on the bounds on `!2`.)
+ /// In effect, there is a "for all" binder around the constraint,
+ /// but it is not represented explicitly -- only implicitly, by
+ /// the presence of a U2 variable.
+ ///
+ /// If we encounter universes like this, which are "out of bounds"
+ /// from our original set of universes, we map them to a distinct
+ /// universe in the original space that is greater than all the
+ /// other universes in the map. That is, if we encounter a
+ /// canonical universe `Ux` where our canonical vector is (say)
+ /// `[U0, U3]`, we would compute the difference `d = x - 2` and
+ /// then return the universe `3 + d + 1`.
+ ///
+ /// The important thing is that we preserve (a) the relative order
+ /// of universes, since that determines visibility, and (b) that
+ /// the universe we produce does not correspond to any of the
+ /// other original universes.
+ fn map_from_canonical<T, I>(&self, interner: I, canonical_value: &Canonical<T>) -> Canonical<T>
+ where
+ T: Clone + TypeFoldable<I> + HasInterner<Interner = I>,
+ T: HasInterner<Interner = I>,
+ I: Interner,
+ {
+ debug_span!("map_from_canonical", ?canonical_value, universes = ?self.universes);
+
+ let binders = canonical_value
+ .binders
+ .iter(interner)
+ .map(|cvk| cvk.map_ref(|&universe| self.map_universe_from_canonical(universe)));
+
+ let value = canonical_value
+ .value
+ .clone()
+ .try_fold_with(
+ &mut UMapFromCanonical {
+ interner,
+ universes: self,
+ },
+ DebruijnIndex::INNERMOST,
+ )
+ .unwrap();
+
+ Canonical {
+ binders: CanonicalVarKinds::from_iter(interner, binders),
+ value,
+ }
+ }
+}
+
+/// The `UCollector` is a "no-op" in terms of the value, but along the
+/// way it collects all universes that were found into a vector.
+struct UCollector<'q, I> {
+ universes: &'q mut UniverseMap,
+ interner: I,
+}
+
+impl<I: Interner> TypeVisitor<I> for UCollector<'_, I> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn visit_free_placeholder(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> ControlFlow<()> {
+ self.universes.add(universe.ui);
+ ControlFlow::Continue(())
+ }
+
+ fn forbid_inference_vars(&self) -> bool {
+ true
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
+
+#[derive(FallibleTypeFolder)]
+struct UMapToCanonical<'q, I: Interner> {
+ interner: I,
+ universes: &'q UniverseMap,
+}
+
+impl<'i, I: Interner> TypeFolder<I> for UMapToCanonical<'i, I> {
+ fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
+ self
+ }
+
+ fn forbid_inference_vars(&self) -> bool {
+ true
+ }
+
+ fn fold_free_placeholder_ty(
+ &mut self,
+ universe0: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Ty<I> {
+ let ui = self
+ .universes
+ .map_universe_to_canonical(universe0.ui)
+ .expect("Expected UCollector to encounter this universe");
+ PlaceholderIndex {
+ ui,
+ idx: universe0.idx,
+ }
+ .to_ty(TypeFolder::interner(self))
+ }
+
+ fn fold_free_placeholder_lifetime(
+ &mut self,
+ universe0: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let universe = self
+ .universes
+ .map_universe_to_canonical(universe0.ui)
+ .expect("Expected UCollector to encounter this universe");
+
+ PlaceholderIndex {
+ ui: universe,
+ idx: universe0.idx,
+ }
+ .to_lifetime(TypeFolder::interner(self))
+ }
+
+ fn fold_free_placeholder_const(
+ &mut self,
+ ty: Ty<I>,
+ universe0: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Const<I> {
+ let universe = self
+ .universes
+ .map_universe_to_canonical(universe0.ui)
+ .expect("Expected UCollector to encounter this universe");
+
+ PlaceholderIndex {
+ ui: universe,
+ idx: universe0.idx,
+ }
+ .to_const(TypeFolder::interner(self), ty)
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
+
+#[derive(FallibleTypeFolder)]
+struct UMapFromCanonical<'q, I: Interner> {
+ interner: I,
+ universes: &'q UniverseMap,
+}
+
+impl<'i, I: Interner> TypeFolder<I> for UMapFromCanonical<'i, I> {
+ fn as_dyn(&mut self) -> &mut dyn TypeFolder<I> {
+ self
+ }
+
+ fn fold_free_placeholder_ty(
+ &mut self,
+ universe0: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Ty<I> {
+ let ui = self.universes.map_universe_from_canonical(universe0.ui);
+ PlaceholderIndex {
+ ui,
+ idx: universe0.idx,
+ }
+ .to_ty(TypeFolder::interner(self))
+ }
+
+ fn fold_free_placeholder_lifetime(
+ &mut self,
+ universe0: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Lifetime<I> {
+ let universe = self.universes.map_universe_from_canonical(universe0.ui);
+ PlaceholderIndex {
+ ui: universe,
+ idx: universe0.idx,
+ }
+ .to_lifetime(TypeFolder::interner(self))
+ }
+
+ fn forbid_inference_vars(&self) -> bool {
+ true
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/unify.rs b/vendor/chalk-solve/src/infer/unify.rs
new file mode 100644
index 000000000..10086e651
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/unify.rs
@@ -0,0 +1,1448 @@
+use super::var::*;
+use super::*;
+use crate::debug_span;
+use chalk_ir::cast::Cast;
+use chalk_ir::fold::{FallibleTypeFolder, TypeFoldable};
+use chalk_ir::interner::{HasInterner, Interner};
+use chalk_ir::zip::{Zip, Zipper};
+use chalk_ir::UnificationDatabase;
+use std::fmt::Debug;
+use tracing::{debug, instrument};
+
+impl<I: Interner> InferenceTable<I> {
+ pub fn relate<T>(
+ &mut self,
+ interner: I,
+ db: &dyn UnificationDatabase<I>,
+ environment: &Environment<I>,
+ variance: Variance,
+ a: &T,
+ b: &T,
+ ) -> Fallible<RelationResult<I>>
+ where
+ T: ?Sized + Zip<I>,
+ {
+ let snapshot = self.snapshot();
+ match Unifier::new(interner, db, self, environment).relate(variance, a, b) {
+ Ok(r) => {
+ self.commit(snapshot);
+ Ok(r)
+ }
+ Err(e) => {
+ self.rollback_to(snapshot);
+ Err(e)
+ }
+ }
+ }
+}
+
+struct Unifier<'t, I: Interner> {
+ table: &'t mut InferenceTable<I>,
+ environment: &'t Environment<I>,
+ goals: Vec<InEnvironment<Goal<I>>>,
+ interner: I,
+ db: &'t dyn UnificationDatabase<I>,
+}
+
+#[derive(Debug)]
+pub struct RelationResult<I: Interner> {
+ pub goals: Vec<InEnvironment<Goal<I>>>,
+}
+
+impl<'t, I: Interner> Unifier<'t, I> {
+ fn new(
+ interner: I,
+ db: &'t dyn UnificationDatabase<I>,
+ table: &'t mut InferenceTable<I>,
+ environment: &'t Environment<I>,
+ ) -> Self {
+ Unifier {
+ environment,
+ table,
+ goals: vec![],
+ interner,
+ db,
+ }
+ }
+
+ /// The main entry point for the `Unifier` type and really the
+ /// only type meant to be called externally. Performs a
+ /// relation of `a` and `b` and returns the Unification Result.
+ #[instrument(level = "debug", skip(self))]
+ fn relate<T>(mut self, variance: Variance, a: &T, b: &T) -> Fallible<RelationResult<I>>
+ where
+ T: ?Sized + Zip<I>,
+ {
+ Zip::zip_with(&mut self, variance, a, b)?;
+ let interner = self.interner();
+ let mut goals = self.goals;
+ let table = self.table;
+ // Sometimes we'll produce a lifetime outlives goal which we later solve by unification
+ // Technically, these *will* get canonicalized to the same bound var and so that will end up
+ // as a goal like `^0.0 <: ^0.0`, which is trivially true. But, we remove those *here*, which
+ // might help caching.
+ goals.retain(|g| match g.goal.data(interner) {
+ GoalData::SubtypeGoal(SubtypeGoal { a, b }) => {
+ let n_a = table.ty_root(interner, a);
+ let n_b = table.ty_root(interner, b);
+ let a = n_a.as_ref().unwrap_or(a);
+ let b = n_b.as_ref().unwrap_or(b);
+ a != b
+ }
+ _ => true,
+ });
+ Ok(RelationResult { goals })
+ }
+
+ /// Relate `a`, `b` with the variance such that if `variance = Covariant`, `a` is
+ /// a subtype of `b`.
+ fn relate_ty_ty(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
+ let interner = self.interner;
+
+ let n_a = self.table.normalize_ty_shallow(interner, a);
+ let n_b = self.table.normalize_ty_shallow(interner, b);
+ let a = n_a.as_ref().unwrap_or(a);
+ let b = n_b.as_ref().unwrap_or(b);
+
+ debug_span!("relate_ty_ty", ?variance, ?a, ?b);
+
+ if a.kind(interner) == b.kind(interner) {
+ return Ok(());
+ }
+
+ match (a.kind(interner), b.kind(interner)) {
+ // Relating two inference variables:
+ // First, if either variable is a float or int kind, then we always
+ // unify if they match. This is because float and ints don't have
+ // subtype relationships.
+ // If both kinds are general then:
+ // If `Invariant`, unify them in the underlying ena table.
+ // If `Covariant` or `Contravariant`, push `SubtypeGoal`
+ (&TyKind::InferenceVar(var1, kind1), &TyKind::InferenceVar(var2, kind2)) => {
+ if matches!(kind1, TyVariableKind::General)
+ && matches!(kind2, TyVariableKind::General)
+ {
+ // Both variable kinds are general; so unify if invariant, otherwise push subtype goal
+ match variance {
+ Variance::Invariant => self.unify_var_var(var1, var2),
+ Variance::Covariant => {
+ self.push_subtype_goal(a.clone(), b.clone());
+ Ok(())
+ }
+ Variance::Contravariant => {
+ self.push_subtype_goal(b.clone(), a.clone());
+ Ok(())
+ }
+ }
+ } else if kind1 == kind2 {
+ // At least one kind is not general, but they match, so unify
+ self.unify_var_var(var1, var2)
+ } else if kind1 == TyVariableKind::General {
+ // First kind is general, second isn't, unify
+ self.unify_general_var_specific_ty(var1, b.clone())
+ } else if kind2 == TyVariableKind::General {
+ // Second kind is general, first isn't, unify
+ self.unify_general_var_specific_ty(var2, a.clone())
+ } else {
+ debug!(
+ "Tried to unify mis-matching inference variables: {:?} and {:?}",
+ kind1, kind2
+ );
+ Err(NoSolution)
+ }
+ }
+
+ // Unifying `forall<X> { T }` with some other forall type `forall<X> { U }`
+ (&TyKind::Function(ref fn1), &TyKind::Function(ref fn2)) => {
+ if fn1.sig == fn2.sig {
+ Zip::zip_with(
+ self,
+ variance,
+ &fn1.clone().into_binders(interner),
+ &fn2.clone().into_binders(interner),
+ )
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ (&TyKind::Placeholder(ref p1), &TyKind::Placeholder(ref p2)) => {
+ Zip::zip_with(self, variance, p1, p2)
+ }
+
+ // Unifying two dyn is possible if they have the same bounds.
+ (&TyKind::Dyn(ref qwc1), &TyKind::Dyn(ref qwc2)) => {
+ Zip::zip_with(self, variance, qwc1, qwc2)
+ }
+
+ (TyKind::BoundVar(_), _) | (_, TyKind::BoundVar(_)) => panic!(
+ "unification encountered bound variable: a={:?} b={:?}",
+ a, b
+ ),
+
+ // Unifying an alias type with some other type `U`.
+ (_, &TyKind::Alias(ref alias)) => self.relate_alias_ty(variance.invert(), alias, a),
+ (&TyKind::Alias(ref alias), _) => self.relate_alias_ty(variance, alias, b),
+
+ (&TyKind::InferenceVar(var, kind), ty_data) => {
+ let ty = ty_data.clone().intern(interner);
+ self.relate_var_ty(variance, var, kind, &ty)
+ }
+ (ty_data, &TyKind::InferenceVar(var, kind)) => {
+ // We need to invert the variance if inference var is `b` because we pass it in
+ // as `a` to relate_var_ty
+ let ty = ty_data.clone().intern(interner);
+ self.relate_var_ty(variance.invert(), var, kind, &ty)
+ }
+
+ // This would correspond to unifying a `fn` type with a non-fn
+ // type in Rust; error.
+ (&TyKind::Function(_), _) | (_, &TyKind::Function(_)) => Err(NoSolution),
+
+ // Cannot unify (e.g.) some struct type `Foo` and a placeholder like `T`
+ (_, &TyKind::Placeholder(_)) | (&TyKind::Placeholder(_), _) => Err(NoSolution),
+
+ // Cannot unify `dyn Trait` with things like structs or placeholders
+ (_, &TyKind::Dyn(_)) | (&TyKind::Dyn(_), _) => Err(NoSolution),
+
+ (TyKind::Adt(id_a, substitution_a), TyKind::Adt(id_b, substitution_b)) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ Some(self.unification_database().adt_variance(*id_a)),
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (
+ TyKind::AssociatedType(id_a, substitution_a),
+ TyKind::AssociatedType(id_b, substitution_b),
+ ) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ None, // TODO: AssociatedType variances?
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (TyKind::Scalar(scalar_a), TyKind::Scalar(scalar_b)) => {
+ Zip::zip_with(self, variance, scalar_a, scalar_b)
+ }
+ (TyKind::Str, TyKind::Str) => Ok(()),
+ (TyKind::Tuple(arity_a, substitution_a), TyKind::Tuple(arity_b, substitution_b)) => {
+ if arity_a != arity_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ Some(Variances::from_iter(
+ self.interner,
+ std::iter::repeat(Variance::Covariant).take(*arity_a),
+ )),
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (
+ TyKind::OpaqueType(id_a, substitution_a),
+ TyKind::OpaqueType(id_b, substitution_b),
+ ) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ None,
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => Zip::zip_with(self, variance, ty_a, ty_b),
+ (TyKind::FnDef(id_a, substitution_a), TyKind::FnDef(id_b, substitution_b)) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ Some(self.unification_database().fn_def_variance(*id_a)),
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (
+ TyKind::Ref(mutability_a, lifetime_a, ty_a),
+ TyKind::Ref(mutability_b, lifetime_b, ty_b),
+ ) => {
+ if mutability_a != mutability_b {
+ return Err(NoSolution);
+ }
+ // The lifetime is `Contravariant`
+ Zip::zip_with(
+ self,
+ variance.xform(Variance::Contravariant),
+ lifetime_a,
+ lifetime_b,
+ )?;
+ // The type is `Covariant` when not mut, `Invariant` otherwise
+ let output_variance = match mutability_a {
+ Mutability::Not => Variance::Covariant,
+ Mutability::Mut => Variance::Invariant,
+ };
+ Zip::zip_with(self, variance.xform(output_variance), ty_a, ty_b)
+ }
+ (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b)) => {
+ if mutability_a != mutability_b {
+ return Err(NoSolution);
+ }
+ let ty_variance = match mutability_a {
+ Mutability::Not => Variance::Covariant,
+ Mutability::Mut => Variance::Invariant,
+ };
+ Zip::zip_with(self, variance.xform(ty_variance), ty_a, ty_b)
+ }
+ (TyKind::Never, TyKind::Never) => Ok(()),
+ (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) => {
+ Zip::zip_with(self, variance, ty_a, ty_b)?;
+ Zip::zip_with(self, variance, const_a, const_b)
+ }
+ (TyKind::Closure(id_a, substitution_a), TyKind::Closure(id_b, substitution_b)) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ None,
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (TyKind::Generator(id_a, substitution_a), TyKind::Generator(id_b, substitution_b)) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ None,
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (
+ TyKind::GeneratorWitness(id_a, substitution_a),
+ TyKind::GeneratorWitness(id_b, substitution_b),
+ ) => {
+ if id_a != id_b {
+ return Err(NoSolution);
+ }
+ self.zip_substs(
+ variance,
+ None,
+ substitution_a.as_slice(interner),
+ substitution_b.as_slice(interner),
+ )
+ }
+ (TyKind::Foreign(id_a), TyKind::Foreign(id_b)) => {
+ Zip::zip_with(self, variance, id_a, id_b)
+ }
+ (TyKind::Error, TyKind::Error) => Ok(()),
+
+ (_, _) => Err(NoSolution),
+ }
+ }
+
+ /// Unify two inference variables
+ #[instrument(level = "debug", skip(self))]
+ fn unify_var_var(&mut self, a: InferenceVar, b: InferenceVar) -> Fallible<()> {
+ let var1 = EnaVariable::from(a);
+ let var2 = EnaVariable::from(b);
+ self.table
+ .unify
+ .unify_var_var(var1, var2)
+ .expect("unification of two unbound variables cannot fail");
+ Ok(())
+ }
+
+ /// Unify a general inference variable with a specific inference variable
+ /// (type kind is not `General`). For example, unify a `TyVariableKind::General`
+ /// inference variable with a `TyVariableKind::Integer` variable, resulting in the
+ /// general inference variable narrowing to an integer variable.
+
+ #[instrument(level = "debug", skip(self))]
+ fn unify_general_var_specific_ty(
+ &mut self,
+ general_var: InferenceVar,
+ specific_ty: Ty<I>,
+ ) -> Fallible<()> {
+ self.table
+ .unify
+ .unify_var_value(
+ general_var,
+ InferenceValue::from_ty(self.interner, specific_ty),
+ )
+ .unwrap();
+
+ Ok(())
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn relate_binders<'a, T>(
+ &mut self,
+ variance: Variance,
+ a: &Binders<T>,
+ b: &Binders<T>,
+ ) -> Fallible<()>
+ where
+ T: Clone + TypeFoldable<I> + HasInterner<Interner = I> + Zip<I>,
+ 't: 'a,
+ {
+ // for<'a...> T == for<'b...> U
+ //
+ // if:
+ //
+ // for<'a...> exists<'b...> T == U &&
+ // for<'b...> exists<'a...> T == U
+
+ // for<'a...> T <: for<'b...> U
+ //
+ // if
+ //
+ // for<'b...> exists<'a...> T <: U
+
+ let interner = self.interner;
+
+ if let Variance::Invariant | Variance::Contravariant = variance {
+ let a_universal = self
+ .table
+ .instantiate_binders_universally(interner, a.clone());
+ let b_existential = self
+ .table
+ .instantiate_binders_existentially(interner, b.clone());
+ Zip::zip_with(self, Variance::Contravariant, &a_universal, &b_existential)?;
+ }
+
+ if let Variance::Invariant | Variance::Covariant = variance {
+ let b_universal = self
+ .table
+ .instantiate_binders_universally(interner, b.clone());
+ let a_existential = self
+ .table
+ .instantiate_binders_existentially(interner, a.clone());
+ Zip::zip_with(self, Variance::Covariant, &a_existential, &b_universal)?;
+ }
+
+ Ok(())
+ }
+
+ /// Relate an alias like `<T as Trait>::Item` or `impl Trait` with some other
+ /// type `ty`. If the variance is `Invariant`, creates a goal like
+ ///
+ /// ```notrust
+ /// AliasEq(<T as Trait>::Item = U) // associated type projection
+ /// AliasEq(impl Trait = U) // impl trait
+ /// ```
+ /// Otherwise, this creates a new variable `?X`, creates a goal like
+ /// ```notrust
+ /// AliasEq(Alias = ?X)
+ /// ```
+ /// and relates `?X` and `ty`.
+ #[instrument(level = "debug", skip(self))]
+ fn relate_alias_ty(
+ &mut self,
+ variance: Variance,
+ alias: &AliasTy<I>,
+ ty: &Ty<I>,
+ ) -> Fallible<()> {
+ let interner = self.interner;
+ match variance {
+ Variance::Invariant => {
+ self.goals.push(InEnvironment::new(
+ self.environment,
+ AliasEq {
+ alias: alias.clone(),
+ ty: ty.clone(),
+ }
+ .cast(interner),
+ ));
+ Ok(())
+ }
+ Variance::Covariant | Variance::Contravariant => {
+ let var = self
+ .table
+ .new_variable(UniverseIndex::root())
+ .to_ty(interner);
+ self.goals.push(InEnvironment::new(
+ self.environment,
+ AliasEq {
+ alias: alias.clone(),
+ ty: var.clone(),
+ }
+ .cast(interner),
+ ));
+ self.relate_ty_ty(variance, &var, ty)
+ }
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn generalize_ty(
+ &mut self,
+ ty: &Ty<I>,
+ universe_index: UniverseIndex,
+ variance: Variance,
+ ) -> Ty<I> {
+ let interner = self.interner;
+ match ty.kind(interner) {
+ TyKind::Adt(id, substitution) => {
+ let variances = if matches!(variance, Variance::Invariant) {
+ None
+ } else {
+ Some(self.unification_database().adt_variance(*id))
+ };
+ let get_variance = |i| {
+ variances
+ .as_ref()
+ .map(|v| v.as_slice(interner)[i])
+ .unwrap_or(Variance::Invariant)
+ };
+ TyKind::Adt(
+ *id,
+ self.generalize_substitution(substitution, universe_index, get_variance),
+ )
+ .intern(interner)
+ }
+ TyKind::AssociatedType(id, substitution) => TyKind::AssociatedType(
+ *id,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::Scalar(scalar) => TyKind::Scalar(*scalar).intern(interner),
+ TyKind::Str => TyKind::Str.intern(interner),
+ TyKind::Tuple(arity, substitution) => TyKind::Tuple(
+ *arity,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::OpaqueType(id, substitution) => TyKind::OpaqueType(
+ *id,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::Slice(ty) => {
+ TyKind::Slice(self.generalize_ty(ty, universe_index, variance)).intern(interner)
+ }
+ TyKind::FnDef(id, substitution) => {
+ let variances = if matches!(variance, Variance::Invariant) {
+ None
+ } else {
+ Some(self.unification_database().fn_def_variance(*id))
+ };
+ let get_variance = |i| {
+ variances
+ .as_ref()
+ .map(|v| v.as_slice(interner)[i])
+ .unwrap_or(Variance::Invariant)
+ };
+ TyKind::FnDef(
+ *id,
+ self.generalize_substitution(substitution, universe_index, get_variance),
+ )
+ .intern(interner)
+ }
+ TyKind::Ref(mutability, lifetime, ty) => {
+ let lifetime_variance = variance.xform(Variance::Contravariant);
+ let ty_variance = match mutability {
+ Mutability::Not => Variance::Covariant,
+ Mutability::Mut => Variance::Invariant,
+ };
+ TyKind::Ref(
+ *mutability,
+ self.generalize_lifetime(lifetime, universe_index, lifetime_variance),
+ self.generalize_ty(ty, universe_index, ty_variance),
+ )
+ .intern(interner)
+ }
+ TyKind::Raw(mutability, ty) => {
+ let ty_variance = match mutability {
+ Mutability::Not => Variance::Covariant,
+ Mutability::Mut => Variance::Invariant,
+ };
+ TyKind::Raw(
+ *mutability,
+ self.generalize_ty(ty, universe_index, ty_variance),
+ )
+ .intern(interner)
+ }
+ TyKind::Never => TyKind::Never.intern(interner),
+ TyKind::Array(ty, const_) => TyKind::Array(
+ self.generalize_ty(ty, universe_index, variance),
+ self.generalize_const(const_, universe_index),
+ )
+ .intern(interner),
+ TyKind::Closure(id, substitution) => TyKind::Closure(
+ *id,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::Generator(id, substitution) => TyKind::Generator(
+ *id,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::GeneratorWitness(id, substitution) => TyKind::GeneratorWitness(
+ *id,
+ self.generalize_substitution(substitution, universe_index, |_| variance),
+ )
+ .intern(interner),
+ TyKind::Foreign(id) => TyKind::Foreign(*id).intern(interner),
+ TyKind::Error => TyKind::Error.intern(interner),
+ TyKind::Dyn(dyn_ty) => {
+ let DynTy { bounds, lifetime } = dyn_ty;
+ let lifetime = self.generalize_lifetime(
+ lifetime,
+ universe_index,
+ variance.xform(Variance::Contravariant),
+ );
+
+ let bounds = bounds.map_ref(|value| {
+ let iter = value.iter(interner).map(|sub_var| {
+ sub_var.map_ref(|clause| {
+ match clause {
+ WhereClause::Implemented(trait_ref) => {
+ let TraitRef {
+ ref substitution,
+ trait_id,
+ } = *trait_ref;
+ let substitution = self.generalize_substitution_skip_self(
+ substitution,
+ universe_index,
+ |_| Some(variance),
+ );
+ WhereClause::Implemented(TraitRef {
+ substitution,
+ trait_id,
+ })
+ }
+ WhereClause::AliasEq(alias_eq) => {
+ let AliasEq { alias, ty: _ } = alias_eq;
+ let alias = match alias {
+ AliasTy::Opaque(opaque_ty) => {
+ let OpaqueTy {
+ ref substitution,
+ opaque_ty_id,
+ } = *opaque_ty;
+ let substitution = self.generalize_substitution(
+ substitution,
+ universe_index,
+ |_| variance,
+ );
+ AliasTy::Opaque(OpaqueTy {
+ substitution,
+ opaque_ty_id,
+ })
+ }
+ AliasTy::Projection(projection_ty) => {
+ let ProjectionTy {
+ ref substitution,
+ associated_ty_id,
+ } = *projection_ty;
+ // TODO: We should be skipping "self", which
+ // would be the first element of
+ // "trait_params" if we had a
+ // `RustIrDatabase` to call
+ // `split_projection` on...
+ // let (assoc_ty_datum, trait_params, assoc_type_params) = s.db().split_projection(&self);
+ let substitution = self.generalize_substitution(
+ substitution,
+ universe_index,
+ |_| variance,
+ );
+ AliasTy::Projection(ProjectionTy {
+ substitution,
+ associated_ty_id,
+ })
+ }
+ };
+ let ty =
+ self.table.new_variable(universe_index).to_ty(interner);
+ WhereClause::AliasEq(AliasEq { alias, ty })
+ }
+ WhereClause::TypeOutlives(_) => {
+ let lifetime_var = self.table.new_variable(universe_index);
+ let lifetime = lifetime_var.to_lifetime(interner);
+ let ty_var = self.table.new_variable(universe_index);
+ let ty = ty_var.to_ty(interner);
+ WhereClause::TypeOutlives(TypeOutlives { ty, lifetime })
+ }
+ WhereClause::LifetimeOutlives(_) => {
+ unreachable!("dyn Trait never contains LifetimeOutlive bounds")
+ }
+ }
+ })
+ });
+ QuantifiedWhereClauses::from_iter(interner, iter)
+ });
+
+ TyKind::Dyn(DynTy { bounds, lifetime }).intern(interner)
+ }
+ TyKind::Function(fn_ptr) => {
+ let FnPointer {
+ num_binders,
+ sig,
+ ref substitution,
+ } = *fn_ptr;
+
+ let len = substitution.0.len(interner);
+ let vars = substitution.0.iter(interner).enumerate().map(|(i, var)| {
+ if i < len - 1 {
+ self.generalize_generic_var(
+ var,
+ universe_index,
+ variance.xform(Variance::Contravariant),
+ )
+ } else {
+ self.generalize_generic_var(
+ substitution.0.as_slice(interner).last().unwrap(),
+ universe_index,
+ variance,
+ )
+ }
+ });
+
+ let substitution = FnSubst(Substitution::from_iter(interner, vars));
+
+ TyKind::Function(FnPointer {
+ num_binders,
+ sig,
+ substitution,
+ })
+ .intern(interner)
+ }
+ TyKind::Placeholder(_) | TyKind::BoundVar(_) => {
+ debug!("just generalizing to the ty itself: {:?}", ty);
+ // BoundVar and PlaceHolder have no internal values to be
+ // generic over, so we just relate directly to it
+ ty.clone()
+ }
+ TyKind::Alias(_) => {
+ let ena_var = self.table.new_variable(universe_index);
+ ena_var.to_ty(interner)
+ }
+ TyKind::InferenceVar(_var, kind) => {
+ if matches!(kind, TyVariableKind::Integer | TyVariableKind::Float) {
+ ty.clone()
+ } else if let Some(ty) = self.table.normalize_ty_shallow(interner, ty) {
+ self.generalize_ty(&ty, universe_index, variance)
+ } else if matches!(variance, Variance::Invariant) {
+ ty.clone()
+ } else {
+ let ena_var = self.table.new_variable(universe_index);
+ ena_var.to_ty(interner)
+ }
+ }
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn generalize_lifetime(
+ &mut self,
+ lifetime: &Lifetime<I>,
+ universe_index: UniverseIndex,
+ variance: Variance,
+ ) -> Lifetime<I> {
+ if matches!(lifetime.data(self.interner), LifetimeData::BoundVar(_))
+ || matches!(variance, Variance::Invariant)
+ {
+ lifetime.clone()
+ } else {
+ self.table
+ .new_variable(universe_index)
+ .to_lifetime(self.interner)
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn generalize_const(&mut self, const_: &Const<I>, universe_index: UniverseIndex) -> Const<I> {
+ let data = const_.data(self.interner);
+ if matches!(data.value, ConstValue::BoundVar(_)) {
+ const_.clone()
+ } else {
+ self.table
+ .new_variable(universe_index)
+ .to_const(self.interner, data.ty.clone())
+ }
+ }
+
+ fn generalize_generic_var(
+ &mut self,
+ sub_var: &GenericArg<I>,
+ universe_index: UniverseIndex,
+ variance: Variance,
+ ) -> GenericArg<I> {
+ let interner = self.interner;
+ (match sub_var.data(interner) {
+ GenericArgData::Ty(ty) => {
+ GenericArgData::Ty(self.generalize_ty(ty, universe_index, variance))
+ }
+ GenericArgData::Lifetime(lifetime) => GenericArgData::Lifetime(
+ self.generalize_lifetime(lifetime, universe_index, variance),
+ ),
+ GenericArgData::Const(const_value) => {
+ GenericArgData::Const(self.generalize_const(const_value, universe_index))
+ }
+ })
+ .intern(interner)
+ }
+
+ /// Generalizes all but the first
+ #[instrument(level = "debug", skip(self, get_variance))]
+ fn generalize_substitution_skip_self<F: Fn(usize) -> Option<Variance>>(
+ &mut self,
+ substitution: &Substitution<I>,
+ universe_index: UniverseIndex,
+ get_variance: F,
+ ) -> Substitution<I> {
+ let interner = self.interner;
+ let vars = substitution.iter(interner).enumerate().map(|(i, sub_var)| {
+ if i == 0 {
+ sub_var.clone()
+ } else {
+ let variance = get_variance(i).unwrap_or(Variance::Invariant);
+ self.generalize_generic_var(sub_var, universe_index, variance)
+ }
+ });
+ Substitution::from_iter(interner, vars)
+ }
+
+ #[instrument(level = "debug", skip(self, get_variance))]
+ fn generalize_substitution<F: Fn(usize) -> Variance>(
+ &mut self,
+ substitution: &Substitution<I>,
+ universe_index: UniverseIndex,
+ get_variance: F,
+ ) -> Substitution<I> {
+ let interner = self.interner;
+ let vars = substitution.iter(interner).enumerate().map(|(i, sub_var)| {
+ let variance = get_variance(i);
+ self.generalize_generic_var(sub_var, universe_index, variance)
+ });
+
+ Substitution::from_iter(interner, vars)
+ }
+
+ /// Unify an inference variable `var` with some non-inference
+ /// variable `ty`, just bind `var` to `ty`. But we must enforce two conditions:
+ ///
+ /// - `var` does not appear inside of `ty` (the standard `OccursCheck`)
+ /// - `ty` does not reference anything in a lifetime that could not be named in `var`
+ /// (the extended `OccursCheck` created to handle universes)
+ #[instrument(level = "debug", skip(self))]
+ fn relate_var_ty(
+ &mut self,
+ variance: Variance,
+ var: InferenceVar,
+ var_kind: TyVariableKind,
+ ty: &Ty<I>,
+ ) -> Fallible<()> {
+ let interner = self.interner;
+
+ match (var_kind, ty.is_integer(interner), ty.is_float(interner)) {
+ // General inference variables can unify with any type
+ (TyVariableKind::General, _, _)
+ // Integer inference variables can only unify with integer types
+ | (TyVariableKind::Integer, true, _)
+ // Float inference variables can only unify with float types
+ | (TyVariableKind::Float, _, true) => {
+ },
+ _ => return Err(NoSolution),
+ }
+
+ let var = EnaVariable::from(var);
+
+ // Determine the universe index associated with this
+ // variable. This is basically a count of the number of
+ // `forall` binders that had been introduced at the point
+ // this variable was created -- though it may change over time
+ // as the variable is unified.
+ let universe_index = self.table.universe_of_unbound_var(var);
+ // let universe_index = self.table.max_universe();
+
+ debug!("relate_var_ty: universe index of var: {:?}", universe_index);
+
+ debug!("trying fold_with on {:?}", ty);
+ let ty1 = ty
+ .clone()
+ .try_fold_with(
+ &mut OccursCheck::new(self, var, universe_index),
+ DebruijnIndex::INNERMOST,
+ )
+ .map_err(|e| {
+ debug!("failed to fold {:?}", ty);
+ e
+ })?;
+
+ // "Generalize" types. This ensures that we aren't accidentally forcing
+ // too much onto `var`. Instead of directly setting `var` equal to `ty`,
+ // we just take the outermost structure we _know_ `var` holds, and then
+ // apply that to `ty`. This involves creating new inference vars for
+ // everything inside `var`, then calling `relate_ty_ty` to relate those
+ // inference vars to the things they generalized with the correct
+ // variance.
+
+ // The main problem this solves is that lifetime relationships are
+ // relationships, not just eq ones. So when solving &'a u32 <: U,
+ // generalizing we would end up with U = &'a u32. Instead, we want
+ // U = &'b u32, with a lifetime constraint 'a <: 'b. This matters
+ // especially when solving multiple constraints - for example, &'a u32
+ // <: U, &'b u32 <: U (where without generalizing, we'd end up with 'a
+ // <: 'b, where we really want 'a <: 'c, 'b <: 'c for some 'c).
+
+ // Example operation: consider `ty` as `&'x SomeType`. To generalize
+ // this, we create two new vars `'0` and `1`. Then we relate `var` with
+ // `&'0 1` and `&'0 1` with `&'x SomeType`. The second relation will
+ // recurse, and we'll end up relating `'0` with `'x` and `1` with `SomeType`.
+ let generalized_val = self.generalize_ty(&ty1, universe_index, variance);
+
+ debug!("var {:?} generalized to {:?}", var, generalized_val);
+
+ self.table
+ .unify
+ .unify_var_value(
+ var,
+ InferenceValue::from_ty(interner, generalized_val.clone()),
+ )
+ .unwrap();
+ debug!("var {:?} set to {:?}", var, generalized_val);
+
+ self.relate_ty_ty(variance, &generalized_val, &ty1)?;
+
+ debug!(
+ "generalized version {:?} related to original {:?}",
+ generalized_val, ty1
+ );
+
+ Ok(())
+ }
+
+ fn relate_lifetime_lifetime(
+ &mut self,
+ variance: Variance,
+ a: &Lifetime<I>,
+ b: &Lifetime<I>,
+ ) -> Fallible<()> {
+ let interner = self.interner;
+
+ let n_a = self.table.normalize_lifetime_shallow(interner, a);
+ let n_b = self.table.normalize_lifetime_shallow(interner, b);
+ let a = n_a.as_ref().unwrap_or(a);
+ let b = n_b.as_ref().unwrap_or(b);
+
+ debug_span!("relate_lifetime_lifetime", ?variance, ?a, ?b);
+
+ match (a.data(interner), b.data(interner)) {
+ (&LifetimeData::InferenceVar(var_a), &LifetimeData::InferenceVar(var_b)) => {
+ let var_a = EnaVariable::from(var_a);
+ let var_b = EnaVariable::from(var_b);
+ debug!(?var_a, ?var_b);
+ self.table.unify.unify_var_var(var_a, var_b).unwrap();
+ Ok(())
+ }
+
+ (
+ &LifetimeData::InferenceVar(a_var),
+ &LifetimeData::Placeholder(PlaceholderIndex { ui, .. }),
+ ) => self.unify_lifetime_var(variance, a_var, b, ui),
+
+ (
+ &LifetimeData::Placeholder(PlaceholderIndex { ui, .. }),
+ &LifetimeData::InferenceVar(b_var),
+ ) => self.unify_lifetime_var(variance.invert(), b_var, a, ui),
+
+ (&LifetimeData::InferenceVar(a_var), &LifetimeData::Erased)
+ | (&LifetimeData::InferenceVar(a_var), &LifetimeData::Static) => {
+ self.unify_lifetime_var(variance, a_var, b, UniverseIndex::root())
+ }
+
+ (&LifetimeData::Erased, &LifetimeData::InferenceVar(b_var))
+ | (&LifetimeData::Static, &LifetimeData::InferenceVar(b_var)) => {
+ self.unify_lifetime_var(variance.invert(), b_var, a, UniverseIndex::root())
+ }
+
+ (&LifetimeData::Static, &LifetimeData::Static)
+ | (&LifetimeData::Erased, &LifetimeData::Erased) => Ok(()),
+
+ (&LifetimeData::Static, &LifetimeData::Placeholder(_))
+ | (&LifetimeData::Static, &LifetimeData::Erased)
+ | (&LifetimeData::Placeholder(_), &LifetimeData::Static)
+ | (&LifetimeData::Placeholder(_), &LifetimeData::Placeholder(_))
+ | (&LifetimeData::Placeholder(_), &LifetimeData::Erased)
+ | (&LifetimeData::Erased, &LifetimeData::Static)
+ | (&LifetimeData::Erased, &LifetimeData::Placeholder(_)) => {
+ if a != b {
+ self.push_lifetime_outlives_goals(variance, a.clone(), b.clone());
+ Ok(())
+ } else {
+ Ok(())
+ }
+ }
+
+ (LifetimeData::BoundVar(_), _) | (_, LifetimeData::BoundVar(_)) => panic!(
+ "unification encountered bound variable: a={:?} b={:?}",
+ a, b
+ ),
+
+ (LifetimeData::Phantom(..), _) | (_, LifetimeData::Phantom(..)) => unreachable!(),
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn unify_lifetime_var(
+ &mut self,
+ variance: Variance,
+ var: InferenceVar,
+ value: &Lifetime<I>,
+ value_ui: UniverseIndex,
+ ) -> Fallible<()> {
+ let var = EnaVariable::from(var);
+ let var_ui = self.table.universe_of_unbound_var(var);
+ if var_ui.can_see(value_ui) && matches!(variance, Variance::Invariant) {
+ debug!("{:?} in {:?} can see {:?}; unifying", var, var_ui, value_ui);
+ self.table
+ .unify
+ .unify_var_value(
+ var,
+ InferenceValue::from_lifetime(self.interner, value.clone()),
+ )
+ .unwrap();
+ Ok(())
+ } else {
+ debug!(
+ "{:?} in {:?} cannot see {:?}; pushing constraint",
+ var, var_ui, value_ui
+ );
+ self.push_lifetime_outlives_goals(
+ variance,
+ var.to_lifetime(self.interner),
+ value.clone(),
+ );
+ Ok(())
+ }
+ }
+
+ fn relate_const_const<'a>(
+ &mut self,
+ variance: Variance,
+ a: &'a Const<I>,
+ b: &'a Const<I>,
+ ) -> Fallible<()> {
+ let interner = self.interner;
+
+ let n_a = self.table.normalize_const_shallow(interner, a);
+ let n_b = self.table.normalize_const_shallow(interner, b);
+ let a = n_a.as_ref().unwrap_or(a);
+ let b = n_b.as_ref().unwrap_or(b);
+
+ debug_span!("relate_const_const", ?variance, ?a, ?b);
+
+ let ConstData {
+ ty: a_ty,
+ value: a_val,
+ } = a.data(interner);
+ let ConstData {
+ ty: b_ty,
+ value: b_val,
+ } = b.data(interner);
+
+ self.relate_ty_ty(variance, a_ty, b_ty)?;
+
+ match (a_val, b_val) {
+ // Unifying two inference variables: unify them in the underlying
+ // ena table.
+ (&ConstValue::InferenceVar(var1), &ConstValue::InferenceVar(var2)) => {
+ debug!(?var1, ?var2, "relate_ty_ty");
+ let var1 = EnaVariable::from(var1);
+ let var2 = EnaVariable::from(var2);
+ self.table
+ .unify
+ .unify_var_var(var1, var2)
+ .expect("unification of two unbound variables cannot fail");
+ Ok(())
+ }
+
+ // Unifying an inference variables with a non-inference variable.
+ (&ConstValue::InferenceVar(var), &ConstValue::Concrete(_))
+ | (&ConstValue::InferenceVar(var), &ConstValue::Placeholder(_)) => {
+ debug!(?var, ty=?b, "unify_var_ty");
+ self.unify_var_const(var, b)
+ }
+
+ (&ConstValue::Concrete(_), &ConstValue::InferenceVar(var))
+ | (&ConstValue::Placeholder(_), &ConstValue::InferenceVar(var)) => {
+ debug!(?var, ty=?a, "unify_var_ty");
+ self.unify_var_const(var, a)
+ }
+
+ (&ConstValue::Placeholder(p1), &ConstValue::Placeholder(p2)) => {
+ Zip::zip_with(self, variance, &p1, &p2)
+ }
+
+ (&ConstValue::Concrete(ref ev1), &ConstValue::Concrete(ref ev2)) => {
+ if ev1.const_eq(a_ty, ev2, interner) {
+ Ok(())
+ } else {
+ Err(NoSolution)
+ }
+ }
+
+ (&ConstValue::Concrete(_), &ConstValue::Placeholder(_))
+ | (&ConstValue::Placeholder(_), &ConstValue::Concrete(_)) => Err(NoSolution),
+
+ (ConstValue::BoundVar(_), _) | (_, ConstValue::BoundVar(_)) => panic!(
+ "unification encountered bound variable: a={:?} b={:?}",
+ a, b
+ ),
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn unify_var_const(&mut self, var: InferenceVar, c: &Const<I>) -> Fallible<()> {
+ let interner = self.interner;
+ let var = EnaVariable::from(var);
+
+ // Determine the universe index associated with this
+ // variable. This is basically a count of the number of
+ // `forall` binders that had been introduced at the point
+ // this variable was created -- though it may change over time
+ // as the variable is unified.
+ let universe_index = self.table.universe_of_unbound_var(var);
+
+ let c1 = c.clone().try_fold_with(
+ &mut OccursCheck::new(self, var, universe_index),
+ DebruijnIndex::INNERMOST,
+ )?;
+
+ debug!("unify_var_const: var {:?} set to {:?}", var, c1);
+ self.table
+ .unify
+ .unify_var_value(var, InferenceValue::from_const(interner, c1))
+ .unwrap();
+
+ Ok(())
+ }
+
+ /// Relate `a`, `b` such that if `variance = Covariant`, `a` is a subtype of
+ /// `b` and thus `a` must outlive `b`.
+ fn push_lifetime_outlives_goals(&mut self, variance: Variance, a: Lifetime<I>, b: Lifetime<I>) {
+ debug!(
+ "pushing lifetime outlives goals for a={:?} b={:?} with variance {:?}",
+ a, b, variance
+ );
+ if matches!(variance, Variance::Invariant | Variance::Contravariant) {
+ self.goals.push(InEnvironment::new(
+ self.environment,
+ WhereClause::LifetimeOutlives(LifetimeOutlives {
+ a: a.clone(),
+ b: b.clone(),
+ })
+ .cast(self.interner),
+ ));
+ }
+ if matches!(variance, Variance::Invariant | Variance::Covariant) {
+ self.goals.push(InEnvironment::new(
+ self.environment,
+ WhereClause::LifetimeOutlives(LifetimeOutlives { a: b, b: a }).cast(self.interner),
+ ));
+ }
+ }
+
+ /// Pushes a goal of `a` being a subtype of `b`.
+ fn push_subtype_goal(&mut self, a: Ty<I>, b: Ty<I>) {
+ let subtype_goal = GoalData::SubtypeGoal(SubtypeGoal { a, b }).intern(self.interner());
+ self.goals
+ .push(InEnvironment::new(self.environment, subtype_goal));
+ }
+}
+
+impl<'i, I: Interner> Zipper<I> for Unifier<'i, I> {
+ fn zip_tys(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
+ debug!("zip_tys {:?}, {:?}, {:?}", variance, a, b);
+ self.relate_ty_ty(variance, a, b)
+ }
+
+ fn zip_lifetimes(
+ &mut self,
+ variance: Variance,
+ a: &Lifetime<I>,
+ b: &Lifetime<I>,
+ ) -> Fallible<()> {
+ self.relate_lifetime_lifetime(variance, a, b)
+ }
+
+ fn zip_consts(&mut self, variance: Variance, a: &Const<I>, b: &Const<I>) -> Fallible<()> {
+ self.relate_const_const(variance, a, b)
+ }
+
+ fn zip_binders<T>(&mut self, variance: Variance, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
+ where
+ T: Clone + HasInterner<Interner = I> + Zip<I> + TypeFoldable<I>,
+ {
+ // The binders that appear in types (apart from quantified types, which are
+ // handled in `unify_ty`) appear as part of `dyn Trait` and `impl Trait` types.
+ //
+ // They come in two varieties:
+ //
+ // * The existential binder from `dyn Trait` / `impl Trait`
+ // (representing the hidden "self" type)
+ // * The `for<..>` binders from higher-ranked traits.
+ //
+ // In both cases we can use the same `relate_binders` routine.
+
+ self.relate_binders(variance, a, b)
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+
+ fn unification_database(&self) -> &dyn UnificationDatabase<I> {
+ self.db
+ }
+}
+
+struct OccursCheck<'u, 't, I: Interner> {
+ unifier: &'u mut Unifier<'t, I>,
+ var: EnaVariable<I>,
+ universe_index: UniverseIndex,
+}
+
+impl<'u, 't, I: Interner> OccursCheck<'u, 't, I> {
+ fn new(
+ unifier: &'u mut Unifier<'t, I>,
+ var: EnaVariable<I>,
+ universe_index: UniverseIndex,
+ ) -> Self {
+ OccursCheck {
+ unifier,
+ var,
+ universe_index,
+ }
+ }
+}
+
+impl<'i, I: Interner> FallibleTypeFolder<I> for OccursCheck<'_, 'i, I> {
+ type Error = NoSolution;
+
+ fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<I, Error = Self::Error> {
+ self
+ }
+
+ fn try_fold_free_placeholder_ty(
+ &mut self,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Fallible<Ty<I>> {
+ let interner = self.interner();
+ if self.universe_index < universe.ui {
+ debug!(
+ "OccursCheck aborting because self.universe_index ({:?}) < universe.ui ({:?})",
+ self.universe_index, universe.ui
+ );
+ Err(NoSolution)
+ } else {
+ Ok(universe.to_ty(interner)) // no need to shift, not relative to depth
+ }
+ }
+
+ fn try_fold_free_placeholder_const(
+ &mut self,
+ ty: Ty<I>,
+ universe: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Fallible<Const<I>> {
+ let interner = self.interner();
+ if self.universe_index < universe.ui {
+ Err(NoSolution)
+ } else {
+ Ok(universe.to_const(interner, ty)) // no need to shift, not relative to depth
+ }
+ }
+
+ #[instrument(level = "debug", skip(self))]
+ fn try_fold_free_placeholder_lifetime(
+ &mut self,
+ ui: PlaceholderIndex,
+ _outer_binder: DebruijnIndex,
+ ) -> Fallible<Lifetime<I>> {
+ let interner = self.interner();
+ if self.universe_index < ui.ui {
+ // Scenario is like:
+ //
+ // exists<T> forall<'b> ?T = Foo<'b>
+ //
+ // unlike with a type variable, this **might** be
+ // ok. Ultimately it depends on whether the
+ // `forall` also introduced relations to lifetimes
+ // nameable in T. To handle that, we introduce a
+ // fresh region variable `'x` in same universe as `T`
+ // and add a side-constraint that `'x = 'b`:
+ //
+ // exists<'x> forall<'b> ?T = Foo<'x>, where 'x = 'b
+
+ let tick_x = self.unifier.table.new_variable(self.universe_index);
+ self.unifier.push_lifetime_outlives_goals(
+ Variance::Invariant,
+ tick_x.to_lifetime(interner),
+ ui.to_lifetime(interner),
+ );
+ Ok(tick_x.to_lifetime(interner))
+ } else {
+ // If the `ui` is higher than `self.universe_index`, then we can name
+ // this lifetime, no problem.
+ Ok(ui.to_lifetime(interner)) // no need to shift, not relative to depth
+ }
+ }
+
+ fn try_fold_inference_ty(
+ &mut self,
+ var: InferenceVar,
+ kind: TyVariableKind,
+ _outer_binder: DebruijnIndex,
+ ) -> Fallible<Ty<I>> {
+ let interner = self.interner();
+ let var = EnaVariable::from(var);
+ match self.unifier.table.unify.probe_value(var) {
+ // If this variable already has a value, fold over that value instead.
+ InferenceValue::Bound(normalized_ty) => {
+ let normalized_ty = normalized_ty.assert_ty_ref(interner);
+ let normalized_ty = normalized_ty
+ .clone()
+ .try_fold_with(self, DebruijnIndex::INNERMOST)?;
+ assert!(!normalized_ty.needs_shift(interner));
+ Ok(normalized_ty)
+ }
+
+ // Otherwise, check the universe of the variable, and also
+ // check for cycles with `self.var` (which this will soon
+ // become the value of).
+ InferenceValue::Unbound(ui) => {
+ if self.unifier.table.unify.unioned(var, self.var) {
+ debug!(
+ "OccursCheck aborting because {:?} unioned with {:?}",
+ var, self.var,
+ );
+ return Err(NoSolution);
+ }
+
+ if self.universe_index < ui {
+ // Scenario is like:
+ //
+ // ?A = foo(?B)
+ //
+ // where ?A is in universe 0 and ?B is in universe 1.
+ // This is OK, if ?B is promoted to universe 0.
+ self.unifier
+ .table
+ .unify
+ .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
+ .unwrap();
+ }
+
+ Ok(var.to_ty_with_kind(interner, kind))
+ }
+ }
+ }
+
+ fn try_fold_inference_const(
+ &mut self,
+ ty: Ty<I>,
+ var: InferenceVar,
+ _outer_binder: DebruijnIndex,
+ ) -> Fallible<Const<I>> {
+ let interner = self.interner();
+ let var = EnaVariable::from(var);
+ match self.unifier.table.unify.probe_value(var) {
+ // If this variable already has a value, fold over that value instead.
+ InferenceValue::Bound(normalized_const) => {
+ let normalized_const = normalized_const.assert_const_ref(interner);
+ let normalized_const = normalized_const
+ .clone()
+ .try_fold_with(self, DebruijnIndex::INNERMOST)?;
+ assert!(!normalized_const.needs_shift(interner));
+ Ok(normalized_const)
+ }
+
+ // Otherwise, check the universe of the variable, and also
+ // check for cycles with `self.var` (which this will soon
+ // become the value of).
+ InferenceValue::Unbound(ui) => {
+ if self.unifier.table.unify.unioned(var, self.var) {
+ return Err(NoSolution);
+ }
+
+ if self.universe_index < ui {
+ // Scenario is like:
+ //
+ // forall<const A> exists<const B> ?C = Foo<B>
+ //
+ // where A is in universe 0 and B is in universe 1.
+ // This is OK, if B is promoted to universe 0.
+ self.unifier
+ .table
+ .unify
+ .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
+ .unwrap();
+ }
+
+ Ok(var.to_const(interner, ty))
+ }
+ }
+ }
+
+ fn try_fold_inference_lifetime(
+ &mut self,
+ var: InferenceVar,
+ outer_binder: DebruijnIndex,
+ ) -> Fallible<Lifetime<I>> {
+ // a free existentially bound region; find the
+ // inference variable it corresponds to
+ let interner = self.interner();
+ let var = EnaVariable::from(var);
+ match self.unifier.table.unify.probe_value(var) {
+ InferenceValue::Unbound(ui) => {
+ if self.universe_index < ui {
+ // Scenario is like:
+ //
+ // exists<T> forall<'b> exists<'a> ?T = Foo<'a>
+ //
+ // where ?A is in universe 0 and `'b` is in universe 1.
+ // This is OK, if `'b` is promoted to universe 0.
+ self.unifier
+ .table
+ .unify
+ .unify_var_value(var, InferenceValue::Unbound(self.universe_index))
+ .unwrap();
+ }
+ Ok(var.to_lifetime(interner))
+ }
+
+ InferenceValue::Bound(l) => {
+ let l = l.assert_lifetime_ref(interner);
+ let l = l.clone().try_fold_with(self, outer_binder)?;
+ assert!(!l.needs_shift(interner));
+ Ok(l)
+ }
+ }
+ }
+
+ fn forbid_free_vars(&self) -> bool {
+ true
+ }
+
+ fn interner(&self) -> I {
+ self.unifier.interner
+ }
+}
diff --git a/vendor/chalk-solve/src/infer/var.rs b/vendor/chalk-solve/src/infer/var.rs
new file mode 100644
index 000000000..3fbf92002
--- /dev/null
+++ b/vendor/chalk-solve/src/infer/var.rs
@@ -0,0 +1,152 @@
+use chalk_ir::cast::Cast;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use ena::unify::{UnifyKey, UnifyValue};
+use std::cmp::min;
+use std::fmt;
+use std::marker::PhantomData;
+use std::u32;
+
+/// Wrapper around `chalk_ir::InferenceVar` for coherence purposes.
+/// An inference variable represents an unknown term -- either a type
+/// or a lifetime. The variable itself is just an index into the
+/// unification table; the unification table maps it to an
+/// `InferenceValue`.
+///
+/// Inference variables can be in one of two states (represents by the variants
+/// of an `InferenceValue`):
+///
+/// - Unbound(`ui`). In this case, the value of the variable is not yet known. We carry
+/// along a universe index `ui` that tracks the universe in which the variable was
+/// created; this determines what names may appear in the variable's value.
+/// - In this state, we do **not** track the kind of this variable
+/// (i.e., whether it represents a type or a lifetime). There is
+/// no need: if it represents a lifetime, for example, then there
+/// should only ever be constraints that relate it to other
+/// lifetimes, or use it in lifetime position.
+/// - Bound. In this case, the value of the variable is known. We
+/// carry along the value. We discard the universe index in which
+/// the variable was created, since that was only needed to help us
+/// reject illegal values. Once the value of a variable is known, it
+/// can never change.
+/// - The value we actually store for variables is a
+/// `ir::GenericArg`, and hence it does carry along the kind of the
+/// variable via the enum variant. However, we should always know
+/// the kind of the variable from context, and hence we typically
+/// "downcast" the resulting variable using
+/// e.g. `value.ty().unwrap()`.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct EnaVariable<I: Interner> {
+ var: InferenceVar,
+ phantom: PhantomData<I>,
+}
+
+impl<I: Interner> From<InferenceVar> for EnaVariable<I> {
+ fn from(var: InferenceVar) -> EnaVariable<I> {
+ EnaVariable {
+ var,
+ phantom: PhantomData,
+ }
+ }
+}
+
+impl<I: Interner> From<EnaVariable<I>> for InferenceVar {
+ fn from(ena_var: EnaVariable<I>) -> InferenceVar {
+ ena_var.var
+ }
+}
+
+impl<I: Interner> EnaVariable<I> {
+ /// Convert this inference variable into a type. When using this
+ /// method, naturally you should know from context that the kind
+ /// of this inference variable is a type (we can't check it).
+ pub fn to_ty_with_kind(self, interner: I, kind: TyVariableKind) -> Ty<I> {
+ self.var.to_ty(interner, kind)
+ }
+
+ /// Same as `to_ty_with_kind`, but the kind is set to `TyVariableKind::General`.
+ /// This should be used instead of `to_ty_with_kind` when creating a new
+ /// inference variable (when the kind is not known).
+ pub fn to_ty(self, interner: I) -> Ty<I> {
+ self.var.to_ty(interner, TyVariableKind::General)
+ }
+
+ /// Convert this inference variable into a lifetime. When using this
+ /// method, naturally you should know from context that the kind
+ /// of this inference variable is a lifetime (we can't check it).
+ pub fn to_lifetime(self, interner: I) -> Lifetime<I> {
+ self.var.to_lifetime(interner)
+ }
+
+ /// Convert this inference variable into a const. When using this
+ /// method, naturally you should know from context that the kind
+ /// of this inference variable is a const (we can't check it).
+ pub fn to_const(self, interner: I, ty: Ty<I>) -> Const<I> {
+ self.var.to_const(interner, ty)
+ }
+}
+
+impl<I: Interner> UnifyKey for EnaVariable<I> {
+ type Value = InferenceValue<I>;
+
+ fn index(&self) -> u32 {
+ self.var.index()
+ }
+
+ fn from_index(u: u32) -> Self {
+ EnaVariable::from(InferenceVar::from(u))
+ }
+
+ fn tag() -> &'static str {
+ "EnaVariable"
+ }
+}
+
+/// The value of an inference variable. We start out as `Unbound` with a
+/// universe index; when the inference variable is assigned a value, it becomes
+/// bound and records that value. See `EnaVariable` for more details.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum InferenceValue<I: Interner> {
+ Unbound(UniverseIndex),
+ Bound(GenericArg<I>),
+}
+
+impl<I: Interner> InferenceValue<I> {
+ pub fn from_ty(interner: I, ty: Ty<I>) -> Self {
+ InferenceValue::Bound(ty.cast(interner))
+ }
+
+ pub fn from_lifetime(interner: I, lifetime: Lifetime<I>) -> Self {
+ InferenceValue::Bound(lifetime.cast(interner))
+ }
+
+ pub fn from_const(interner: I, constant: Const<I>) -> Self {
+ InferenceValue::Bound(constant.cast(interner))
+ }
+}
+
+impl<I: Interner> UnifyValue for InferenceValue<I> {
+ type Error = (InferenceValue<I>, InferenceValue<I>);
+
+ fn unify_values(
+ a: &InferenceValue<I>,
+ b: &InferenceValue<I>,
+ ) -> Result<InferenceValue<I>, (InferenceValue<I>, InferenceValue<I>)> {
+ match (a, b) {
+ (&InferenceValue::Unbound(ui_a), &InferenceValue::Unbound(ui_b)) => {
+ Ok(InferenceValue::Unbound(min(ui_a, ui_b)))
+ }
+ (bound @ &InferenceValue::Bound(_), &InferenceValue::Unbound(_))
+ | (&InferenceValue::Unbound(_), bound @ &InferenceValue::Bound(_)) => Ok(bound.clone()),
+ (&InferenceValue::Bound(_), &InferenceValue::Bound(_)) => {
+ panic!("we should not be asked to unify two bound things")
+ }
+ }
+ }
+}
+
+impl<I: Interner> fmt::Debug for EnaVariable<I> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ write!(fmt, "{:?}", self.var)
+ }
+}
diff --git a/vendor/chalk-solve/src/lib.rs b/vendor/chalk-solve/src/lib.rs
new file mode 100644
index 000000000..a870a0c49
--- /dev/null
+++ b/vendor/chalk-solve/src/lib.rs
@@ -0,0 +1,219 @@
+#![deny(rust_2018_idioms)]
+
+use crate::display::sanitize_debug_name;
+use crate::rust_ir::*;
+use chalk_ir::interner::Interner;
+
+use chalk_ir::*;
+use std::fmt::Debug;
+use std::sync::Arc;
+
+pub mod clauses;
+pub mod coherence;
+pub mod coinductive_goal;
+pub mod display;
+pub mod ext;
+pub mod goal_builder;
+pub mod infer;
+pub mod logging;
+pub mod logging_db;
+pub mod rust_ir;
+pub mod solve;
+pub mod split;
+pub mod wf;
+
+/// Trait representing access to a database of rust types.
+///
+/// # `*_name` methods
+///
+/// This trait has a number of `*_name` methods with default implementations.
+/// These are used in the implementation for [`LoggingRustIrDatabase`], so that
+/// when printing `.chalk` files equivalent to the data used, we can use real
+/// names.
+///
+/// The default implementations simply fall back to calling [`Interner`] debug
+/// methods, and printing `"UnknownN"` (where `N` is the demultiplexing integer)
+/// if those methods return `None`.
+///
+/// The [`display::sanitize_debug_name`] utility is used in the default
+/// implementations, and might be useful when providing custom implementations.
+///
+/// [`LoggingRustIrDatabase`]: crate::logging_db::LoggingRustIrDatabase
+/// [`display::sanitize_debug_name`]: crate::display::sanitize_debug_name
+/// [`Interner`]: Interner
+pub trait RustIrDatabase<I: Interner>: Debug {
+ /// Returns any "custom program clauses" that do not derive from
+ /// Rust IR. Used only in testing the underlying solver.
+ fn custom_clauses(&self) -> Vec<ProgramClause<I>>;
+
+ /// Returns the datum for the associated type with the given id.
+ fn associated_ty_data(&self, ty: AssocTypeId<I>) -> Arc<AssociatedTyDatum<I>>;
+
+ /// Returns the datum for the definition with the given id.
+ fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>>;
+
+ /// Returns the datum for the ADT with the given id.
+ fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>>;
+
+ /// Returns the generator datum for the generator with the given id.
+ fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>>;
+
+ /// Returns the generator witness datum for the generator with the given id.
+ fn generator_witness_datum(
+ &self,
+ generator_id: GeneratorId<I>,
+ ) -> Arc<GeneratorWitnessDatum<I>>;
+
+ /// Returns the representation for the ADT definition with the given id.
+ fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>>;
+
+ /// Returns the siza and alignment of the ADT definition with the given id.
+ fn adt_size_align(&self, id: AdtId<I>) -> Arc<AdtSizeAlign>;
+
+ /// Returns the datum for the fn definition with the given id.
+ fn fn_def_datum(&self, fn_def_id: FnDefId<I>) -> Arc<FnDefDatum<I>>;
+
+ /// Returns the datum for the impl with the given id.
+ fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>>;
+
+ /// Returns the `AssociatedTyValue` with the given id.
+ fn associated_ty_value(&self, id: AssociatedTyValueId<I>) -> Arc<AssociatedTyValue<I>>;
+
+ /// Returns the `OpaqueTyDatum` with the given id.
+ fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>>;
+
+ /// Returns the "hidden type" corresponding with the opaque type.
+ fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I>;
+
+ /// Returns a list of potentially relevant impls for a given
+ /// trait-id; we also supply the type parameters that we are
+ /// trying to match (if known: these parameters may contain
+ /// inference variables, for example). The implementor is
+ /// permitted to return any superset of the applicable impls;
+ /// chalk will narrow down the list to only those that truly
+ /// apply. The parameters are provided as a "hint" to help the
+ /// implementor do less work, but can be completely ignored if
+ /// desired.
+ ///
+ /// The `binders` are for the `parameters`; if the recursive solver is used,
+ /// the parameters can contain bound variables referring to these binders.
+ fn impls_for_trait(
+ &self,
+ trait_id: TraitId<I>,
+ parameters: &[GenericArg<I>],
+ binders: &CanonicalVarKinds<I>,
+ ) -> Vec<ImplId<I>>;
+
+ /// Returns the impls that require coherence checking. This is not the
+ /// full set of impls that exist:
+ ///
+ /// - It can exclude impls not defined in the current crate.
+ /// - It can exclude "built-in" impls, like those for closures; only the
+ /// impls actually written by users need to be checked.
+ fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>>;
+
+ /// Returns true if there is an explicit impl of the auto trait
+ /// `auto_trait_id` for the type `ty`. This is part of
+ /// the auto trait handling -- if there is no explicit impl given
+ /// by the user for `ty`, then we provide default impls
+ /// (otherwise, we rely on the impls the user gave).
+ fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool;
+
+ /// Returns id of a trait lang item, if found
+ fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<I>>;
+
+ /// Calculates program clauses from an env. This is intended to call the
+ /// `program_clauses_for_env` function and then possibly cache the clauses.
+ fn program_clauses_for_env(&self, environment: &Environment<I>) -> ProgramClauses<I>;
+
+ fn interner(&self) -> I;
+
+ /// Check if a trait is object safe
+ fn is_object_safe(&self, trait_id: TraitId<I>) -> bool;
+
+ /// Gets the `ClosureKind` for a given closure and substitution.
+ fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind;
+
+ /// Gets the inputs and output for a given closure id and substitution. We
+ /// pass both the `ClosureId` and it's `Substituion` to give implementors
+ /// the freedom to store associated data in the substitution (like rustc) or
+ /// separately (like chalk-integration).
+ fn closure_inputs_and_output(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Binders<FnDefInputsAndOutputDatum<I>>;
+
+ /// Gets the upvars as a `Ty` for a given closure id and substitution. There
+ /// are no restrictions on the type of upvars.
+ fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>>;
+
+ /// Gets the substitution for the closure when used as a function.
+ /// For example, for the following (not-quite-)rust code:
+ /// ```ignore
+ /// let foo = |a: &mut u32| { a += 1; };
+ /// let c: &'a u32 = &0;
+ /// foo(c);
+ /// ```
+ ///
+ /// This would return a `Substitution` of `[&'a]`. This could either be
+ /// substituted into the inputs and output, or into the upvars.
+ fn closure_fn_substitution(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Substitution<I>;
+
+ fn unification_database(&self) -> &dyn UnificationDatabase<I>;
+
+ /// Retrieves a trait's original name. No uniqueness guarantees, but must
+ /// a valid Rust identifier.
+ fn trait_name(&self, trait_id: TraitId<I>) -> String {
+ sanitize_debug_name(|f| I::debug_trait_id(trait_id, f))
+ }
+
+ /// Retrieves a struct's original name. No uniqueness guarantees, but must
+ /// a valid Rust identifier.
+ fn adt_name(&self, adt_id: AdtId<I>) -> String {
+ sanitize_debug_name(|f| I::debug_adt_id(adt_id, f))
+ }
+
+ /// Retrieves the name of an associated type. No uniqueness guarantees, but must
+ /// a valid Rust identifier.
+ fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
+ sanitize_debug_name(|f| I::debug_assoc_type_id(assoc_ty_id, f))
+ }
+
+ /// Retrieves the name of an opaque type. No uniqueness guarantees, but must
+ /// a valid Rust identifier.
+ fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
+ sanitize_debug_name(|f| I::debug_opaque_ty_id(opaque_ty_id, f))
+ }
+
+ /// Retrieves the name of a function definition. No uniqueness guarantees, but must
+ /// a valid Rust identifier.
+ fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
+ sanitize_debug_name(|f| I::debug_fn_def_id(fn_def_id, f))
+ }
+
+ // Retrieves the discriminant type for a type (mirror of rustc `TyS::discriminant_ty`)
+ fn discriminant_type(&self, ty: Ty<I>) -> Ty<I>;
+}
+
+pub use clauses::program_clauses_for_env;
+
+pub use solve::Guidance;
+pub use solve::Solution;
+pub use solve::Solver;
+pub use solve::SubstitutionResult;
+
+#[macro_use]
+mod debug_macros {
+ #[macro_export]
+ macro_rules! debug_span {
+ ($($t: tt)*) => {
+ let __span = tracing::debug_span!($($t)*);
+ let __span = __span.enter();
+ };
+ }
+}
diff --git a/vendor/chalk-solve/src/logging.rs b/vendor/chalk-solve/src/logging.rs
new file mode 100644
index 000000000..a5be4d4d4
--- /dev/null
+++ b/vendor/chalk-solve/src/logging.rs
@@ -0,0 +1,19 @@
+/// Run an action with a tracing log subscriber. The logging level is loaded
+/// from `CHALK_DEBUG`.
+#[cfg(feature = "tracing-full")]
+pub fn with_tracing_logs<T>(action: impl FnOnce() -> T) -> T {
+ use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
+ use tracing_tree::HierarchicalLayer;
+ let filter = EnvFilter::from_env("CHALK_DEBUG");
+ let subscriber = Registry::default()
+ .with(filter)
+ .with(HierarchicalLayer::new(2).with_writer(std::io::stdout));
+ tracing::subscriber::with_default(subscriber, action)
+}
+
+/// Run an action with a tracing log subscriber. The logging level is loaded
+/// from `CHALK_DEBUG`.
+#[cfg(not(feature = "tracing-full"))]
+pub fn with_tracing_logs<T>(action: impl FnOnce() -> T) -> T {
+ action()
+}
diff --git a/vendor/chalk-solve/src/logging_db.rs b/vendor/chalk-solve/src/logging_db.rs
new file mode 100644
index 000000000..12d8b052a
--- /dev/null
+++ b/vendor/chalk-solve/src/logging_db.rs
@@ -0,0 +1,593 @@
+//! Provides wrappers over `RustIrDatabase` which record used definitions and write
+//! `.chalk` files containing those definitions.
+use std::{
+ borrow::Borrow,
+ fmt::{self, Debug, Display},
+ io::Write,
+ marker::PhantomData,
+ sync::Arc,
+ sync::Mutex,
+};
+
+use crate::rust_ir::*;
+use crate::{
+ display::{self, WriterState},
+ RustIrDatabase,
+};
+use chalk_ir::{interner::Interner, *};
+
+use indexmap::IndexSet;
+
+mod id_collector;
+
+/// Wraps another `RustIrDatabase` (`DB`) and records which definitions are
+/// used.
+///
+/// A full .chalk file containing all used definitions can be recovered through
+/// `LoggingRustIrDatabase`'s `Display` implementation.
+///
+/// Uses a separate type, `P`, for the database stored inside to account for
+/// `Arc` or wrapping other storage mediums.
+#[derive(Debug)]
+pub struct LoggingRustIrDatabase<I, DB, P = DB>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ ws: WriterState<I, DB, P>,
+ def_ids: Mutex<IndexSet<RecordedItemId<I>>>,
+ _phantom: PhantomData<DB>,
+}
+
+impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ pub fn new(db: P) -> Self {
+ LoggingRustIrDatabase {
+ ws: WriterState::new(db),
+ def_ids: Default::default(),
+ _phantom: PhantomData,
+ }
+ }
+}
+
+impl<I, DB, P> Display for LoggingRustIrDatabase<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let def_ids = self.def_ids.lock().unwrap();
+ let stub_ids = id_collector::collect_unrecorded_ids(self.ws.db(), &def_ids);
+ display::write_stub_items(f, &self.ws, stub_ids)?;
+ display::write_items(f, &self.ws, def_ids.iter().copied())
+ }
+}
+
+impl<I, DB, P> LoggingRustIrDatabase<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+ I: Interner,
+{
+ fn record(&self, id: impl Into<RecordedItemId<I>>) {
+ self.def_ids.lock().unwrap().insert(id.into());
+ }
+
+ fn record_all<T, U>(&self, ids: T)
+ where
+ T: IntoIterator<Item = U>,
+ U: Into<RecordedItemId<I>>,
+ {
+ self.def_ids
+ .lock()
+ .unwrap()
+ .extend(ids.into_iter().map(Into::into));
+ }
+}
+
+impl<I, DB, P> UnificationDatabase<I> for LoggingRustIrDatabase<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + Debug,
+ I: Interner,
+{
+ fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
+ self.ws
+ .db()
+ .unification_database()
+ .fn_def_variance(fn_def_id)
+ }
+
+ fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
+ self.ws.db().unification_database().adt_variance(adt_id)
+ }
+}
+
+impl<I, DB, P> RustIrDatabase<I> for LoggingRustIrDatabase<I, DB, P>
+where
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + Debug,
+ I: Interner,
+{
+ fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
+ self.ws.db().custom_clauses()
+ }
+
+ fn associated_ty_data(
+ &self,
+ ty: chalk_ir::AssocTypeId<I>,
+ ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
+ let ty_datum = self.ws.db().associated_ty_data(ty);
+ self.record(ty_datum.trait_id);
+ ty_datum
+ }
+
+ fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
+ self.record(trait_id);
+ self.ws.db().trait_datum(trait_id)
+ }
+
+ fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
+ self.record(adt_id);
+ self.ws.db().adt_datum(adt_id)
+ }
+
+ fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
+ self.record(generator_id);
+ self.ws.db().borrow().generator_datum(generator_id)
+ }
+
+ fn generator_witness_datum(
+ &self,
+ generator_id: GeneratorId<I>,
+ ) -> Arc<GeneratorWitnessDatum<I>> {
+ self.record(generator_id);
+ self.ws.db().borrow().generator_witness_datum(generator_id)
+ }
+
+ fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
+ self.record(id);
+ self.ws.db().adt_repr(id)
+ }
+
+ fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> {
+ self.record(id);
+ self.ws.db().adt_size_align(id)
+ }
+
+ fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
+ self.record(impl_id);
+ self.ws.db().impl_datum(impl_id)
+ }
+
+ fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
+ self.record(id);
+ self.ws.db().hidden_opaque_type(id)
+ }
+
+ fn associated_ty_value(
+ &self,
+ id: crate::rust_ir::AssociatedTyValueId<I>,
+ ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
+ let value = self.ws.db().associated_ty_value(id);
+ self.record(value.impl_id);
+ value
+ }
+
+ fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
+ self.record(id);
+ self.ws.db().opaque_ty_data(id)
+ }
+
+ fn impls_for_trait(
+ &self,
+ trait_id: TraitId<I>,
+ parameters: &[chalk_ir::GenericArg<I>],
+ binders: &CanonicalVarKinds<I>,
+ ) -> Vec<ImplId<I>> {
+ self.record(trait_id);
+ let impl_ids = self.ws.db().impls_for_trait(trait_id, parameters, binders);
+ self.record_all(impl_ids.iter().copied());
+ impl_ids
+ }
+
+ fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
+ self.record(trait_id);
+ self.ws.db().local_impls_to_coherence_check(trait_id)
+ }
+
+ fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool {
+ self.record(auto_trait_id);
+ if let TyKind::Adt(adt_id, _) = ty {
+ self.record(*adt_id);
+ }
+ self.ws.db().impl_provided_for(auto_trait_id, ty)
+ }
+
+ fn well_known_trait_id(
+ &self,
+ well_known_trait: crate::rust_ir::WellKnownTrait,
+ ) -> Option<TraitId<I>> {
+ let trait_id = self.ws.db().well_known_trait_id(well_known_trait);
+ if let Some(id) = trait_id {
+ self.record(id);
+ }
+ trait_id
+ }
+
+ fn program_clauses_for_env(
+ &self,
+ environment: &chalk_ir::Environment<I>,
+ ) -> chalk_ir::ProgramClauses<I> {
+ self.ws.db().program_clauses_for_env(environment)
+ }
+
+ fn interner(&self) -> I {
+ self.ws.db().interner()
+ }
+
+ fn trait_name(&self, trait_id: TraitId<I>) -> String {
+ self.ws.db().trait_name(trait_id)
+ }
+
+ fn adt_name(&self, adt_id: AdtId<I>) -> String {
+ self.ws.db().adt_name(adt_id)
+ }
+
+ fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
+ self.ws.db().assoc_type_name(assoc_ty_id)
+ }
+
+ fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
+ self.ws.db().opaque_type_name(opaque_ty_id)
+ }
+
+ fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
+ self.record(trait_id);
+ self.ws.db().is_object_safe(trait_id)
+ }
+
+ fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
+ self.record(fn_def_id);
+ self.ws.db().fn_def_datum(fn_def_id)
+ }
+
+ fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
+ self.ws.db().fn_def_name(fn_def_id)
+ }
+
+ fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
+ // TODO: record closure IDs
+ self.ws.db().closure_kind(closure_id, substs)
+ }
+
+ fn closure_inputs_and_output(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Binders<FnDefInputsAndOutputDatum<I>> {
+ // TODO: record closure IDs
+ self.ws.db().closure_inputs_and_output(closure_id, substs)
+ }
+
+ fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
+ // TODO: record closure IDs
+ self.ws.db().closure_upvars(closure_id, substs)
+ }
+
+ fn closure_fn_substitution(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Substitution<I> {
+ // TODO: record closure IDs
+ self.ws.db().closure_fn_substitution(closure_id, substs)
+ }
+
+ fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
+ self.ws.db().discriminant_type(ty)
+ }
+
+ fn unification_database(&self) -> &dyn UnificationDatabase<I> {
+ self
+ }
+}
+
+/// Wraps a [`RustIrDatabase`], and, when dropped, writes out all used
+/// definition to the given file.
+///
+/// Uses [`LoggingRustIrDatabase`] internally.
+///
+/// Uses a separate type, `P`, for the database stored inside to account for
+/// `Arc` or wrapping other storage mediums.
+pub struct WriteOnDropRustIrDatabase<I, W, DB, P = DB>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+{
+ db: LoggingRustIrDatabase<I, DB, P>,
+ write: W,
+}
+
+impl<I, W, DB, P> fmt::Debug for WriteOnDropRustIrDatabase<I, W, DB, P>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("WriteOnDropRustIrDatabase")
+ .field("db", &self.db)
+ .field("write", &"<opaque>")
+ .finish()
+ }
+}
+
+impl<I, W, DB, P> WriteOnDropRustIrDatabase<I, W, DB, P>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+{
+ pub fn new(db: P, write: W) -> Self {
+ WriteOnDropRustIrDatabase {
+ db: LoggingRustIrDatabase::new(db),
+ write,
+ }
+ }
+
+ pub fn from_logging_db(db: LoggingRustIrDatabase<I, DB, P>, write: W) -> Self {
+ WriteOnDropRustIrDatabase { db, write }
+ }
+}
+
+impl<I, W, DB, P> Drop for WriteOnDropRustIrDatabase<I, W, DB, P>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB>,
+{
+ fn drop(&mut self) {
+ write!(self.write, "{}", self.db)
+ .and_then(|_| self.write.flush())
+ .expect("expected to be able to write rust ir database");
+ }
+}
+
+impl<I, W, DB, P> UnificationDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + Debug,
+{
+ fn fn_def_variance(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Variances<I> {
+ self.db
+ .borrow()
+ .unification_database()
+ .fn_def_variance(fn_def_id)
+ }
+
+ fn adt_variance(&self, adt_id: chalk_ir::AdtId<I>) -> Variances<I> {
+ self.db.borrow().unification_database().adt_variance(adt_id)
+ }
+}
+
+impl<I, W, DB, P> RustIrDatabase<I> for WriteOnDropRustIrDatabase<I, W, DB, P>
+where
+ I: Interner,
+ W: Write,
+ DB: RustIrDatabase<I>,
+ P: Borrow<DB> + Debug,
+{
+ fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<I>> {
+ self.db.custom_clauses()
+ }
+
+ fn associated_ty_data(
+ &self,
+ ty: chalk_ir::AssocTypeId<I>,
+ ) -> Arc<crate::rust_ir::AssociatedTyDatum<I>> {
+ self.db.associated_ty_data(ty)
+ }
+
+ fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>> {
+ self.db.trait_datum(trait_id)
+ }
+
+ fn adt_datum(&self, adt_id: AdtId<I>) -> Arc<AdtDatum<I>> {
+ self.db.adt_datum(adt_id)
+ }
+
+ fn generator_datum(&self, generator_id: GeneratorId<I>) -> Arc<GeneratorDatum<I>> {
+ self.db.borrow().generator_datum(generator_id)
+ }
+
+ /// Returns the generator witness datum for the generator with the given id.
+ fn generator_witness_datum(
+ &self,
+ generator_id: GeneratorId<I>,
+ ) -> Arc<GeneratorWitnessDatum<I>> {
+ self.db.borrow().generator_witness_datum(generator_id)
+ }
+
+ fn adt_repr(&self, id: AdtId<I>) -> Arc<AdtRepr<I>> {
+ self.db.adt_repr(id)
+ }
+
+ fn adt_size_align(&self, id: chalk_ir::AdtId<I>) -> Arc<crate::rust_ir::AdtSizeAlign> {
+ self.db.adt_size_align(id)
+ }
+
+ fn impl_datum(&self, impl_id: ImplId<I>) -> Arc<ImplDatum<I>> {
+ self.db.impl_datum(impl_id)
+ }
+
+ fn associated_ty_value(
+ &self,
+ id: crate::rust_ir::AssociatedTyValueId<I>,
+ ) -> Arc<crate::rust_ir::AssociatedTyValue<I>> {
+ self.db.associated_ty_value(id)
+ }
+
+ fn opaque_ty_data(&self, id: OpaqueTyId<I>) -> Arc<OpaqueTyDatum<I>> {
+ self.db.opaque_ty_data(id)
+ }
+
+ fn hidden_opaque_type(&self, id: OpaqueTyId<I>) -> Ty<I> {
+ self.db.hidden_opaque_type(id)
+ }
+
+ fn impls_for_trait(
+ &self,
+ trait_id: TraitId<I>,
+ parameters: &[chalk_ir::GenericArg<I>],
+ binders: &CanonicalVarKinds<I>,
+ ) -> Vec<ImplId<I>> {
+ self.db.impls_for_trait(trait_id, parameters, binders)
+ }
+
+ fn local_impls_to_coherence_check(&self, trait_id: TraitId<I>) -> Vec<ImplId<I>> {
+ self.db.local_impls_to_coherence_check(trait_id)
+ }
+
+ fn impl_provided_for(&self, auto_trait_id: TraitId<I>, ty: &TyKind<I>) -> bool {
+ self.db.impl_provided_for(auto_trait_id, ty)
+ }
+
+ fn well_known_trait_id(
+ &self,
+ well_known_trait: crate::rust_ir::WellKnownTrait,
+ ) -> Option<TraitId<I>> {
+ self.db.well_known_trait_id(well_known_trait)
+ }
+
+ fn program_clauses_for_env(
+ &self,
+ environment: &chalk_ir::Environment<I>,
+ ) -> chalk_ir::ProgramClauses<I> {
+ self.db.program_clauses_for_env(environment)
+ }
+
+ fn interner(&self) -> I {
+ self.db.interner()
+ }
+
+ fn is_object_safe(&self, trait_id: TraitId<I>) -> bool {
+ self.db.is_object_safe(trait_id)
+ }
+
+ fn unification_database(&self) -> &dyn UnificationDatabase<I> {
+ self
+ }
+
+ fn trait_name(&self, trait_id: TraitId<I>) -> String {
+ self.db.trait_name(trait_id)
+ }
+
+ fn adt_name(&self, adt_id: AdtId<I>) -> String {
+ self.db.adt_name(adt_id)
+ }
+
+ fn assoc_type_name(&self, assoc_ty_id: AssocTypeId<I>) -> String {
+ self.db.assoc_type_name(assoc_ty_id)
+ }
+
+ fn opaque_type_name(&self, opaque_ty_id: OpaqueTyId<I>) -> String {
+ self.db.opaque_type_name(opaque_ty_id)
+ }
+
+ fn fn_def_datum(&self, fn_def_id: chalk_ir::FnDefId<I>) -> Arc<FnDefDatum<I>> {
+ self.db.fn_def_datum(fn_def_id)
+ }
+
+ fn fn_def_name(&self, fn_def_id: FnDefId<I>) -> String {
+ self.db.fn_def_name(fn_def_id)
+ }
+
+ fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
+ // TODO: record closure IDs
+ self.db.closure_kind(closure_id, substs)
+ }
+
+ fn closure_inputs_and_output(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Binders<FnDefInputsAndOutputDatum<I>> {
+ self.db.closure_inputs_and_output(closure_id, substs)
+ }
+
+ fn closure_upvars(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Binders<Ty<I>> {
+ self.db.closure_upvars(closure_id, substs)
+ }
+
+ fn closure_fn_substitution(
+ &self,
+ closure_id: ClosureId<I>,
+ substs: &Substitution<I>,
+ ) -> Substitution<I> {
+ self.db.closure_fn_substitution(closure_id, substs)
+ }
+
+ fn discriminant_type(&self, ty: Ty<I>) -> Ty<I> {
+ self.db.discriminant_type(ty)
+ }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
+pub enum RecordedItemId<I: Interner> {
+ Adt(AdtId<I>),
+ Trait(TraitId<I>),
+ Impl(ImplId<I>),
+ OpaqueTy(OpaqueTyId<I>),
+ FnDef(FnDefId<I>),
+ Generator(GeneratorId<I>),
+}
+
+impl<I: Interner> From<AdtId<I>> for RecordedItemId<I> {
+ fn from(v: AdtId<I>) -> Self {
+ RecordedItemId::Adt(v)
+ }
+}
+
+impl<I: Interner> From<TraitId<I>> for RecordedItemId<I> {
+ fn from(v: TraitId<I>) -> Self {
+ RecordedItemId::Trait(v)
+ }
+}
+
+impl<I: Interner> From<ImplId<I>> for RecordedItemId<I> {
+ fn from(v: ImplId<I>) -> Self {
+ RecordedItemId::Impl(v)
+ }
+}
+
+impl<I: Interner> From<OpaqueTyId<I>> for RecordedItemId<I> {
+ fn from(v: OpaqueTyId<I>) -> Self {
+ RecordedItemId::OpaqueTy(v)
+ }
+}
+
+impl<I: Interner> From<FnDefId<I>> for RecordedItemId<I> {
+ fn from(v: FnDefId<I>) -> Self {
+ RecordedItemId::FnDef(v)
+ }
+}
+
+impl<I: Interner> From<GeneratorId<I>> for RecordedItemId<I> {
+ fn from(v: GeneratorId<I>) -> Self {
+ RecordedItemId::Generator(v)
+ }
+}
diff --git a/vendor/chalk-solve/src/logging_db/id_collector.rs b/vendor/chalk-solve/src/logging_db/id_collector.rs
new file mode 100644
index 000000000..41aa38166
--- /dev/null
+++ b/vendor/chalk-solve/src/logging_db/id_collector.rs
@@ -0,0 +1,162 @@
+use super::RecordedItemId;
+use crate::RustIrDatabase;
+use chalk_ir::{
+ interner::Interner,
+ visit::TypeVisitor,
+ visit::{TypeSuperVisitable, TypeVisitable},
+ AliasTy, DebruijnIndex, TyKind, WhereClause,
+};
+use std::ops::ControlFlow;
+
+use indexmap::IndexSet;
+
+/// Collects the identifiers needed to resolve all the names for a given
+/// set of identifers, excluding identifiers we already have.
+///
+/// When recording identifiers to print, the `LoggingRustIrDatabase` only
+/// records identifiers the solver uses. But the solver assumes well-formedness,
+/// and thus skips over many names referenced in the definitions.
+///
+/// For instance, if we have:
+///
+/// ```rust,ignore
+/// struct S {}
+///
+/// trait Parent {}
+/// trait Child where Self: Parent {}
+/// impl Parent for S {}
+/// impl Child for S {}
+/// ```
+///
+/// And our goal is `S: Child`, we will only render `S`, `impl Child for S`, and
+/// `trait Child`. This will not parse because the `Child` trait's definition
+/// references parent. IdCollector solves this by collecting all of the directly
+/// related identifiers, allowing those to be rendered as well, ensuring name
+/// resolution is successful.
+pub fn collect_unrecorded_ids<I: Interner, DB: RustIrDatabase<I>>(
+ db: &DB,
+ identifiers: &'_ IndexSet<RecordedItemId<I>>,
+) -> IndexSet<RecordedItemId<I>> {
+ let mut collector = IdCollector {
+ db,
+ found_identifiers: IndexSet::new(),
+ };
+ for id in identifiers {
+ match *id {
+ RecordedItemId::Adt(adt_id) => {
+ collector
+ .db
+ .adt_datum(adt_id)
+ .visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ RecordedItemId::FnDef(fn_def) => {
+ collector
+ .db
+ .fn_def_datum(fn_def)
+ .visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ RecordedItemId::Generator(_generator_id) => unimplemented!(),
+ RecordedItemId::Trait(trait_id) => {
+ let trait_datum = collector.db.trait_datum(trait_id);
+
+ trait_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ for assoc_ty_id in &trait_datum.associated_ty_ids {
+ let assoc_ty_datum = collector.db.associated_ty_data(*assoc_ty_id);
+ assoc_ty_datum
+ .bounds_on_self(collector.db.interner())
+ .visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ assoc_ty_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ }
+ RecordedItemId::OpaqueTy(opaque_id) => {
+ collector
+ .db
+ .opaque_ty_data(opaque_id)
+ .visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ collector
+ .db
+ .hidden_opaque_type(opaque_id)
+ .visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ RecordedItemId::Impl(impl_id) => {
+ let impl_datum = collector.db.impl_datum(impl_id);
+ for id in &impl_datum.associated_ty_value_ids {
+ let assoc_ty_value = collector.db.associated_ty_value(*id);
+ assoc_ty_value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ impl_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ }
+ }
+ }
+ collector
+ .found_identifiers
+ .difference(identifiers)
+ .copied()
+ .collect()
+}
+
+struct IdCollector<'i, I: Interner, DB: RustIrDatabase<I>> {
+ db: &'i DB,
+ found_identifiers: IndexSet<RecordedItemId<I>>,
+}
+
+impl<'i, I: Interner, DB: RustIrDatabase<I>> IdCollector<'i, I, DB> {
+ fn record(&mut self, id: impl Into<RecordedItemId<I>>) {
+ self.found_identifiers.insert(id.into());
+ }
+
+ fn visit_alias(&mut self, alias: &AliasTy<I>) {
+ match alias {
+ AliasTy::Projection(projection_ty) => {
+ let assoc_ty_datum = self.db.associated_ty_data(projection_ty.associated_ty_id);
+ self.record(assoc_ty_datum.trait_id)
+ }
+ AliasTy::Opaque(opaque_ty) => self.record(opaque_ty.opaque_ty_id),
+ }
+ }
+}
+
+impl<'i, I: Interner, DB: RustIrDatabase<I>> TypeVisitor<I> for IdCollector<'i, I, DB> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+ fn interner(&self) -> I {
+ self.db.interner()
+ }
+
+ fn visit_ty(
+ &mut self,
+ ty: &chalk_ir::Ty<I>,
+ outer_binder: chalk_ir::DebruijnIndex,
+ ) -> ControlFlow<()> {
+ match ty.kind(self.db.interner()) {
+ TyKind::Adt(adt, _) => self.record(*adt),
+ TyKind::FnDef(fn_def, _) => self.record(*fn_def),
+ TyKind::OpaqueType(opaque, _) => self.record(*opaque),
+ TyKind::Alias(alias) => self.visit_alias(alias),
+ TyKind::BoundVar(..) => (),
+ TyKind::Dyn(..) => (),
+ TyKind::Function(..) => (),
+ TyKind::InferenceVar(..) => (),
+ TyKind::Placeholder(..) => (),
+ _ => {}
+ }
+ ty.super_visit_with(self, outer_binder)
+ }
+
+ fn visit_where_clause(
+ &mut self,
+ where_clause: &WhereClause<I>,
+ outer_binder: DebruijnIndex,
+ ) -> ControlFlow<()> {
+ match where_clause {
+ WhereClause::Implemented(trait_ref) => self.record(trait_ref.trait_id),
+ WhereClause::AliasEq(alias_eq) => self.visit_alias(&alias_eq.alias),
+ WhereClause::LifetimeOutlives(_lifetime_outlives) => (),
+ WhereClause::TypeOutlives(_type_outlives) => (),
+ }
+ where_clause.super_visit_with(self.as_dyn(), outer_binder)
+ }
+}
diff --git a/vendor/chalk-solve/src/rust_ir.rs b/vendor/chalk-solve/src/rust_ir.rs
new file mode 100644
index 000000000..935a29032
--- /dev/null
+++ b/vendor/chalk-solve/src/rust_ir.rs
@@ -0,0 +1,752 @@
+//! Contains the definition for the "Rust IR" -- this is basically a "lowered"
+//! version of the AST, roughly corresponding to [the HIR] in the Rust
+//! compiler.
+
+use chalk_derive::{HasInterner, TypeFoldable, TypeVisitable};
+use chalk_ir::cast::Cast;
+use chalk_ir::fold::shift::Shift;
+use chalk_ir::interner::Interner;
+use chalk_ir::{
+ try_break, visit::TypeVisitable, AdtId, AliasEq, AliasTy, AssocTypeId, Binders, DebruijnIndex,
+ FnDefId, GenericArg, ImplId, OpaqueTyId, ProjectionTy, QuantifiedWhereClause, Substitution,
+ ToGenericArg, TraitId, TraitRef, Ty, TyKind, VariableKind, WhereClause, WithKind,
+};
+use std::iter;
+use std::ops::ControlFlow;
+
+/// Identifier for an "associated type value" found in some impl.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct AssociatedTyValueId<I: Interner>(pub I::DefId);
+
+chalk_ir::id_visit!(AssociatedTyValueId);
+chalk_ir::id_fold!(AssociatedTyValueId);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable)]
+pub struct ImplDatum<I: Interner> {
+ pub polarity: Polarity,
+ pub binders: Binders<ImplDatumBound<I>>,
+ pub impl_type: ImplType,
+ pub associated_ty_value_ids: Vec<AssociatedTyValueId<I>>,
+}
+
+impl<I: Interner> ImplDatum<I> {
+ pub fn is_positive(&self) -> bool {
+ self.polarity.is_positive()
+ }
+
+ pub fn trait_id(&self) -> TraitId<I> {
+ self.binders.skip_binders().trait_ref.trait_id
+ }
+
+ pub fn self_type_adt_id(&self, interner: I) -> Option<AdtId<I>> {
+ match self
+ .binders
+ .skip_binders()
+ .trait_ref
+ .self_type_parameter(interner)
+ .kind(interner)
+ {
+ TyKind::Adt(id, _) => Some(*id),
+ _ => None,
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, TypeFoldable, TypeVisitable)]
+pub struct ImplDatumBound<I: Interner> {
+ pub trait_ref: TraitRef<I>,
+ pub where_clauses: Vec<QuantifiedWhereClause<I>>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum ImplType {
+ Local,
+ External,
+}
+
+chalk_ir::const_visit!(ImplType);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct DefaultImplDatum<I: Interner> {
+ pub binders: Binders<DefaultImplDatumBound<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner)]
+pub struct DefaultImplDatumBound<I: Interner> {
+ pub trait_ref: TraitRef<I>,
+ pub accessible_tys: Vec<Ty<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable)]
+pub struct AdtDatum<I: Interner> {
+ pub binders: Binders<AdtDatumBound<I>>,
+ pub id: AdtId<I>,
+ pub flags: AdtFlags,
+ pub kind: AdtKind,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
+pub enum AdtKind {
+ Struct,
+ Enum,
+ Union,
+}
+
+chalk_ir::const_visit!(AdtKind);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
+pub struct AdtDatumBound<I: Interner> {
+ pub variants: Vec<AdtVariantDatum<I>>,
+ pub where_clauses: Vec<QuantifiedWhereClause<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
+pub struct AdtVariantDatum<I: Interner> {
+ pub fields: Vec<Ty<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct AdtFlags {
+ pub upstream: bool,
+ pub fundamental: bool,
+ pub phantom_data: bool,
+}
+
+chalk_ir::const_visit!(AdtFlags);
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct AdtRepr<I: Interner> {
+ pub c: bool,
+ pub packed: bool,
+ pub int: Option<chalk_ir::Ty<I>>,
+}
+
+/// Information about the size and alignment of an ADT.
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct AdtSizeAlign {
+ one_zst: bool,
+}
+
+impl AdtSizeAlign {
+ pub fn from_one_zst(one_zst: bool) -> AdtSizeAlign {
+ AdtSizeAlign { one_zst }
+ }
+
+ pub fn one_zst(&self) -> bool {
+ self.one_zst
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+/// A rust intermediate represention (rust_ir) of a function definition/declaration.
+/// For example, in the following rust code:
+///
+/// ```ignore
+/// fn foo<T>() -> i32 where T: Eq;
+/// ```
+///
+/// This would represent the declaration of `foo`.
+///
+/// Note this is distinct from a function pointer, which points to
+/// a function with a given type signature, whereas this represents
+/// a specific function definition.
+pub struct FnDefDatum<I: Interner> {
+ pub id: FnDefId<I>,
+ pub sig: chalk_ir::FnSig<I>,
+ pub binders: Binders<FnDefDatumBound<I>>,
+}
+
+/// Avoids visiting `I::FnAbi`
+impl<I: Interner> TypeVisitable<I> for FnDefDatum<I> {
+ fn visit_with<B>(
+ &self,
+ visitor: &mut dyn chalk_ir::visit::TypeVisitor<I, BreakTy = B>,
+ outer_binder: DebruijnIndex,
+ ) -> ControlFlow<B> {
+ try_break!(self.id.visit_with(visitor, outer_binder));
+ self.binders.visit_with(visitor, outer_binder)
+ }
+}
+
+/// Represents the inputs and outputs on a `FnDefDatum`. This is split
+/// from the where clauses, since these can contain bound lifetimes.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
+pub struct FnDefInputsAndOutputDatum<I: Interner> {
+ /// Types of the function's arguments
+ /// ```ignore
+ /// fn foo<T>(bar: i32, baz: T);
+ /// ^^^ ^
+ /// ```
+ ///
+ pub argument_types: Vec<Ty<I>>,
+ /// Return type of the function
+ /// ```ignore
+ /// fn foo<T>() -> i32;
+ /// ^^^
+ /// ```
+ pub return_type: Ty<I>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
+/// Represents the bounds on a `FnDefDatum`, including
+/// the function definition's type signature and where clauses.
+pub struct FnDefDatumBound<I: Interner> {
+ /// Inputs and outputs defined on a function
+ /// These are needed for late-bound regions in rustc. For example the
+ /// lifetime `'a` in
+ /// ```ignore
+ /// fn foo<'a, T>(&'a T);
+ /// ^^
+ /// ```
+ /// Rustc doesn't pass in late-bound the regions in substs, but the inputs
+ /// and outputs may use them. `where_clauses` don't need an extra set of
+ /// `Binders`, since any lifetimes found in where clauses are not late-bound.
+ ///
+ /// For more information, see [this rustc-dev-guide chapter](https://rustc-dev-guide.rust-lang.org/early-late-bound.html).
+ pub inputs_and_output: Binders<FnDefInputsAndOutputDatum<I>>,
+
+ /// Where clauses defined on the function
+ /// ```ignore
+ /// fn foo<T>() where T: Eq;
+ /// ^^^^^^^^^^^
+ /// ```
+ pub where_clauses: Vec<QuantifiedWhereClause<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+// FIXME: unignore the doctest below when GATs hit stable.
+/// A rust intermediate representation (rust_ir) of a Trait Definition. For
+/// example, given the following rust code:
+///
+/// ```ignore
+/// use std::fmt::Debug;
+///
+/// trait Foo<T>
+/// where
+/// T: Debug,
+/// {
+/// type Bar<U>;
+/// }
+/// ```
+///
+/// This would represent the `trait Foo` declaration. Note that the details of
+/// the trait members (e.g., the associated type declaration (`type Bar<U>`) are
+/// not contained in this type, and are represented separately (e.g., in
+/// [`AssociatedTyDatum`]).
+///
+/// Not to be confused with the rust_ir for a Trait Implementation, which is
+/// represented by [`ImplDatum`]
+///
+/// [`ImplDatum`]: struct.ImplDatum.html
+/// [`AssociatedTyDatum`]: struct.AssociatedTyDatum.html
+#[derive(TypeVisitable)]
+pub struct TraitDatum<I: Interner> {
+ pub id: TraitId<I>,
+
+ pub binders: Binders<TraitDatumBound<I>>,
+
+ /// "Flags" indicate special kinds of traits, like auto traits.
+ /// In Rust syntax these are represented in different ways, but in
+ /// chalk we add annotations like `#[auto]`.
+ pub flags: TraitFlags,
+
+ pub associated_ty_ids: Vec<AssocTypeId<I>>,
+
+ /// If this is a well-known trait, which one? If `None`, this is a regular,
+ /// user-defined trait.
+ pub well_known: Option<WellKnownTrait>,
+}
+
+/// A list of the traits that are "well known" to chalk, which means that
+/// the chalk-solve crate has special, hard-coded impls for them.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
+pub enum WellKnownTrait {
+ Sized,
+ Copy,
+ Clone,
+ Drop,
+ /// The trait `FnOnce<Args>` - the generic argument `Args` is always a tuple
+ /// corresponding to the arguments of a function implementing this trait.
+ /// E.g. `fn(u8, bool): FnOnce<(u8, bool)>`
+ FnOnce,
+ FnMut,
+ Fn,
+ Unsize,
+ Unpin,
+ CoerceUnsized,
+ DiscriminantKind,
+ Generator,
+ DispatchFromDyn,
+ Tuple,
+}
+
+chalk_ir::const_visit!(WellKnownTrait);
+
+impl<I: Interner> TraitDatum<I> {
+ pub fn is_auto_trait(&self) -> bool {
+ self.flags.auto
+ }
+
+ pub fn is_non_enumerable_trait(&self) -> bool {
+ self.flags.non_enumerable
+ }
+
+ pub fn is_coinductive_trait(&self) -> bool {
+ self.flags.coinductive
+ }
+
+ /// Gives access to the where clauses of the trait, quantified over the type parameters of the trait:
+ ///
+ /// ```ignore
+ /// trait Foo<T> where T: Debug { }
+ /// ^^^^^^^^^^^^^^
+ /// ```
+ pub fn where_clauses(&self) -> Binders<&Vec<QuantifiedWhereClause<I>>> {
+ self.binders.as_ref().map(|td| &td.where_clauses)
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, TypeVisitable)]
+pub struct TraitDatumBound<I: Interner> {
+ /// Where clauses defined on the trait:
+ ///
+ /// ```ignore
+ /// trait Foo<T> where T: Debug { }
+ /// ^^^^^^^^^^^^^^
+ /// ```
+ pub where_clauses: Vec<QuantifiedWhereClause<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct TraitFlags {
+ /// An "auto trait" is one that is "automatically implemented" for every
+ /// struct, so long as no explicit impl is given.
+ ///
+ /// Examples are `Send` and `Sync`.
+ pub auto: bool,
+
+ pub marker: bool,
+
+ /// Indicate that a trait is defined upstream (in a dependency), used during
+ /// coherence checking.
+ pub upstream: bool,
+
+ /// A fundamental trait is a trait where adding an impl for an existing type
+ /// is considered a breaking change. Examples of fundamental traits are the
+ /// closure traits like `Fn` and `FnMut`.
+ ///
+ /// As of this writing (2020-03-27), fundamental traits are declared by the
+ /// unstable `#[fundamental]` attribute in rustc, and hence cannot appear
+ /// outside of the standard library.
+ pub fundamental: bool,
+
+ /// Indicates that chalk cannot list all of the implementations of the given
+ /// trait, likely because it is a publicly exported trait in a library.
+ ///
+ /// Currently (2020-03-27) rustc and rust-analyzer mark all traits as
+ /// non_enumerable, and in the future it may become the only option.
+ pub non_enumerable: bool,
+
+ pub coinductive: bool,
+}
+
+chalk_ir::const_visit!(TraitFlags);
+
+/// An inline bound, e.g. `: Foo<K>` in `impl<K, T: Foo<K>> SomeType<T>`.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
+pub enum InlineBound<I: Interner> {
+ TraitBound(TraitBound<I>),
+ AliasEqBound(AliasEqBound<I>),
+}
+
+#[allow(type_alias_bounds)]
+pub type QuantifiedInlineBound<I: Interner> = Binders<InlineBound<I>>;
+
+pub trait IntoWhereClauses<I: Interner> {
+ type Output;
+
+ fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<Self::Output>;
+}
+
+impl<I: Interner> IntoWhereClauses<I> for InlineBound<I> {
+ type Output = WhereClause<I>;
+
+ /// Applies the `InlineBound` to `self_ty` and lowers to a
+ /// [`chalk_ir::DomainGoal`].
+ ///
+ /// Because an `InlineBound` does not know anything about what it's binding,
+ /// you must provide that type as `self_ty`.
+ fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
+ match self {
+ InlineBound::TraitBound(b) => b.into_where_clauses(interner, self_ty),
+ InlineBound::AliasEqBound(b) => b.into_where_clauses(interner, self_ty),
+ }
+ }
+}
+
+impl<I: Interner> IntoWhereClauses<I> for QuantifiedInlineBound<I> {
+ type Output = QuantifiedWhereClause<I>;
+
+ fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<QuantifiedWhereClause<I>> {
+ let self_ty = self_ty.shifted_in(interner);
+ self.map_ref(|b| b.into_where_clauses(interner, self_ty))
+ .into_iter()
+ .collect()
+ }
+}
+
+/// Represents a trait bound on e.g. a type or type parameter.
+/// Does not know anything about what it's binding.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
+pub struct TraitBound<I: Interner> {
+ pub trait_id: TraitId<I>,
+ pub args_no_self: Vec<GenericArg<I>>,
+}
+
+impl<I: Interner> TraitBound<I> {
+ fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
+ let trait_ref = self.as_trait_ref(interner, self_ty);
+ vec![WhereClause::Implemented(trait_ref)]
+ }
+
+ pub fn as_trait_ref(&self, interner: I, self_ty: Ty<I>) -> TraitRef<I> {
+ TraitRef {
+ trait_id: self.trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ iter::once(self_ty.cast(interner)).chain(self.args_no_self.iter().cloned()),
+ ),
+ }
+ }
+}
+
+/// Represents an alias equality bound on e.g. a type or type parameter.
+/// Does not know anything about what it's binding.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
+pub struct AliasEqBound<I: Interner> {
+ pub trait_bound: TraitBound<I>,
+ pub associated_ty_id: AssocTypeId<I>,
+ /// Does not include trait parameters.
+ pub parameters: Vec<GenericArg<I>>,
+ pub value: Ty<I>,
+}
+
+impl<I: Interner> AliasEqBound<I> {
+ fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
+ let trait_ref = self.trait_bound.as_trait_ref(interner, self_ty);
+
+ let substitution = Substitution::from_iter(
+ interner,
+ self.parameters
+ .iter()
+ .cloned()
+ .chain(trait_ref.substitution.iter(interner).cloned()),
+ );
+
+ vec![
+ WhereClause::Implemented(trait_ref),
+ WhereClause::AliasEq(AliasEq {
+ alias: AliasTy::Projection(ProjectionTy {
+ associated_ty_id: self.associated_ty_id,
+ substitution,
+ }),
+ ty: self.value.clone(),
+ }),
+ ]
+ }
+}
+
+pub trait Anonymize<I: Interner> {
+ /// Utility function that converts from a list of generic arguments
+ /// which *have* associated data (`WithKind<I, T>`) to a list of
+ /// "anonymous" generic parameters that just preserves their
+ /// kinds (`VariableKind<I>`). Often convenient in lowering.
+ fn anonymize(&self) -> Vec<VariableKind<I>>;
+}
+
+impl<I: Interner, T> Anonymize<I> for [WithKind<I, T>] {
+ fn anonymize(&self) -> Vec<VariableKind<I>> {
+ self.iter().map(|pk| pk.kind.clone()).collect()
+ }
+}
+
+/// Represents an associated type declaration found inside of a trait:
+///
+/// ```notrust
+/// trait Foo<P1..Pn> { // P0 is Self
+/// type Bar<Pn..Pm>: [bounds]
+/// where
+/// [where_clauses];
+/// }
+/// ```
+///
+/// The meaning of each of these parts:
+///
+/// * The *parameters* `P0...Pm` are all in scope for this associated type.
+/// * The *bounds* `bounds` are things that the impl must prove to be true.
+/// * The *where clauses* `where_clauses` are things that the impl can *assume* to be true
+/// (but which projectors must prove).
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct AssociatedTyDatum<I: Interner> {
+ /// The trait this associated type is defined in.
+ pub trait_id: TraitId<I>,
+
+ /// The ID of this associated type
+ pub id: AssocTypeId<I>,
+
+ /// Name of this associated type.
+ pub name: I::Identifier,
+
+ /// These binders represent the `P0...Pm` variables. The binders
+ /// are in the order `[Pn..Pm; P0..Pn]`. That is, the variables
+ /// from `Bar` come first (corresponding to the de bruijn concept
+ /// that "inner" binders are lower indices, although within a
+ /// given binder we do not have an ordering).
+ pub binders: Binders<AssociatedTyDatumBound<I>>,
+}
+
+// Manual implementation to avoid I::Identifier type.
+impl<I: Interner> TypeVisitable<I> for AssociatedTyDatum<I> {
+ fn visit_with<B>(
+ &self,
+ visitor: &mut dyn chalk_ir::visit::TypeVisitor<I, BreakTy = B>,
+ outer_binder: DebruijnIndex,
+ ) -> ControlFlow<B> {
+ try_break!(self.trait_id.visit_with(visitor, outer_binder));
+ try_break!(self.id.visit_with(visitor, outer_binder));
+ self.binders.visit_with(visitor, outer_binder)
+ }
+}
+
+/// Encodes the parts of `AssociatedTyDatum` where the parameters
+/// `P0..Pm` are in scope (`bounds` and `where_clauses`).
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
+pub struct AssociatedTyDatumBound<I: Interner> {
+ /// Bounds on the associated type itself.
+ ///
+ /// These must be proven by the implementer, for all possible parameters that
+ /// would result in a well-formed projection.
+ pub bounds: Vec<QuantifiedInlineBound<I>>,
+
+ /// Where clauses that must hold for the projection to be well-formed.
+ pub where_clauses: Vec<QuantifiedWhereClause<I>>,
+}
+
+impl<I: Interner> AssociatedTyDatum<I> {
+ /// Returns the associated ty's bounds applied to the projection type, e.g.:
+ ///
+ /// ```notrust
+ /// Implemented(<?0 as Foo>::Item<?1>: Sized)
+ /// ```
+ ///
+ /// these quantified where clauses are in the scope of the
+ /// `binders` field.
+ pub fn bounds_on_self(&self, interner: I) -> Vec<QuantifiedWhereClause<I>> {
+ let (binders, assoc_ty_datum) = self.binders.as_ref().into();
+ // Create a list `P0...Pn` of references to the binders in
+ // scope for this associated type:
+ let substitution = Substitution::from_iter(
+ interner,
+ binders
+ .iter(interner)
+ .enumerate()
+ .map(|p| p.to_generic_arg(interner)),
+ );
+
+ // The self type will be `<P0 as Foo<P1..Pn>>::Item<Pn..Pm>` etc
+ let self_ty = TyKind::Alias(AliasTy::Projection(ProjectionTy {
+ associated_ty_id: self.id,
+ substitution,
+ }))
+ .intern(interner);
+
+ // Now use that as the self type for the bounds, transforming
+ // something like `type Bar<Pn..Pm>: Debug` into
+ //
+ // ```
+ // <P0 as Foo<P1..Pn>>::Item<Pn..Pm>: Debug
+ // ```
+ assoc_ty_datum
+ .bounds
+ .iter()
+ .flat_map(|b| b.into_where_clauses(interner, self_ty.clone()))
+ .collect()
+ }
+}
+
+/// Represents the *value* of an associated type that is assigned
+/// from within some impl.
+///
+/// ```ignore
+/// impl Iterator for Foo {
+/// type Item = XXX; // <-- represents this line!
+/// }
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
+pub struct AssociatedTyValue<I: Interner> {
+ /// Impl in which this associated type value is found. You might
+ /// need to look at this to find the generic parameters defined on
+ /// the impl, for example.
+ ///
+ /// ```ignore
+ /// impl Iterator for Foo { // <-- refers to this impl
+ /// type Item = XXX; // <-- (where this is self)
+ /// }
+ /// ```
+ pub impl_id: ImplId<I>,
+
+ /// Associated type being defined.
+ ///
+ /// ```ignore
+ /// impl Iterator for Foo {
+ /// type Item = XXX; // <-- (where this is self)
+ /// }
+ /// ...
+ /// trait Iterator {
+ /// type Item; // <-- refers to this declaration here!
+ /// }
+ /// ```
+ pub associated_ty_id: AssocTypeId<I>,
+
+ /// Additional binders declared on the associated type itself,
+ /// beyond those from the impl. This would be empty for normal
+ /// associated types, but non-empty for generic associated types.
+ ///
+ /// ```ignore
+ /// impl<T> Iterable for Vec<T> {
+ /// type Iter<'a> = vec::Iter<'a, T>;
+ /// // ^^^^ refers to these generics here
+ /// }
+ /// ```
+ pub value: Binders<AssociatedTyValueBound<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
+pub struct AssociatedTyValueBound<I: Interner> {
+ /// Type that we normalize to. The X in `type Foo<'a> = X`.
+ pub ty: Ty<I>,
+}
+
+/// Represents the bounds for an `impl Trait` type.
+///
+/// ```ignore
+/// opaque type T: A + B = HiddenTy;
+/// ```
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
+pub struct OpaqueTyDatum<I: Interner> {
+ /// The placeholder `!T` that corresponds to the opaque type `T`.
+ pub opaque_ty_id: OpaqueTyId<I>,
+
+ /// The type bound to when revealed.
+ pub bound: Binders<OpaqueTyDatumBound<I>>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
+pub struct OpaqueTyDatumBound<I: Interner> {
+ /// Trait bounds for the opaque type. These are bounds that the hidden type must meet.
+ pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
+ /// Where clauses that inform well-formedness conditions for the opaque type.
+ /// These are conditions on the generic parameters of the opaque type which must be true
+ /// for a reference to the opaque type to be well-formed.
+ pub where_clauses: Binders<Vec<QuantifiedWhereClause<I>>>,
+}
+
+// The movability of a generator: whether a generator contains self-references,
+// causing it to be !Unpin
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub enum Movability {
+ Static,
+ Movable,
+}
+chalk_ir::copy_fold!(Movability);
+
+/// Represents a generator type.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
+pub struct GeneratorDatum<I: Interner> {
+ // Can the generator be moved (is Unpin or not)
+ pub movability: Movability,
+ /// All of the nested types for this generator. The `Binder`
+ /// represents the types and lifetimes that this generator is generic over -
+ /// this behaves in the same way as `AdtDatum.binders`
+ pub input_output: Binders<GeneratorInputOutputDatum<I>>,
+}
+
+/// The nested types for a generator. This always appears inside a `GeneratorDatum`
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
+pub struct GeneratorInputOutputDatum<I: Interner> {
+ /// The generator resume type - a value of this type
+ /// is supplied by the caller when resuming the generator.
+ /// Currently, this plays no rule in goal resolution.
+ pub resume_type: Ty<I>,
+ /// The generator yield type - a value of this type
+ /// is supplied by the generator during a yield.
+ /// Currently, this plays no role in goal resolution.
+ pub yield_type: Ty<I>,
+ /// The generator return type - a value of this type
+ /// is supplied by the generator when it returns.
+ /// Currently, this plays no role in goal resolution
+ pub return_type: Ty<I>,
+ /// The upvars stored by the generator. These represent
+ /// types captured from the generator's environment,
+ /// and are stored across all yields. These types (along with the witness types)
+ /// are considered 'constituent types' for the purposes of determining auto trait
+ /// implementations - that its, a generator impls an auto trait A
+ /// iff all of its constituent types implement A.
+ pub upvars: Vec<Ty<I>>,
+}
+
+/// The generator witness data. Each `GeneratorId` has both a `GeneratorDatum`
+/// and a `GeneratorWitnessDatum` - these represent two distinct types in Rust.
+/// `GeneratorWitnessDatum` is logically 'inside' a generator - this only
+/// matters when we treat the witness type as a 'constituent type for the
+/// purposes of determining auto trait implementations.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
+pub struct GeneratorWitnessDatum<I: Interner> {
+ /// This binder is identical to the `input_output` binder in `GeneratorWitness` -
+ /// it binds the types and lifetimes that the generator is generic over.
+ /// There is an additional binder inside `GeneratorWitnessExistential`, which
+ /// is treated specially.
+ pub inner_types: Binders<GeneratorWitnessExistential<I>>,
+}
+
+/// The generator witness types, together with existentially bound lifetimes.
+/// Each 'witness type' represents a type stored inside the generator across
+/// a yield. When a generator type is constructed, the precise region relationships
+/// found in the generator body are erased. As a result, we are left with existential
+/// lifetimes - each type is parameterized over *some* lifetimes, but we do not
+/// know their precise values.
+///
+/// Unlike the binder in `GeneratorWitnessDatum`, this `Binder` never gets substituted
+/// via an `Ty`. Instead, we handle this `Binders` specially when determining
+/// auto trait impls. See `push_auto_trait_impls_generator_witness` for more details.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
+pub struct GeneratorWitnessExistential<I: Interner> {
+ pub types: Binders<Vec<Ty<I>>>,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub enum Polarity {
+ Positive,
+ Negative,
+}
+
+chalk_ir::const_visit!(Polarity);
+
+impl Polarity {
+ pub fn is_positive(&self) -> bool {
+ match *self {
+ Polarity::Positive => true,
+ Polarity::Negative => false,
+ }
+ }
+}
+
+/// Indicates the "most permissive" Fn-like trait that the closure implements.
+/// If the closure kind for a closure is FnMut, for example, then the closure
+/// implements FnMut and FnOnce.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
+pub enum ClosureKind {
+ Fn,
+ FnMut,
+ FnOnce,
+}
diff --git a/vendor/chalk-solve/src/solve.rs b/vendor/chalk-solve/src/solve.rs
new file mode 100644
index 000000000..0734fc53e
--- /dev/null
+++ b/vendor/chalk-solve/src/solve.rs
@@ -0,0 +1,350 @@
+use crate::RustIrDatabase;
+use chalk_derive::HasInterner;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use std::fmt;
+use tracing::debug;
+
+pub mod truncate;
+
+/// A (possible) solution for a proposed goal.
+#[derive(Clone, Debug, PartialEq, Eq, HasInterner)]
+pub enum Solution<I: Interner> {
+ /// The goal indeed holds, and there is a unique value for all existential
+ /// variables. In this case, we also record a set of lifetime constraints
+ /// which must also hold for the goal to be valid.
+ Unique(Canonical<ConstrainedSubst<I>>),
+
+ /// The goal may be provable in multiple ways, but regardless we may have some guidance
+ /// for type inference. In this case, we don't return any lifetime
+ /// constraints, since we have not "committed" to any particular solution
+ /// yet.
+ Ambig(Guidance<I>),
+}
+
+/// When a goal holds ambiguously (e.g., because there are multiple possible
+/// solutions), we issue a set of *guidance* back to type inference.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum Guidance<I: Interner> {
+ /// The existential variables *must* have the given values if the goal is
+ /// ever to hold, but that alone isn't enough to guarantee the goal will
+ /// actually hold.
+ Definite(Canonical<Substitution<I>>),
+
+ /// There are multiple plausible values for the existentials, but the ones
+ /// here are suggested as the preferred choice heuristically. These should
+ /// be used for inference fallback only.
+ Suggested(Canonical<Substitution<I>>),
+
+ /// There's no useful information to feed back to type inference
+ Unknown,
+}
+
+impl<I: Interner> Solution<I> {
+ /// There are multiple candidate solutions, which may or may not agree on
+ /// the values for existential variables; attempt to combine them. This
+ /// operation does not depend on the order of its arguments.
+ ///
+ /// This actually isn't as precise as it could be, in two ways:
+ ///
+ /// a. It might be that while there are multiple distinct candidates, they
+ /// all agree about *some things*. To be maximally precise, we would
+ /// compute the intersection of what they agree on. It's not clear though
+ /// that this is actually what we want Rust's inference to do, and it's
+ /// certainly not what it does today.
+ ///
+ /// b. There might also be an ambiguous candidate and a successful candidate,
+ /// both with the same refined-goal. In that case, we could probably claim
+ /// success, since if the conditions of the ambiguous candidate were met,
+ /// we know the success would apply. Example: `?0: Clone` yields ambiguous
+ /// candidate `Option<?0>: Clone` and successful candidate `Option<?0>:
+ /// Clone`.
+ ///
+ /// But you get the idea.
+ pub fn combine(self, other: Solution<I>, interner: I) -> Solution<I> {
+ use self::Guidance::*;
+
+ if self == other {
+ return self;
+ }
+
+ // Special case hack: if one solution is "true" without any constraints,
+ // that is always the combined result.
+ //
+ // This is not as general as it could be: ideally, if we had one solution
+ // that is Unique with a simpler substitution than the other one, or region constraints
+ // which are a subset, we'd combine them.
+ if self.is_trivial_and_always_true(interner) {
+ return self;
+ }
+ if other.is_trivial_and_always_true(interner) {
+ return other;
+ }
+
+ debug!(
+ "combine {} with {}",
+ self.display(interner),
+ other.display(interner)
+ );
+
+ // Otherwise, always downgrade to Ambig:
+
+ let guidance = match (self.into_guidance(), other.into_guidance()) {
+ (Definite(ref subst1), Definite(ref subst2)) if subst1 == subst2 => {
+ Definite(subst1.clone())
+ }
+ (Suggested(ref subst1), Suggested(ref subst2)) if subst1 == subst2 => {
+ Suggested(subst1.clone())
+ }
+ _ => Unknown,
+ };
+ Solution::Ambig(guidance)
+ }
+
+ pub fn is_trivial_and_always_true(&self, interner: I) -> bool {
+ match self {
+ Solution::Unique(constrained_subst) => {
+ constrained_subst.value.subst.is_identity_subst(interner)
+ && constrained_subst.value.constraints.is_empty(interner)
+ }
+ Solution::Ambig(_) => false,
+ }
+ }
+
+ /// View this solution purely in terms of type inference guidance
+ pub fn into_guidance(self) -> Guidance<I> {
+ match self {
+ Solution::Unique(constrained) => Guidance::Definite(Canonical {
+ value: constrained.value.subst,
+ binders: constrained.binders,
+ }),
+ Solution::Ambig(guidance) => guidance,
+ }
+ }
+
+ /// Extract a constrained substitution from this solution, even if ambiguous.
+ pub fn constrained_subst(&self, interner: I) -> Option<Canonical<ConstrainedSubst<I>>> {
+ match *self {
+ Solution::Unique(ref constrained) => Some(constrained.clone()),
+ Solution::Ambig(Guidance::Definite(ref canonical))
+ | Solution::Ambig(Guidance::Suggested(ref canonical)) => {
+ let value = ConstrainedSubst {
+ subst: canonical.value.clone(),
+ constraints: Constraints::empty(interner),
+ };
+ Some(Canonical {
+ value,
+ binders: canonical.binders.clone(),
+ })
+ }
+ Solution::Ambig(_) => None,
+ }
+ }
+
+ /// Determine whether this solution contains type information that *must*
+ /// hold, and returns the subst in that case.
+ pub fn definite_subst(&self, interner: I) -> Option<Canonical<ConstrainedSubst<I>>> {
+ match self {
+ Solution::Unique(constrained) => Some(constrained.clone()),
+ Solution::Ambig(Guidance::Definite(canonical)) => {
+ let value = ConstrainedSubst {
+ subst: canonical.value.clone(),
+ constraints: Constraints::empty(interner),
+ };
+ Some(Canonical {
+ value,
+ binders: canonical.binders.clone(),
+ })
+ }
+ _ => None,
+ }
+ }
+
+ pub fn is_unique(&self) -> bool {
+ matches!(*self, Solution::Unique(..))
+ }
+
+ pub fn is_ambig(&self) -> bool {
+ matches!(*self, Solution::Ambig(_))
+ }
+
+ pub fn display(&self, interner: I) -> SolutionDisplay<'_, I> {
+ SolutionDisplay {
+ solution: self,
+ interner,
+ }
+ }
+}
+
+pub struct SolutionDisplay<'a, I: Interner> {
+ solution: &'a Solution<I>,
+ interner: I,
+}
+
+impl<'a, I: Interner> fmt::Display for SolutionDisplay<'a, I> {
+ #[rustfmt::skip]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+ let SolutionDisplay { solution, interner } = self;
+ match solution {
+ // If a `Unique` solution has no associated data, omit the trailing semicolon.
+ // This makes blessed test output nicer to read.
+ Solution::Unique(Canonical { binders, value: ConstrainedSubst { subst, constraints } } )
+ if interner.constraints_data(constraints.interned()).is_empty()
+ && interner.substitution_data(subst.interned()).is_empty()
+ && interner.canonical_var_kinds_data(binders.interned()).is_empty()
+ => write!(f, "Unique"),
+
+ Solution::Unique(constrained) => write!(f, "Unique; {}", constrained.display(*interner)),
+
+ Solution::Ambig(Guidance::Definite(subst)) => write!(
+ f,
+ "Ambiguous; definite substitution {}",
+ subst.display(*interner)
+ ),
+ Solution::Ambig(Guidance::Suggested(subst)) => write!(
+ f,
+ "Ambiguous; suggested substitution {}",
+ subst.display(*interner)
+ ),
+ Solution::Ambig(Guidance::Unknown) => write!(f, "Ambiguous; no inference guidance"),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub enum SubstitutionResult<S> {
+ Definite(S),
+ Ambiguous(S),
+ Floundered,
+}
+
+impl<S> SubstitutionResult<S> {
+ pub fn as_ref(&self) -> SubstitutionResult<&S> {
+ match self {
+ SubstitutionResult::Definite(subst) => SubstitutionResult::Definite(subst),
+ SubstitutionResult::Ambiguous(subst) => SubstitutionResult::Ambiguous(subst),
+ SubstitutionResult::Floundered => SubstitutionResult::Floundered,
+ }
+ }
+ pub fn map<U, F: FnOnce(S) -> U>(self, f: F) -> SubstitutionResult<U> {
+ match self {
+ SubstitutionResult::Definite(subst) => SubstitutionResult::Definite(f(subst)),
+ SubstitutionResult::Ambiguous(subst) => SubstitutionResult::Ambiguous(f(subst)),
+ SubstitutionResult::Floundered => SubstitutionResult::Floundered,
+ }
+ }
+}
+
+impl<S: fmt::Display> fmt::Display for SubstitutionResult<S> {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ SubstitutionResult::Definite(subst) => write!(fmt, "{}", subst),
+ SubstitutionResult::Ambiguous(subst) => write!(fmt, "Ambiguous({})", subst),
+ SubstitutionResult::Floundered => write!(fmt, "Floundered"),
+ }
+ }
+}
+
+/// Finds the solution to "goals", or trait queries -- i.e., figures
+/// out what sets of types implement which traits. Also, between
+/// queries, this struct stores the cached state from previous solver
+/// attempts, which can then be re-used later.
+pub trait Solver<I: Interner>
+where
+ Self: fmt::Debug,
+{
+ /// Attempts to solve the given goal, which must be in canonical
+ /// form. Returns a unique solution (if one exists). This will do
+ /// only as much work towards `goal` as it has to (and that work
+ /// is cached for future attempts).
+ ///
+ /// # Parameters
+ ///
+ /// - `program` -- defines the program clauses in scope.
+ /// - **Important:** You must supply the same set of program clauses
+ /// each time you invoke `solve`, as otherwise the cached data may be
+ /// invalid.
+ /// - `goal` the goal to solve
+ ///
+ /// # Returns
+ ///
+ /// - `None` is the goal cannot be proven.
+ /// - `Some(solution)` if we succeeded in finding *some* answers,
+ /// although `solution` may reflect ambiguity and unknowns.
+ fn solve(
+ &mut self,
+ program: &dyn RustIrDatabase<I>,
+ goal: &UCanonical<InEnvironment<Goal<I>>>,
+ ) -> Option<Solution<I>>;
+
+ /// Attempts to solve the given goal, which must be in canonical
+ /// form. Returns a unique solution (if one exists). This will do
+ /// only as much work towards `goal` as it has to (and that work
+ /// is cached for future attempts). In addition, the solving of the
+ /// goal can be limited by returning `false` from `should_continue`.
+ ///
+ /// # Parameters
+ ///
+ /// - `program` -- defines the program clauses in scope.
+ /// - **Important:** You must supply the same set of program clauses
+ /// each time you invoke `solve`, as otherwise the cached data may be
+ /// invalid.
+ /// - `goal` the goal to solve
+ /// - `should_continue` if `false` is returned, the no further solving
+ /// will be done. A `Guidance(Suggested(...))` will be returned a
+ /// `Solution`, using any answers that were generated up to that point.
+ ///
+ /// # Returns
+ ///
+ /// - `None` is the goal cannot be proven.
+ /// - `Some(solution)` if we succeeded in finding *some* answers,
+ /// although `solution` may reflect ambiguity and unknowns.
+ fn solve_limited(
+ &mut self,
+ program: &dyn RustIrDatabase<I>,
+ goal: &UCanonical<InEnvironment<Goal<I>>>,
+ should_continue: &dyn std::ops::Fn() -> bool,
+ ) -> Option<Solution<I>>;
+
+ /// Attempts to solve the given goal, which must be in canonical
+ /// form. Provides multiple solutions to function `f`. This will do
+ /// only as much work towards `goal` as it has to (and that work
+ /// is cached for future attempts).
+ ///
+ /// # Parameters
+ ///
+ /// - `program` -- defines the program clauses in scope.
+ /// - **Important:** You must supply the same set of program clauses
+ /// each time you invoke `solve`, as otherwise the cached data may be
+ /// invalid.
+ /// - `goal` the goal to solve
+ /// - `f` -- function to proceed solution. New solutions will be generated
+ /// while function returns `true`.
+ /// - first argument is solution found
+ /// - second argument is the next solution present
+ /// - returns true if next solution should be handled
+ ///
+ /// # Returns
+ ///
+ /// - `true` all solutions were processed with the function.
+ /// - `false` the function returned `false` and solutions were interrupted.
+ fn solve_multiple(
+ &mut self,
+ program: &dyn RustIrDatabase<I>,
+ goal: &UCanonical<InEnvironment<Goal<I>>>,
+ f: &mut dyn FnMut(SubstitutionResult<Canonical<ConstrainedSubst<I>>>, bool) -> bool,
+ ) -> bool;
+
+ /// A convenience method for when one doesn't need the actual solution,
+ /// only whether or not one exists.
+ fn has_unique_solution(
+ &mut self,
+ program: &dyn RustIrDatabase<I>,
+ goal: &UCanonical<InEnvironment<Goal<I>>>,
+ ) -> bool {
+ match self.solve(program, goal) {
+ Some(sol) => sol.is_unique(),
+ None => false,
+ }
+ }
+}
diff --git a/vendor/chalk-solve/src/solve/test/bench.rs b/vendor/chalk-solve/src/solve/test/bench.rs
new file mode 100644
index 000000000..6ef6eb1f9
--- /dev/null
+++ b/vendor/chalk-solve/src/solve/test/bench.rs
@@ -0,0 +1,111 @@
+//! Benchmarking tests.
+
+extern crate test;
+use self::test::Bencher;
+
+use crate::db::ChalkDatabase;
+use crate::query::{ProgramSolverChoice, ProgramText};
+use chalk_solve::SolverChoice;
+use ir;
+use std::sync::Arc;
+
+use super::{assert_result, parse_and_lower_goal, parse_and_lower_program};
+
+fn run_bench(
+ program_text: &str,
+ solver_choice: SolverChoice,
+ goal_text: &str,
+ bencher: &mut Bencher,
+ expected: &str,
+) {
+ ChalkDatabase::with_program(Arc::new(program_text.to_string()), solver_choice, |db| {
+ let program = db.lowered_program().unwrap();
+ let env = db.environment().unwrap();
+ ir::tls::set_current_program(&program, || {
+ let goal = parse_and_lower_goal(&program, goal_text).unwrap();
+ let peeled_goal = goal.into_peeled_goal();
+
+ // Execute once to get an expected result.
+ let result = solver_choice.solve_root_goal(&env, &peeled_goal);
+
+ // Check expectation.
+ assert_result(&result, expected);
+
+ // Then do it many times to measure time.
+ bencher.iter(|| solver_choice.solve_root_goal(&env, &peeled_goal));
+ });
+ });
+}
+
+const CYCLEY: &str = "
+trait AsRef<T> { }
+trait Clone { }
+trait Copy where Self: Clone { }
+trait Sized { }
+
+struct i32 { }
+impl Copy for i32 { }
+impl Clone for i32 { }
+impl Sized for i32 { }
+
+struct u32 { }
+impl Copy for u32 { }
+impl Clone for u32 { }
+impl Sized for u32 { }
+
+struct Rc<T> { }
+impl<T> Clone for Rc<T> { }
+impl<T> Sized for Rc<T> { }
+
+struct Box<T> { }
+impl<T> AsRef<T> for Box<T> where T: Sized { }
+impl<T> Clone for Box<T> where T: Clone { }
+impl<T> Sized for Box<T> { }
+
+// Meant to be [T]
+struct Slice<T> where T: Sized { }
+impl<T> Sized for Slice<T> { }
+impl<T> AsRef<Slice<T>> for Slice<T> where T: Sized { }
+
+struct Vec<T> where T: Sized { }
+impl<T> AsRef<Slice<T>> for Vec<T> where T: Sized { }
+impl<T> AsRef<Vec<T>> for Vec<T> where T: Sized { }
+impl<T> Clone for Vec<T> where T: Clone, T: Sized { }
+impl<T> Sized for Vec<T> where T: Sized { }
+
+trait SliceExt
+ where <Self as SliceExt>::Item: Clone
+{
+ type Item;
+}
+
+impl<T> SliceExt for Slice<T>
+ where T: Clone
+{
+ type Item = T;
+}
+";
+
+const CYCLEY_GOAL: &str = "
+forall<T> {
+ if (
+ <Slice<T> as SliceExt>::Item: Clone;
+ <Slice<T> as SliceExt>::Item: Sized;
+ T: Clone;
+ T: Sized
+ ) {
+ T: Sized
+ }
+}
+";
+
+#[bench]
+fn cycley_slg(b: &mut Bencher) {
+ run_bench(
+ CYCLEY,
+ SolverChoice::SLG { max_size: 20 },
+ CYCLEY_GOAL,
+ b,
+ "Unique",
+ );
+}
diff --git a/vendor/chalk-solve/src/solve/truncate.rs b/vendor/chalk-solve/src/solve/truncate.rs
new file mode 100644
index 000000000..1ed47b94f
--- /dev/null
+++ b/vendor/chalk-solve/src/solve/truncate.rs
@@ -0,0 +1,134 @@
+//!
+
+use crate::infer::InferenceTable;
+use chalk_ir::interner::Interner;
+use chalk_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use chalk_ir::*;
+use std::cmp::max;
+use std::ops::ControlFlow;
+
+/// "Truncation" (called "abstraction" in the papers referenced below)
+/// refers to the act of modifying a goal or answer that has become
+/// too large in order to guarantee termination.
+///
+/// Currently we don't perform truncation (but it might me readded later).
+///
+/// Citations:
+///
+/// - Terminating Evaluation of Logic Programs with Finite Three-Valued Models
+/// - Riguzzi and Swift; ACM Transactions on Computational Logic 2013
+/// - Radial Restraint
+/// - Grosof and Swift; 2013
+pub fn needs_truncation<I: Interner>(
+ interner: I,
+ infer: &mut InferenceTable<I>,
+ max_size: usize,
+ value: impl TypeVisitable<I>,
+) -> bool {
+ let mut visitor = TySizeVisitor::new(interner, infer);
+ value.visit_with(&mut visitor, DebruijnIndex::INNERMOST);
+
+ visitor.max_size > max_size
+}
+
+struct TySizeVisitor<'infer, I: Interner> {
+ interner: I,
+ infer: &'infer mut InferenceTable<I>,
+ size: usize,
+ depth: usize,
+ max_size: usize,
+}
+
+impl<'infer, I: Interner> TySizeVisitor<'infer, I> {
+ fn new(interner: I, infer: &'infer mut InferenceTable<I>) -> Self {
+ Self {
+ interner,
+ infer,
+ size: 0,
+ depth: 0,
+ max_size: 0,
+ }
+ }
+}
+
+impl<'infer, I: Interner> TypeVisitor<I> for TySizeVisitor<'infer, I> {
+ type BreakTy = ();
+
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ if let Some(normalized_ty) = self.infer.normalize_ty_shallow(self.interner, ty) {
+ normalized_ty.visit_with(self, outer_binder);
+ return ControlFlow::Continue(());
+ }
+
+ self.size += 1;
+ self.max_size = max(self.size, self.max_size);
+
+ self.depth += 1;
+ ty.super_visit_with(self, outer_binder);
+ self.depth -= 1;
+
+ // When we get back to the first invocation, clear the counters.
+ // We process each outermost type independently.
+ if self.depth == 0 {
+ self.size = 0;
+ }
+ ControlFlow::Continue(())
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use chalk_integration::{arg, ty};
+
+ #[test]
+ fn one_type() {
+ use chalk_integration::interner::ChalkIr;
+ let interner = ChalkIr;
+ let mut table = InferenceTable::<chalk_integration::interner::ChalkIr>::new();
+ let _u1 = table.new_universe();
+
+ // Vec<Vec<Vec<Vec<T>>>>
+ let ty0 = ty!(apply (item 0)
+ (apply (item 0)
+ (apply (item 0)
+ (apply (item 0)
+ (placeholder 1)))));
+
+ let mut visitor = TySizeVisitor::new(interner, &mut table);
+ ty0.visit_with(&mut visitor, DebruijnIndex::INNERMOST);
+ assert!(visitor.max_size == 5);
+ }
+
+ #[test]
+ fn multiple_types() {
+ use chalk_integration::interner::ChalkIr;
+ let interner = ChalkIr;
+ let mut table = InferenceTable::<chalk_integration::interner::ChalkIr>::new();
+ let _u1 = table.new_universe();
+
+ // Vec<Vec<Vec<Vec<T>>>>
+ let ty0 = ty!(apply (item 0)
+ (apply (item 0)
+ (apply (item 0)
+ (apply (item 0)
+ (placeholder 1)))));
+
+ let ty1 = ty!(apply (item 0)
+ (apply (item 0)
+ (apply (item 0)
+ (placeholder 1))));
+
+ let mut visitor = TySizeVisitor::new(interner, &mut table);
+ vec![&ty0, &ty1].visit_with(&mut visitor, DebruijnIndex::INNERMOST);
+ assert!(visitor.max_size == 5);
+ }
+}
diff --git a/vendor/chalk-solve/src/split.rs b/vendor/chalk-solve/src/split.rs
new file mode 100644
index 000000000..bea24044d
--- /dev/null
+++ b/vendor/chalk-solve/src/split.rs
@@ -0,0 +1,199 @@
+use crate::rust_ir::*;
+use crate::RustIrDatabase;
+use chalk_ir::interner::Interner;
+use chalk_ir::*;
+use std::sync::Arc;
+use tracing::{debug, instrument};
+
+/// Methods for splitting up the projections for associated types from
+/// the surrounding context.
+pub trait Split<I: Interner>: RustIrDatabase<I> {
+ /// Given a projection of an associated type, split the type
+ /// parameters into those that come from the *trait* and those
+ /// that come from the *associated type itself*. So e.g. if you
+ /// have `(Iterator::Item)<F>`, this would return `([F], [])`,
+ /// since `Iterator::Item` is not generic and hence doesn't have
+ /// any type parameters itself.
+ fn split_projection<'p>(
+ &self,
+ projection: &'p ProjectionTy<I>,
+ ) -> (
+ Arc<AssociatedTyDatum<I>>,
+ &'p [GenericArg<I>],
+ &'p [GenericArg<I>],
+ ) {
+ let interner = self.interner();
+ let ProjectionTy {
+ associated_ty_id,
+ ref substitution,
+ } = *projection;
+ let parameters = substitution.as_slice(interner);
+ let associated_ty_data = &self.associated_ty_data(associated_ty_id);
+ let (trait_params, other_params) =
+ self.split_associated_ty_parameters(parameters, &**associated_ty_data);
+ (associated_ty_data.clone(), trait_params, other_params)
+ }
+
+ /// Given a projection `<P0 as Trait<P1..Pn>>::Item<Pn..Pm>`,
+ /// returns the trait parameters `[P0..Pn]` (see
+ /// `split_projection`).
+ fn trait_parameters_from_projection<'p>(
+ &self,
+ projection: &'p ProjectionTy<I>,
+ ) -> &'p [GenericArg<I>] {
+ let (_, trait_params, _) = self.split_projection(projection);
+ trait_params
+ }
+
+ /// Given a projection `<P0 as Trait<P1..Pn>>::Item<Pn..Pm>`,
+ /// returns the trait parameters `[P0..Pn]` (see
+ /// `split_projection`).
+ fn trait_ref_from_projection(&self, projection: &ProjectionTy<I>) -> TraitRef<I> {
+ let interner = self.interner();
+ let (associated_ty_data, trait_params, _) = self.split_projection(projection);
+ TraitRef {
+ trait_id: associated_ty_data.trait_id,
+ substitution: Substitution::from_iter(interner, trait_params),
+ }
+ }
+
+ /// Given the full set of parameters (or binders) for an
+ /// associated type *value* (which appears in an impl), splits
+ /// them into the substitutions for the *impl* and those for the
+ /// *associated type*.
+ ///
+ /// # Example
+ ///
+ /// ```ignore (example)
+ /// impl<T> Iterable for Vec<T> {
+ /// type Iter<'a>;
+ /// }
+ /// ```
+ ///
+ /// in this example, the full set of parameters would be `['x,
+ /// Y]`, where `'x` is the value for `'a` and `Y` is the value for
+ /// `T`.
+ ///
+ /// # Returns
+ ///
+ /// Returns the pair of:
+ ///
+ /// * the parameters for the impl (`[Y]`, in our example)
+ /// * the parameters for the associated type value (`['a]`, in our example)
+ fn split_associated_ty_value_parameters<'p, P>(
+ &self,
+ parameters: &'p [P],
+ associated_ty_value: &AssociatedTyValue<I>,
+ ) -> (&'p [P], &'p [P]) {
+ let interner = self.interner();
+ let impl_datum = self.impl_datum(associated_ty_value.impl_id);
+ let impl_params_len = impl_datum.binders.len(interner);
+ assert!(parameters.len() >= impl_params_len);
+
+ // the impl parameters are a suffix
+ //
+ // [ P0..Pn, Pn...Pm ]
+ // ^^^^^^^ impl parameters
+ let split_point = parameters.len() - impl_params_len;
+ let (other_params, impl_params) = parameters.split_at(split_point);
+ (impl_params, other_params)
+ }
+
+ /// Given the full set of parameters for an associated type *value*
+ /// (which appears in an impl), returns the trait reference
+ /// and projection that are being satisfied by that value.
+ ///
+ /// # Example
+ ///
+ /// ```ignore (example)
+ /// impl<T> Iterable for Vec<T> {
+ /// type Iter<'a>;
+ /// }
+ /// ```
+ ///
+ /// Here we expect the full set of parameters for `Iter`, which
+ /// would be `['x, Y]`, where `'x` is the value for `'a` and `Y`
+ /// is the value for `T`.
+ ///
+ /// Returns the pair of:
+ ///
+ /// * the parameters that apply to the impl (`Y`, in our example)
+ /// * the projection `<Vec<Y> as Iterable>::Iter<'x>`
+ #[instrument(level = "debug", skip(self, associated_ty_value))]
+ fn impl_parameters_and_projection_from_associated_ty_value<'p>(
+ &self,
+ parameters: &'p [GenericArg<I>],
+ associated_ty_value: &AssociatedTyValue<I>,
+ ) -> (&'p [GenericArg<I>], ProjectionTy<I>) {
+ let interner = self.interner();
+
+ let impl_datum = self.impl_datum(associated_ty_value.impl_id);
+
+ // Get the trait ref from the impl -- so in our example above
+ // this would be `Box<!T>: Foo`.
+ let (impl_parameters, atv_parameters) =
+ self.split_associated_ty_value_parameters(parameters, associated_ty_value);
+ let trait_ref = {
+ let opaque_ty_ref = impl_datum.binders.map_ref(|b| &b.trait_ref).cloned();
+ debug!(?opaque_ty_ref);
+ opaque_ty_ref.substitute(interner, impl_parameters)
+ };
+
+ // Create the parameters for the projection -- in our example
+ // above, this would be `['!a, Box<!T>]`, corresponding to
+ // `<Box<!T> as Foo>::Item<'!a>`
+ let projection_substitution = Substitution::from_iter(
+ interner,
+ atv_parameters
+ .iter()
+ .chain(trait_ref.substitution.iter(interner))
+ .cloned(),
+ );
+
+ let projection = ProjectionTy {
+ associated_ty_id: associated_ty_value.associated_ty_id,
+ substitution: projection_substitution,
+ };
+
+ debug!(?impl_parameters, ?trait_ref, ?projection);
+
+ (impl_parameters, projection)
+ }
+
+ /// Given the full set of parameters (or binders) for an
+ /// associated type datum (the one appearing in a trait), splits
+ /// them into the parameters for the *trait* and those for the
+ /// *associated type*.
+ ///
+ /// # Example
+ ///
+ /// ```ignore (example)
+ /// trait Foo<T> {
+ /// type Assoc<'a>;
+ /// }
+ /// ```
+ ///
+ /// in this example, the full set of parameters would be `['x,
+ /// Y]`, where `'x` is the value for `'a` and `Y` is the value for
+ /// `T`.
+ ///
+ /// # Returns
+ ///
+ /// Returns the tuple of:
+ ///
+ /// * the parameters for the impl (`[Y]`, in our example)
+ /// * the parameters for the associated type value (`['a]`, in our example)
+ fn split_associated_ty_parameters<'p, P>(
+ &self,
+ parameters: &'p [P],
+ associated_ty_datum: &AssociatedTyDatum<I>,
+ ) -> (&'p [P], &'p [P]) {
+ let trait_datum = &self.trait_datum(associated_ty_datum.trait_id);
+ let trait_num_params = trait_datum.binders.len(self.interner());
+ let split_point = parameters.len() - trait_num_params;
+ let (other_params, trait_params) = parameters.split_at(split_point);
+ (trait_params, other_params)
+ }
+}
+
+impl<DB: RustIrDatabase<I> + ?Sized, I: Interner> Split<I> for DB {}
diff --git a/vendor/chalk-solve/src/wf.rs b/vendor/chalk-solve/src/wf.rs
new file mode 100644
index 000000000..d552cdde7
--- /dev/null
+++ b/vendor/chalk-solve/src/wf.rs
@@ -0,0 +1,1202 @@
+use std::ops::ControlFlow;
+use std::{fmt, iter};
+
+use crate::{
+ ext::*, goal_builder::GoalBuilder, rust_ir::*, solve::Solver, split::Split, RustIrDatabase,
+};
+use chalk_ir::{
+ cast::*,
+ fold::shift::Shift,
+ interner::Interner,
+ visit::{TypeVisitable, TypeVisitor},
+ *,
+};
+use tracing::debug;
+
+#[derive(Debug)]
+pub enum WfError<I: Interner> {
+ IllFormedTypeDecl(chalk_ir::AdtId<I>),
+ IllFormedOpaqueTypeDecl(chalk_ir::OpaqueTyId<I>),
+ IllFormedTraitImpl(chalk_ir::TraitId<I>),
+}
+
+impl<I: Interner> fmt::Display for WfError<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ WfError::IllFormedTypeDecl(id) => write!(
+ f,
+ "type declaration `{:?}` does not meet well-formedness requirements",
+ id
+ ),
+ WfError::IllFormedOpaqueTypeDecl(id) => write!(
+ f,
+ "opaque type declaration `{:?}` does not meet well-formedness requirements",
+ id
+ ),
+ WfError::IllFormedTraitImpl(id) => write!(
+ f,
+ "trait impl for `{:?}` does not meet well-formedness requirements",
+ id
+ ),
+ }
+ }
+}
+
+impl<I: Interner> std::error::Error for WfError<I> {}
+
+pub struct WfSolver<'a, I: Interner> {
+ db: &'a dyn RustIrDatabase<I>,
+ solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
+}
+
+struct InputTypeCollector<I: Interner> {
+ types: Vec<Ty<I>>,
+ interner: I,
+}
+
+impl<I: Interner> InputTypeCollector<I> {
+ fn new(interner: I) -> Self {
+ Self {
+ types: Vec::new(),
+ interner,
+ }
+ }
+
+ fn types_in(interner: I, value: impl TypeVisitable<I>) -> Vec<Ty<I>> {
+ let mut collector = Self::new(interner);
+ value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
+ collector.types
+ }
+}
+
+impl<I: Interner> TypeVisitor<I> for InputTypeCollector<I> {
+ type BreakTy = ();
+ fn as_dyn(&mut self) -> &mut dyn TypeVisitor<I, BreakTy = Self::BreakTy> {
+ self
+ }
+
+ fn interner(&self) -> I {
+ self.interner
+ }
+
+ fn visit_where_clause(
+ &mut self,
+ where_clause: &WhereClause<I>,
+ outer_binder: DebruijnIndex,
+ ) -> ControlFlow<()> {
+ match where_clause {
+ WhereClause::AliasEq(alias_eq) => alias_eq
+ .alias
+ .clone()
+ .intern(self.interner)
+ .visit_with(self, outer_binder),
+ WhereClause::Implemented(trait_ref) => trait_ref.visit_with(self, outer_binder),
+ WhereClause::TypeOutlives(TypeOutlives { ty, .. }) => ty.visit_with(self, outer_binder),
+ WhereClause::LifetimeOutlives(..) => ControlFlow::Continue(()),
+ }
+ }
+
+ fn visit_ty(&mut self, ty: &Ty<I>, outer_binder: DebruijnIndex) -> ControlFlow<()> {
+ let interner = self.interner();
+
+ let mut push_ty = || {
+ self.types
+ .push(ty.clone().shifted_out_to(interner, outer_binder).unwrap())
+ };
+ match ty.kind(interner) {
+ TyKind::Adt(id, substitution) => {
+ push_ty();
+ id.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::AssociatedType(assoc_ty, substitution) => {
+ push_ty();
+ assoc_ty.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Scalar(scalar) => {
+ push_ty();
+ scalar.visit_with(self, outer_binder)
+ }
+ TyKind::Str => {
+ push_ty();
+ ControlFlow::Continue(())
+ }
+ TyKind::Tuple(arity, substitution) => {
+ push_ty();
+ arity.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::OpaqueType(opaque_ty, substitution) => {
+ push_ty();
+ opaque_ty.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Slice(substitution) => {
+ push_ty();
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::FnDef(fn_def, substitution) => {
+ push_ty();
+ fn_def.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Ref(mutability, lifetime, ty) => {
+ push_ty();
+ mutability.visit_with(self, outer_binder);
+ lifetime.visit_with(self, outer_binder);
+ ty.visit_with(self, outer_binder)
+ }
+ TyKind::Raw(mutability, substitution) => {
+ push_ty();
+ mutability.visit_with(self, outer_binder);
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Never => {
+ push_ty();
+ ControlFlow::Continue(())
+ }
+ TyKind::Array(ty, const_) => {
+ push_ty();
+ ty.visit_with(self, outer_binder);
+ const_.visit_with(self, outer_binder)
+ }
+ TyKind::Closure(_id, substitution) => {
+ push_ty();
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Generator(_generator, substitution) => {
+ push_ty();
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::GeneratorWitness(_witness, substitution) => {
+ push_ty();
+ substitution.visit_with(self, outer_binder)
+ }
+ TyKind::Foreign(_foreign_ty) => {
+ push_ty();
+ ControlFlow::Continue(())
+ }
+ TyKind::Error => {
+ push_ty();
+ ControlFlow::Continue(())
+ }
+
+ TyKind::Dyn(clauses) => {
+ push_ty();
+ clauses.visit_with(self, outer_binder)
+ }
+
+ TyKind::Alias(AliasTy::Projection(proj)) => {
+ push_ty();
+ proj.visit_with(self, outer_binder)
+ }
+
+ TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
+ push_ty();
+ opaque_ty.visit_with(self, outer_binder)
+ }
+
+ TyKind::Placeholder(_) => {
+ push_ty();
+ ControlFlow::Continue(())
+ }
+
+ // Type parameters do not carry any input types (so we can sort of assume they are
+ // always WF).
+ TyKind::BoundVar(..) => ControlFlow::Continue(()),
+
+ // Higher-kinded types such as `for<'a> fn(&'a u32)` introduce their own implied
+ // bounds, and these bounds will be enforced upon calling such a function. In some
+ // sense, well-formedness requirements for the input types of an HKT will be enforced
+ // lazily, so no need to include them here.
+ TyKind::Function(..) => ControlFlow::Continue(()),
+
+ TyKind::InferenceVar(..) => {
+ panic!("unexpected inference variable in wf rules: {:?}", ty)
+ }
+ }
+ }
+}
+
+impl<'a, I> WfSolver<'a, I>
+where
+ I: Interner,
+{
+ /// Constructs a new `WfSolver`.
+ pub fn new(
+ db: &'a dyn RustIrDatabase<I>,
+ solver_builder: &'a dyn Fn() -> Box<dyn Solver<I>>,
+ ) -> Self {
+ Self { db, solver_builder }
+ }
+
+ pub fn verify_adt_decl(&self, adt_id: AdtId<I>) -> Result<(), WfError<I>> {
+ let interner = self.db.interner();
+
+ // Given a struct like
+ //
+ // ```rust
+ // struct Foo<T> where T: Eq {
+ // data: Vec<T>
+ // }
+ // ```
+ let adt_datum = self.db.adt_datum(adt_id);
+ let is_enum = adt_datum.kind == AdtKind::Enum;
+
+ let mut gb = GoalBuilder::new(self.db);
+ let adt_data = adt_datum
+ .binders
+ .map_ref(|b| (&b.variants, &b.where_clauses));
+
+ // We make a goal like...
+ //
+ // forall<T> { ... }
+ let wg_goal = gb.forall(
+ &adt_data,
+ is_enum,
+ |gb, _, (variants, where_clauses), is_enum| {
+ let interner = gb.interner();
+
+ // (FromEnv(T: Eq) => ...)
+ gb.implies(
+ where_clauses
+ .iter()
+ .cloned()
+ .map(|wc| wc.into_from_env_goal(interner)),
+ |gb| {
+ let sub_goals: Vec<_> = variants
+ .iter()
+ .flat_map(|variant| {
+ let fields = &variant.fields;
+
+ // When checking if Enum is well-formed, we require that all fields of
+ // each variant are sized. For `structs`, we relax this requirement to
+ // all but the last field.
+ let sized_constraint_goal =
+ WfWellKnownConstraints::struct_sized_constraint(
+ gb.db(),
+ fields,
+ is_enum,
+ );
+
+ // WellFormed(Vec<T>), for each field type `Vec<T>` or type that appears in the where clauses
+ let types = InputTypeCollector::types_in(
+ gb.interner(),
+ (&fields, &where_clauses),
+ );
+
+ types
+ .into_iter()
+ .map(|ty| ty.well_formed().cast(interner))
+ .chain(sized_constraint_goal.into_iter())
+ })
+ .collect();
+
+ gb.all(sub_goals)
+ },
+ )
+ },
+ );
+
+ let wg_goal = wg_goal.into_closed_goal(interner);
+ let mut fresh_solver = (self.solver_builder)();
+ let is_legal = fresh_solver.has_unique_solution(self.db, &wg_goal);
+
+ if !is_legal {
+ Err(WfError::IllFormedTypeDecl(adt_id))
+ } else {
+ Ok(())
+ }
+ }
+
+ pub fn verify_trait_impl(&self, impl_id: ImplId<I>) -> Result<(), WfError<I>> {
+ let interner = self.db.interner();
+
+ let impl_datum = self.db.impl_datum(impl_id);
+ let trait_id = impl_datum.trait_id();
+
+ let impl_goal = Goal::all(
+ interner,
+ impl_header_wf_goal(self.db, impl_id).into_iter().chain(
+ impl_datum
+ .associated_ty_value_ids
+ .iter()
+ .filter_map(|&id| compute_assoc_ty_goal(self.db, id)),
+ ),
+ );
+
+ if let Some(well_known) = self.db.trait_datum(trait_id).well_known {
+ self.verify_well_known_impl(impl_id, well_known)?
+ }
+
+ debug!("WF trait goal: {:?}", impl_goal);
+
+ let mut fresh_solver = (self.solver_builder)();
+ let is_legal =
+ fresh_solver.has_unique_solution(self.db, &impl_goal.into_closed_goal(interner));
+
+ if is_legal {
+ Ok(())
+ } else {
+ Err(WfError::IllFormedTraitImpl(trait_id))
+ }
+ }
+
+ pub fn verify_opaque_ty_decl(&self, opaque_ty_id: OpaqueTyId<I>) -> Result<(), WfError<I>> {
+ // Given an opaque type like
+ // ```notrust
+ // opaque type Foo<T>: Clone where T: Bar = Baz;
+ // ```
+ let interner = self.db.interner();
+
+ let mut gb = GoalBuilder::new(self.db);
+
+ let datum = self.db.opaque_ty_data(opaque_ty_id);
+ let bound = &datum.bound;
+
+ // We make a goal like
+ //
+ // forall<T>
+ let goal = gb.forall(bound, opaque_ty_id, |gb, _, bound, opaque_ty_id| {
+ let interner = gb.interner();
+
+ let subst = Substitution::from1(interner, gb.db().hidden_opaque_type(opaque_ty_id));
+
+ let bounds = bound.bounds.clone().substitute(interner, &subst);
+ let where_clauses = bound.where_clauses.clone().substitute(interner, &subst);
+
+ let clauses = where_clauses
+ .iter()
+ .cloned()
+ .map(|wc| wc.into_from_env_goal(interner));
+
+ // if (WellFormed(T: Bar))
+ gb.implies(clauses, |gb| {
+ let interner = gb.interner();
+
+ // all(WellFormed(Baz: Clone))
+ gb.all(
+ bounds
+ .iter()
+ .cloned()
+ .map(|b| b.into_well_formed_goal(interner)),
+ )
+ })
+ });
+
+ debug!("WF opaque type goal: {:#?}", goal);
+
+ let mut new_solver = (self.solver_builder)();
+ let is_legal = new_solver.has_unique_solution(self.db, &goal.into_closed_goal(interner));
+
+ if is_legal {
+ Ok(())
+ } else {
+ Err(WfError::IllFormedOpaqueTypeDecl(opaque_ty_id))
+ }
+ }
+
+ /// Verify builtin rules for well-known traits
+ pub fn verify_well_known_impl(
+ &self,
+ impl_id: ImplId<I>,
+ well_known: WellKnownTrait,
+ ) -> Result<(), WfError<I>> {
+ let mut solver = (self.solver_builder)();
+ let impl_datum = self.db.impl_datum(impl_id);
+
+ let is_legal = match well_known {
+ WellKnownTrait::Copy => {
+ WfWellKnownConstraints::copy_impl_constraint(&mut *solver, self.db, &impl_datum)
+ }
+ WellKnownTrait::Drop => {
+ WfWellKnownConstraints::drop_impl_constraint(&mut *solver, self.db, &impl_datum)
+ }
+ WellKnownTrait::CoerceUnsized => {
+ WfWellKnownConstraints::coerce_unsized_impl_constraint(
+ &mut *solver,
+ self.db,
+ &impl_datum,
+ )
+ }
+ WellKnownTrait::DispatchFromDyn => {
+ WfWellKnownConstraints::dispatch_from_dyn_constraint(
+ &mut *solver,
+ self.db,
+ &impl_datum,
+ )
+ }
+ WellKnownTrait::Clone | WellKnownTrait::Unpin => true,
+ // You can't add a manual implementation for the following traits:
+ WellKnownTrait::Fn
+ | WellKnownTrait::FnOnce
+ | WellKnownTrait::FnMut
+ | WellKnownTrait::Unsize
+ | WellKnownTrait::Sized
+ | WellKnownTrait::DiscriminantKind
+ | WellKnownTrait::Generator
+ | WellKnownTrait::Tuple => false,
+ };
+
+ if is_legal {
+ Ok(())
+ } else {
+ Err(WfError::IllFormedTraitImpl(impl_datum.trait_id()))
+ }
+ }
+}
+
+fn impl_header_wf_goal<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ impl_id: ImplId<I>,
+) -> Option<Goal<I>> {
+ let impl_datum = db.impl_datum(impl_id);
+
+ if !impl_datum.is_positive() {
+ return None;
+ }
+
+ let impl_fields = impl_datum
+ .binders
+ .map_ref(|v| (&v.trait_ref, &v.where_clauses));
+
+ let mut gb = GoalBuilder::new(db);
+ // forall<P0...Pn> {...}
+ let well_formed_goal = gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
+ let interner = gb.interner();
+
+ // if (WC && input types are well formed) { ... }
+ gb.implies(
+ impl_wf_environment(interner, where_clauses, trait_ref),
+ |gb| {
+ // We retrieve all the input types of the where clauses appearing on the trait impl,
+ // e.g. in:
+ // ```
+ // impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
+ // ```
+ // we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
+ // We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
+ // bound would be needed here).
+ let types = InputTypeCollector::types_in(gb.interner(), &where_clauses);
+
+ // Things to prove well-formed: input types of the where-clauses, projection types
+ // appearing in the header, associated type values, and of course the trait ref.
+ debug!(input_types=?types);
+ let goals = types
+ .into_iter()
+ .map(|ty| ty.well_formed().cast(interner))
+ .chain(Some((*trait_ref).clone().well_formed().cast(interner)));
+
+ gb.all::<_, Goal<I>>(goals)
+ },
+ )
+ });
+
+ Some(well_formed_goal)
+}
+
+/// Creates the conditions that an impl (and its contents of an impl)
+/// can assume to be true when proving that it is well-formed.
+fn impl_wf_environment<'i, I: Interner>(
+ interner: I,
+ where_clauses: &'i [QuantifiedWhereClause<I>],
+ trait_ref: &'i TraitRef<I>,
+) -> impl Iterator<Item = ProgramClause<I>> + 'i {
+ // if (WC) { ... }
+ let wc = where_clauses
+ .iter()
+ .cloned()
+ .map(move |qwc| qwc.into_from_env_goal(interner).cast(interner));
+
+ // We retrieve all the input types of the type on which we implement the trait: we will
+ // *assume* that these types are well-formed, e.g. we will be able to derive that
+ // `K: Hash` holds without writing any where clause.
+ //
+ // Example:
+ // ```
+ // struct HashSet<K> where K: Hash { ... }
+ //
+ // impl<K> Foo for HashSet<K> {
+ // // Inside here, we can rely on the fact that `K: Hash` holds
+ // }
+ // ```
+ let types = InputTypeCollector::types_in(interner, trait_ref);
+
+ let types_wf = types
+ .into_iter()
+ .map(move |ty| ty.into_from_env_goal(interner).cast(interner));
+
+ wc.chain(types_wf)
+}
+
+/// Associated type values are special because they can be parametric (independently of
+/// the impl), so we issue a special goal which is quantified using the binders of the
+/// associated type value, for example in:
+///
+/// ```ignore
+/// trait Foo {
+/// type Item<'a>: Clone where Self: 'a
+/// }
+///
+/// impl<T> Foo for Box<T> {
+/// type Item<'a> = Box<&'a T>;
+/// }
+/// ```
+///
+/// we would issue the following subgoal: `forall<'a> { WellFormed(Box<&'a T>) }`.
+///
+/// Note that there is no binder for `T` in the above: the goal we
+/// generate is expected to be exected in the context of the
+/// larger WF goal for the impl, which already has such a
+/// binder. So the entire goal for the impl might be:
+///
+/// ```ignore
+/// forall<T> {
+/// WellFormed(Box<T>) /* this comes from the impl, not this routine */,
+/// forall<'a> { WellFormed(Box<&'a T>) },
+/// }
+/// ```
+fn compute_assoc_ty_goal<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ assoc_ty_id: AssociatedTyValueId<I>,
+) -> Option<Goal<I>> {
+ let mut gb = GoalBuilder::new(db);
+ let assoc_ty = &db.associated_ty_value(assoc_ty_id);
+
+ // Create `forall<T, 'a> { .. }`
+ Some(gb.forall(
+ &assoc_ty.value.map_ref(|v| &v.ty),
+ assoc_ty_id,
+ |gb, assoc_ty_substitution, value_ty, assoc_ty_id| {
+ let interner = gb.interner();
+ let db = gb.db();
+
+ // Hmm, because `Arc<AssociatedTyValue>` does not implement `TypeFoldable`, we can't pass this value through,
+ // just the id, so we have to fetch `assoc_ty` from the database again.
+ // Implementing `TypeFoldable` for `AssociatedTyValue` doesn't *quite* seem right though, as that
+ // would result in a deep clone, and the value is inert. We could do some more refatoring
+ // (move the `Arc` behind a newtype, for example) to fix this, but for now doesn't
+ // seem worth it.
+ let assoc_ty = &db.associated_ty_value(assoc_ty_id);
+
+ let (impl_parameters, projection) = db
+ .impl_parameters_and_projection_from_associated_ty_value(
+ assoc_ty_substitution.as_slice(interner),
+ assoc_ty,
+ );
+
+ // If (/* impl WF environment */) { ... }
+ let impl_id = assoc_ty.impl_id;
+ let impl_datum = &db.impl_datum(impl_id);
+ let ImplDatumBound {
+ trait_ref: impl_trait_ref,
+ where_clauses: impl_where_clauses,
+ } = impl_datum
+ .binders
+ .clone()
+ .substitute(interner, impl_parameters);
+ let impl_wf_clauses =
+ impl_wf_environment(interner, &impl_where_clauses, &impl_trait_ref);
+ gb.implies(impl_wf_clauses, |gb| {
+ // Get the bounds and where clauses from the trait
+ // declaration, substituted appropriately.
+ //
+ // From our example:
+ //
+ // * bounds
+ // * original in trait, `Clone`
+ // * after substituting impl parameters, `Clone`
+ // * note that the self-type is not yet supplied for bounds,
+ // we will do that later
+ // * where clauses
+ // * original in trait, `Self: 'a`
+ // * after substituting impl parameters, `Box<!T>: '!a`
+ let assoc_ty_datum = db.associated_ty_data(projection.associated_ty_id);
+ let AssociatedTyDatumBound {
+ bounds: defn_bounds,
+ where_clauses: defn_where_clauses,
+ } = assoc_ty_datum
+ .binders
+ .clone()
+ .substitute(interner, &projection.substitution);
+
+ // Create `if (/* where clauses on associated type value */) { .. }`
+ gb.implies(
+ defn_where_clauses
+ .iter()
+ .cloned()
+ .map(|qwc| qwc.into_from_env_goal(interner)),
+ |gb| {
+ let types = InputTypeCollector::types_in(gb.interner(), value_ty);
+
+ // We require that `WellFormed(T)` for each type that appears in the value
+ let wf_goals = types
+ .into_iter()
+ .map(|ty| ty.well_formed())
+ .casted(interner);
+
+ // Check that the `value_ty` meets the bounds from the trait.
+ // Here we take the substituted bounds (`defn_bounds`) and we
+ // supply the self-type `value_ty` to yield the final result.
+ //
+ // In our example, the bound was `Clone`, so the combined
+ // result is `Box<!T>: Clone`. This is then converted to a
+ // well-formed goal like `WellFormed(Box<!T>: Clone)`.
+ let bound_goals = defn_bounds
+ .iter()
+ .cloned()
+ .flat_map(|qb| qb.into_where_clauses(interner, (*value_ty).clone()))
+ .map(|qwc| qwc.into_well_formed_goal(interner))
+ .casted(interner);
+
+ // Concatenate the WF goals of inner types + the requirements from trait
+ gb.all::<_, Goal<I>>(wf_goals.chain(bound_goals))
+ },
+ )
+ })
+ },
+ ))
+}
+
+/// Defines methods to compute well-formedness goals for well-known
+/// traits (e.g. a goal for all fields of struct in a Copy impl to be Copy)
+struct WfWellKnownConstraints;
+
+impl WfWellKnownConstraints {
+ /// Computes a goal to prove Sized constraints on a struct definition.
+ /// Struct is considered well-formed (in terms of Sized) when it either
+ /// has no fields or all of it's fields except the last are proven to be Sized.
+ pub fn struct_sized_constraint<I: Interner>(
+ db: &dyn RustIrDatabase<I>,
+ fields: &[Ty<I>],
+ size_all: bool,
+ ) -> Option<Goal<I>> {
+ let excluded = if size_all { 0 } else { 1 };
+
+ if fields.len() <= excluded {
+ return None;
+ }
+
+ let interner = db.interner();
+
+ let sized_trait = db.well_known_trait_id(WellKnownTrait::Sized)?;
+
+ Some(Goal::all(
+ interner,
+ fields[..fields.len() - excluded].iter().map(|ty| {
+ TraitRef {
+ trait_id: sized_trait,
+ substitution: Substitution::from1(interner, ty.clone()),
+ }
+ .cast(interner)
+ }),
+ ))
+ }
+
+ /// Verify constraints on a Copy implementation.
+ /// Copy impl is considered well-formed for
+ /// a) certain builtin types (scalar values, shared ref, etc..)
+ /// b) adts which
+ /// 1) have all Copy fields
+ /// 2) don't have a Drop impl
+ fn copy_impl_constraint<I: Interner>(
+ solver: &mut dyn Solver<I>,
+ db: &dyn RustIrDatabase<I>,
+ impl_datum: &ImplDatum<I>,
+ ) -> bool {
+ let interner = db.interner();
+
+ let mut gb = GoalBuilder::new(db);
+
+ let impl_fields = impl_datum
+ .binders
+ .map_ref(|v| (&v.trait_ref, &v.where_clauses));
+
+ // Implementations for scalars, pointer types and never type are provided by libcore.
+ // User implementations on types other than ADTs are forbidden.
+ match impl_datum
+ .binders
+ .skip_binders()
+ .trait_ref
+ .self_type_parameter(interner)
+ .kind(interner)
+ {
+ TyKind::Scalar(_)
+ | TyKind::Raw(_, _)
+ | TyKind::Ref(Mutability::Not, _, _)
+ | TyKind::Never => return true,
+
+ TyKind::Adt(_, _) => (),
+
+ _ => return false,
+ };
+
+ // Well fomedness goal for ADTs
+ let well_formed_goal =
+ gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
+ let interner = gb.interner();
+
+ let ty = trait_ref.self_type_parameter(interner);
+
+ let (adt_id, substitution) = match ty.kind(interner) {
+ TyKind::Adt(adt_id, substitution) => (*adt_id, substitution),
+
+ _ => unreachable!(),
+ };
+
+ // if (WC) { ... }
+ gb.implies(
+ impl_wf_environment(interner, where_clauses, trait_ref),
+ |gb| -> Goal<I> {
+ let db = gb.db();
+
+ // not { Implemented(ImplSelfTy: Drop) }
+ let neg_drop_goal =
+ db.well_known_trait_id(WellKnownTrait::Drop)
+ .map(|drop_trait_id| {
+ TraitRef {
+ trait_id: drop_trait_id,
+ substitution: Substitution::from1(interner, ty.clone()),
+ }
+ .cast::<Goal<I>>(interner)
+ .negate(interner)
+ });
+
+ let adt_datum = db.adt_datum(adt_id);
+
+ let goals = adt_datum
+ .binders
+ .map_ref(|b| &b.variants)
+ .cloned()
+ .substitute(interner, substitution)
+ .into_iter()
+ .flat_map(|v| {
+ v.fields.into_iter().map(|f| {
+ // Implemented(FieldTy: Copy)
+ TraitRef {
+ trait_id: trait_ref.trait_id,
+ substitution: Substitution::from1(interner, f),
+ }
+ .cast(interner)
+ })
+ })
+ .chain(neg_drop_goal.into_iter());
+ gb.all(goals)
+ },
+ )
+ });
+
+ solver.has_unique_solution(db, &well_formed_goal.into_closed_goal(interner))
+ }
+
+ /// Verifies constraints on a Drop implementation
+ /// Drop implementation is considered well-formed if:
+ /// a) it's implemented on an ADT
+ /// b) The generic parameters of the impl's type must all be parameters
+ /// of the Drop impl itself (i.e., no specialization like
+ /// `impl Drop for S<Foo> {...}` is allowed).
+ /// c) Any bounds on the genereic parameters of the impl must be
+ /// deductible from the bounds imposed by the struct definition
+ /// (i.e. the implementation must be exactly as generic as the ADT definition).
+ ///
+ /// ```rust,ignore
+ /// struct S<T1, T2> { }
+ /// struct Foo<T> { }
+ ///
+ /// impl<U1: Copy, U2: Sized> Drop for S<U2, Foo<U1>> { }
+ /// ```
+ ///
+ /// generates the following:
+ /// goal derived from c):
+ ///
+ /// ```notrust
+ /// forall<U1, U2> {
+ /// Implemented(U1: Copy), Implemented(U2: Sized) :- FromEnv(S<U2, Foo<U1>>)
+ /// }
+ /// ```
+ ///
+ /// goal derived from b):
+ /// ```notrust
+ /// forall <T1, T2> {
+ /// exists<U1, U2> {
+ /// S<T1, T2> = S<U2, Foo<U1>>
+ /// }
+ /// }
+ /// ```
+ fn drop_impl_constraint<I: Interner>(
+ solver: &mut dyn Solver<I>,
+ db: &dyn RustIrDatabase<I>,
+ impl_datum: &ImplDatum<I>,
+ ) -> bool {
+ let interner = db.interner();
+
+ let adt_id = match impl_datum.self_type_adt_id(interner) {
+ Some(id) => id,
+ // Drop can only be implemented on a nominal type
+ None => return false,
+ };
+
+ let mut gb = GoalBuilder::new(db);
+
+ let adt_datum = db.adt_datum(adt_id);
+
+ let impl_fields = impl_datum
+ .binders
+ .map_ref(|v| (&v.trait_ref, &v.where_clauses));
+
+ // forall<ImplP1...ImplPn> { .. }
+ let implied_by_adt_def_goal =
+ gb.forall(&impl_fields, (), |gb, _, (trait_ref, where_clauses), ()| {
+ let interner = gb.interner();
+
+ // FromEnv(ImplSelfType) => ...
+ gb.implies(
+ iter::once(
+ FromEnv::Ty(trait_ref.self_type_parameter(interner))
+ .cast::<DomainGoal<I>>(interner),
+ ),
+ |gb| {
+ // All(ImplWhereClauses)
+ gb.all(
+ where_clauses
+ .iter()
+ .map(|wc| wc.clone().into_well_formed_goal(interner)),
+ )
+ },
+ )
+ });
+
+ let impl_self_ty = impl_datum
+ .binders
+ .map_ref(|b| b.trait_ref.self_type_parameter(interner));
+
+ // forall<StructP1..StructPN> {...}
+ let eq_goal = gb.forall(
+ &adt_datum.binders,
+ (adt_id, impl_self_ty),
+ |gb, substitution, _, (adt_id, impl_self_ty)| {
+ let interner = gb.interner();
+
+ let def_adt = TyKind::Adt(adt_id, substitution).intern(interner);
+
+ // exists<ImplP1...ImplPn> { .. }
+ gb.exists(&impl_self_ty, def_adt, |gb, _, impl_adt, def_adt| {
+ let interner = gb.interner();
+
+ // StructName<StructP1..StructPn> = ImplSelfType
+ GoalData::EqGoal(EqGoal {
+ a: GenericArgData::Ty(def_adt).intern(interner),
+ b: GenericArgData::Ty(impl_adt.clone()).intern(interner),
+ })
+ .intern(interner)
+ })
+ },
+ );
+
+ let well_formed_goal = gb.all([implied_by_adt_def_goal, eq_goal].iter());
+
+ solver.has_unique_solution(db, &well_formed_goal.into_closed_goal(interner))
+ }
+
+ /// Verify constraints a CoerceUnsized impl.
+ /// Rules for CoerceUnsized impl to be considered well-formed:
+ /// 1) pointer conversions: `&[mut] T -> &[mut] U`, `&[mut] T -> *[mut] U`,
+ /// `*[mut] T -> *[mut] U` are considered valid if
+ /// 1) `T: Unsize<U>`
+ /// 2) mutability is respected, i.e. immutable -> immutable, mutable -> immutable,
+ /// mutable -> mutable conversions are allowed, immutable -> mutable is not.
+ /// 2) struct conversions of structures with the same definition, `S<P0...Pn>` -> `S<Q0...Qn>`.
+ /// To check if this impl is legal, we would walk down the fields of `S`
+ /// and consider their types with both substitutes. We are looking to find
+ /// exactly one (non-phantom) field that has changed its type (from `T` to `U`), and
+ /// expect `T` to be unsizeable to `U`, i.e. `T: CoerceUnsized<U>`.
+ ///
+ /// As an example, consider a struct
+ /// ```rust
+ /// struct Foo<T, U> {
+ /// extra: T,
+ /// ptr: *mut U,
+ /// }
+ /// ```
+ ///
+ /// We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
+ /// to `Foo<T, [i32]>`. That impl would look like:
+ /// ```rust,ignore
+ /// impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
+ /// ```
+ /// In this case:
+ ///
+ /// - `extra` has type `T` before and type `T` after
+ /// - `ptr` has type `*mut U` before and type `*mut V` after
+ ///
+ /// Since just one field changed, we would then check that `*mut U: CoerceUnsized<*mut V>`
+ /// is implemented. This will work out because `U: Unsize<V>`, and we have a libcore rule
+ /// that `*mut U` can be coerced to `*mut V` if `U: Unsize<V>`.
+ fn coerce_unsized_impl_constraint<I: Interner>(
+ solver: &mut dyn Solver<I>,
+ db: &dyn RustIrDatabase<I>,
+ impl_datum: &ImplDatum<I>,
+ ) -> bool {
+ let interner = db.interner();
+ let mut gb = GoalBuilder::new(db);
+
+ let (binders, impl_datum) = impl_datum.binders.as_ref().into();
+
+ let trait_ref: &TraitRef<I> = &impl_datum.trait_ref;
+
+ let source = trait_ref.self_type_parameter(interner);
+ let target = trait_ref
+ .substitution
+ .at(interner, 1)
+ .assert_ty_ref(interner)
+ .clone();
+
+ let mut place_in_environment = |goal| -> Goal<I> {
+ gb.forall(
+ &Binders::new(
+ binders.clone(),
+ (goal, trait_ref, &impl_datum.where_clauses),
+ ),
+ (),
+ |gb, _, (goal, trait_ref, where_clauses), ()| {
+ let interner = gb.interner();
+ gb.implies(
+ impl_wf_environment(interner, where_clauses, trait_ref),
+ |_| goal,
+ )
+ },
+ )
+ };
+
+ match (source.kind(interner), target.kind(interner)) {
+ (TyKind::Ref(s_m, _, source), TyKind::Ref(t_m, _, target))
+ | (TyKind::Ref(s_m, _, source), TyKind::Raw(t_m, target))
+ | (TyKind::Raw(s_m, source), TyKind::Raw(t_m, target)) => {
+ if (*s_m, *t_m) == (Mutability::Not, Mutability::Mut) {
+ return false;
+ }
+
+ let unsize_trait_id =
+ if let Some(id) = db.well_known_trait_id(WellKnownTrait::Unsize) {
+ id
+ } else {
+ return false;
+ };
+
+ // Source: Unsize<Target>
+ let unsize_goal: Goal<I> = TraitRef {
+ trait_id: unsize_trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ [source.clone(), target.clone()].iter().cloned(),
+ ),
+ }
+ .cast(interner);
+
+ // ImplEnv -> Source: Unsize<Target>
+ let unsize_goal = place_in_environment(unsize_goal);
+
+ solver.has_unique_solution(db, &unsize_goal.into_closed_goal(interner))
+ }
+ (TyKind::Adt(source_id, subst_a), TyKind::Adt(target_id, subst_b)) => {
+ let adt_datum = db.adt_datum(*source_id);
+
+ if source_id != target_id || adt_datum.kind != AdtKind::Struct {
+ return false;
+ }
+
+ let fields = adt_datum
+ .binders
+ .map_ref(|bound| &bound.variants.last().unwrap().fields)
+ .cloned();
+
+ let (source_fields, target_fields) = (
+ fields.clone().substitute(interner, subst_a),
+ fields.substitute(interner, subst_b),
+ );
+
+ // collect fields with unequal ids
+ let uneq_field_ids: Vec<usize> = (0..source_fields.len())
+ .filter(|&i| {
+ // ignore phantom data fields
+ if let Some(adt_id) = source_fields[i].adt_id(interner) {
+ if db.adt_datum(adt_id).flags.phantom_data {
+ return false;
+ }
+ }
+
+ let eq_goal: Goal<I> = EqGoal {
+ a: source_fields[i].clone().cast(interner),
+ b: target_fields[i].clone().cast(interner),
+ }
+ .cast(interner);
+
+ // ImplEnv -> Source.fields[i] = Target.fields[i]
+ let eq_goal = place_in_environment(eq_goal);
+
+ // We are interested in !UNEQUAL! fields
+ !solver.has_unique_solution(db, &eq_goal.into_closed_goal(interner))
+ })
+ .collect();
+
+ if uneq_field_ids.len() != 1 {
+ return false;
+ }
+
+ let field_id = uneq_field_ids[0];
+
+ // Source.fields[i]: CoerceUnsized<TargetFields[i]>
+ let coerce_unsized_goal: Goal<I> = TraitRef {
+ trait_id: trait_ref.trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ [
+ source_fields[field_id].clone(),
+ target_fields[field_id].clone(),
+ ]
+ .iter()
+ .cloned(),
+ ),
+ }
+ .cast(interner);
+
+ // ImplEnv -> Source.fields[i]: CoerceUnsized<TargetFields[i]>
+ let coerce_unsized_goal = place_in_environment(coerce_unsized_goal);
+
+ solver.has_unique_solution(db, &coerce_unsized_goal.into_closed_goal(interner))
+ }
+ _ => false,
+ }
+ }
+
+ /// Verify constraints of a DispatchFromDyn impl.
+ ///
+ /// Rules for DispatchFromDyn impl to be considered well-formed:
+ ///
+ /// * Self and the type parameter must both be references or raw pointers with the same mutabilty
+ /// * OR all the following hold:
+ /// - Self and the type parameter must be structs
+ /// - Self and the type parameter must have the same definitions
+ /// - Self must not be `#[repr(packed)]` or `#[repr(C)]`
+ /// - Self must have exactly one field which is not a 1-ZST (there may be any number of 1-ZST
+ /// fields), and that field must have a different type in the type parameter (i.e., it is
+ /// the field being coerced)
+ /// - `DispatchFromDyn` is implemented for the type of the field being coerced.
+ fn dispatch_from_dyn_constraint<I: Interner>(
+ solver: &mut dyn Solver<I>,
+ db: &dyn RustIrDatabase<I>,
+ impl_datum: &ImplDatum<I>,
+ ) -> bool {
+ let interner = db.interner();
+ let mut gb = GoalBuilder::new(db);
+
+ let (binders, impl_datum) = impl_datum.binders.as_ref().into();
+
+ let trait_ref: &TraitRef<I> = &impl_datum.trait_ref;
+
+ // DispatchFromDyn specifies that Self (source) can be coerced to T (target; its single type parameter).
+ let source = trait_ref.self_type_parameter(interner);
+ let target = trait_ref
+ .substitution
+ .at(interner, 1)
+ .assert_ty_ref(interner)
+ .clone();
+
+ let mut place_in_environment = |goal| -> Goal<I> {
+ gb.forall(
+ &Binders::new(
+ binders.clone(),
+ (goal, trait_ref, &impl_datum.where_clauses),
+ ),
+ (),
+ |gb, _, (goal, trait_ref, where_clauses), ()| {
+ let interner = gb.interner();
+ gb.implies(
+ impl_wf_environment(interner, &where_clauses, &trait_ref),
+ |_| goal,
+ )
+ },
+ )
+ };
+
+ match (source.kind(interner), target.kind(interner)) {
+ (TyKind::Ref(s_m, _, _), TyKind::Ref(t_m, _, _))
+ | (TyKind::Raw(s_m, _), TyKind::Raw(t_m, _))
+ if s_m == t_m =>
+ {
+ true
+ }
+ (TyKind::Adt(source_id, subst_a), TyKind::Adt(target_id, subst_b)) => {
+ let adt_datum = db.adt_datum(*source_id);
+
+ // Definitions are equal and are structs.
+ if source_id != target_id || adt_datum.kind != AdtKind::Struct {
+ return false;
+ }
+
+ // Not repr(C) or repr(packed).
+ let repr = db.adt_repr(*source_id);
+ if repr.c || repr.packed {
+ return false;
+ }
+
+ // Collect non 1-ZST fields; there must be exactly one.
+ let fields = adt_datum
+ .binders
+ .map_ref(|bound| &bound.variants.last().unwrap().fields)
+ .cloned();
+
+ let (source_fields, target_fields) = (
+ fields.clone().substitute(interner, subst_a),
+ fields.substitute(interner, subst_b),
+ );
+
+ let mut non_zst_fields: Vec<_> = source_fields
+ .iter()
+ .zip(target_fields.iter())
+ .filter(|(sf, _)| match sf.adt_id(interner) {
+ Some(adt) => !db.adt_size_align(adt).one_zst(),
+ None => true,
+ })
+ .collect();
+
+ if non_zst_fields.len() != 1 {
+ return false;
+ }
+
+ // The field being coerced (the interesting field).
+ let (field_src, field_tgt) = non_zst_fields.pop().unwrap();
+
+ // The interesting field is different in the source and target types.
+ let eq_goal: Goal<I> = EqGoal {
+ a: field_src.clone().cast(interner),
+ b: field_tgt.clone().cast(interner),
+ }
+ .cast(interner);
+ let eq_goal = place_in_environment(eq_goal);
+ if solver.has_unique_solution(db, &eq_goal.into_closed_goal(interner)) {
+ return false;
+ }
+
+ // Type(field_src): DispatchFromDyn<Type(field_tgt)>
+ let field_dispatch_goal: Goal<I> = TraitRef {
+ trait_id: trait_ref.trait_id,
+ substitution: Substitution::from_iter(
+ interner,
+ [field_src.clone(), field_tgt.clone()].iter().cloned(),
+ ),
+ }
+ .cast(interner);
+ let field_dispatch_goal = place_in_environment(field_dispatch_goal);
+ if !solver.has_unique_solution(db, &field_dispatch_goal.into_closed_goal(interner))
+ {
+ return false;
+ }
+
+ true
+ }
+ _ => false,
+ }
+ }
+}