diff --git a/chalk-integration/src/db.rs b/chalk-integration/src/db.rs index 22e3362e582..4fa796d099d 100644 --- a/chalk-integration/src/db.rs +++ b/chalk-integration/src/db.rs @@ -15,7 +15,7 @@ use chalk_ir::{ use chalk_solve::rust_ir::{ AdtDatum, AdtRepr, AdtSizeAlign, AssociatedTyDatum, AssociatedTyValue, AssociatedTyValueId, ClosureKind, CoroutineDatum, CoroutineWitnessDatum, FnDefDatum, FnDefInputsAndOutputDatum, - ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownTrait, + ImplDatum, OpaqueTyDatum, TraitDatum, WellKnownAssocType, WellKnownTrait, }; use chalk_solve::{RustIrDatabase, Solution, SubstitutionResult}; use salsa::Database; @@ -183,6 +183,15 @@ impl RustIrDatabase for ChalkDatabase { .well_known_trait_id(well_known_trait) } + fn well_known_assoc_type_id( + &self, + assoc_type: WellKnownAssocType, + ) -> Option> { + self.program_ir() + .unwrap() + .well_known_assoc_type_id(assoc_type) + } + fn program_clauses_for_env( &self, environment: &Environment, diff --git a/chalk-integration/src/program.rs b/chalk-integration/src/program.rs index 01fd6e74ca7..2444de91946 100644 --- a/chalk-integration/src/program.rs +++ b/chalk-integration/src/program.rs @@ -537,6 +537,14 @@ impl RustIrDatabase for Program { self.well_known_traits.get(&well_known_trait).copied() } + fn well_known_assoc_type_id( + &self, + _assoc_type: chalk_solve::rust_ir::WellKnownAssocType, + ) -> Option> { + // FIXME + None + } + fn program_clauses_for_env( &self, environment: &chalk_ir::Environment, diff --git a/chalk-solve/src/clauses/builtin_traits/fn_family.rs b/chalk-solve/src/clauses/builtin_traits/fn_family.rs index 7e8ce7aa1e9..72d88c4612f 100644 --- a/chalk-solve/src/clauses/builtin_traits/fn_family.rs +++ b/chalk-solve/src/clauses/builtin_traits/fn_family.rs @@ -1,5 +1,5 @@ use crate::clauses::ClauseBuilder; -use crate::rust_ir::{ClosureKind, FnDefInputsAndOutputDatum, WellKnownTrait}; +use crate::rust_ir::{ClosureKind, FnDefInputsAndOutputDatum, WellKnownAssocType, WellKnownTrait}; use crate::{Interner, RustIrDatabase, TraitRef}; use chalk_ir::cast::Cast; use chalk_ir::{ @@ -83,14 +83,9 @@ fn push_clauses( if let WellKnownTrait::AsyncFnOnce = well_known { builder.push_bound_ty(|builder, ty| { - let trait_datum = db.trait_datum(trait_id); - assert_eq!( - trait_datum.associated_ty_ids.len(), - 2, - "AsyncFnOnce trait should have exactly two associated types, found {:?}", - trait_datum.associated_ty_ids - ); - let output_id = trait_datum.associated_ty_ids[1]; + let output_id = db + .well_known_assoc_type_id(WellKnownAssocType::AsyncFnOnceOutput) + .unwrap(); let async_alias = AliasTy::Projection(ProjectionTy { associated_ty_id: output_id, substitution, diff --git a/chalk-solve/src/display/stub.rs b/chalk-solve/src/display/stub.rs index 2535eee9c5f..bffa5b4c227 100644 --- a/chalk-solve/src/display/stub.rs +++ b/chalk-solve/src/display/stub.rs @@ -188,6 +188,13 @@ impl> RustIrDatabase for StubWrapper<'_, D self.db.well_known_trait_id(well_known_trait) } + fn well_known_assoc_type_id( + &self, + assoc_type: crate::rust_ir::WellKnownAssocType, + ) -> Option> { + self.db.well_known_assoc_type_id(assoc_type) + } + fn program_clauses_for_env( &self, environment: &chalk_ir::Environment, diff --git a/chalk-solve/src/lib.rs b/chalk-solve/src/lib.rs index e2c8f075f96..a02a6f59ca8 100644 --- a/chalk-solve/src/lib.rs +++ b/chalk-solve/src/lib.rs @@ -128,6 +128,9 @@ pub trait RustIrDatabase: Debug { /// Returns id of a trait lang item, if found fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option>; + /// Returns id of a associated type, if found. + fn well_known_assoc_type_id(&self, assoc_type: WellKnownAssocType) -> Option>; + /// 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) -> ProgramClauses; diff --git a/chalk-solve/src/logging_db.rs b/chalk-solve/src/logging_db.rs index 83da075b7fc..b37b2bd4e03 100644 --- a/chalk-solve/src/logging_db.rs +++ b/chalk-solve/src/logging_db.rs @@ -229,6 +229,14 @@ where trait_id } + fn well_known_assoc_type_id(&self, assoc_type: WellKnownAssocType) -> Option> { + let assoc_type_id = self.ws.db().well_known_assoc_type_id(assoc_type); + if let Some(id) = assoc_type_id { + self.record(self.ws.db().associated_ty_data(id).trait_id); + } + assoc_type_id + } + fn program_clauses_for_env( &self, environment: &chalk_ir::Environment, @@ -489,6 +497,10 @@ where self.db.well_known_trait_id(well_known_trait) } + fn well_known_assoc_type_id(&self, assoc_type: WellKnownAssocType) -> Option> { + self.db.well_known_assoc_type_id(assoc_type) + } + fn program_clauses_for_env( &self, environment: &chalk_ir::Environment, diff --git a/chalk-solve/src/rust_ir.rs b/chalk-solve/src/rust_ir.rs index ea6514f91eb..643a0124551 100644 --- a/chalk-solve/src/rust_ir.rs +++ b/chalk-solve/src/rust_ir.rs @@ -287,6 +287,15 @@ pub enum WellKnownTrait { chalk_ir::const_visit!(WellKnownTrait); +/// A list of the associated types 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 WellKnownAssocType { + AsyncFnOnceOutput, +} + +chalk_ir::const_visit!(WellKnownAssocType); + impl TraitDatum { pub fn is_auto_trait(&self) -> bool { self.flags.auto diff --git a/tests/display/unique_names.rs b/tests/display/unique_names.rs index f657f3f0455..c97fcc505af 100644 --- a/tests/display/unique_names.rs +++ b/tests/display/unique_names.rs @@ -155,6 +155,12 @@ where ) -> Option> { self.db.well_known_trait_id(well_known_trait) } + fn well_known_assoc_type_id( + &self, + assoc_type: chalk_solve::rust_ir::WellKnownAssocType, + ) -> Option> { + self.db.well_known_assoc_type_id(assoc_type) + } fn program_clauses_for_env( &self, environment: &chalk_ir::Environment, diff --git a/tests/integration/panic.rs b/tests/integration/panic.rs index 2bd86c8dff4..9606f24754a 100644 --- a/tests/integration/panic.rs +++ b/tests/integration/panic.rs @@ -211,6 +211,13 @@ impl RustIrDatabase for MockDatabase { unimplemented!() } + fn well_known_assoc_type_id( + &self, + assoc_type: WellKnownAssocType, + ) -> Option> { + unimplemented!() + } + fn program_clauses_for_env( &self, environment: &Environment,