diff --git a/chalk-integration/src/db.rs b/chalk-integration/src/db.rs index fda52182653..c36c02ed929 100644 --- a/chalk-integration/src/db.rs +++ b/chalk-integration/src/db.rs @@ -199,7 +199,7 @@ impl RustIrDatabase for ChalkDatabase { &self, closure_id: ClosureId, substs: &Substitution, - ) -> ClosureKind { + ) -> Option { self.program_ir().unwrap().closure_kind(closure_id, substs) } diff --git a/chalk-integration/src/program.rs b/chalk-integration/src/program.rs index b82bd9db99e..a96b7fcd7a7 100644 --- a/chalk-integration/src/program.rs +++ b/chalk-integration/src/program.rs @@ -557,7 +557,7 @@ impl RustIrDatabase for Program { &self, closure_id: ClosureId, _substs: &Substitution, - ) -> ClosureKind { + ) -> Option { self.closure_closure_kind[&closure_id] } diff --git a/chalk-solve/src/clauses.rs b/chalk-solve/src/clauses.rs index e3fdd351b7a..039d981d0f8 100644 --- a/chalk-solve/src/clauses.rs +++ b/chalk-solve/src/clauses.rs @@ -164,6 +164,7 @@ pub fn push_auto_trait_impls( 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); + debug!(?binders, ?closure_fn_substitution); 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 @@ -1062,9 +1063,12 @@ fn match_ty( 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::>(interner)]); + let dyn_ty_ty = chalk_ir::Ty::new(interner, TyKind::Dyn(dyn_ty.clone())); + let arg: chalk_ir::GenericArg = chalk_ir::GenericArg::new( + interner, + chalk_ir::GenericArgData::Ty(dyn_ty_ty.clone()), + ); + let bounds = dyn_ty.bounds.substitute(interner, &[arg.clone()]); let mut wf_goals = Vec::new(); @@ -1081,7 +1085,7 @@ fn match_ty( }) })); - builder.push_clause(WellFormed::Ty(ty.clone()), wf_goals); + builder.push_clause(WellFormed::Ty(dyn_ty_ty), wf_goals); }); } } diff --git a/chalk-solve/src/clauses/builtin_traits.rs b/chalk-solve/src/clauses/builtin_traits.rs index b5a1c7d57dd..3b136cc33ff 100644 --- a/chalk-solve/src/clauses/builtin_traits.rs +++ b/chalk-solve/src/clauses/builtin_traits.rs @@ -1,6 +1,8 @@ use super::{builder::ClauseBuilder, generalize}; use crate::{CanonicalVarKinds, Interner, RustIrDatabase, TraitRef, WellKnownTrait}; use chalk_ir::{Floundered, Substitution, Ty}; +use tracing::instrument; + mod clone; mod copy; @@ -99,6 +101,7 @@ pub fn add_builtin_assoc_program_clauses( /// 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)` +#[instrument(level = "debug", skip(db, builder, tys))] pub fn needs_impl_for_tys( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, diff --git a/chalk-solve/src/clauses/builtin_traits/fn_family.rs b/chalk-solve/src/clauses/builtin_traits/fn_family.rs index f2358bc7300..f5940be41b2 100644 --- a/chalk-solve/src/clauses/builtin_traits/fn_family.rs +++ b/chalk-solve/src/clauses/builtin_traits/fn_family.rs @@ -109,6 +109,12 @@ pub fn add_fn_trait_program_clauses( } TyKind::Closure(closure_id, substitution) => { let closure_kind = db.closure_kind(*closure_id, substitution); + let closure_kind = match closure_kind{ + Some(k) => k, + // If we haven't resolved the closure kind yet, don't add any program clauses. + // Really, we *could* add `FnOnce`, since closures will always at least be that. + None => return, + }; let trait_matches = matches!( (well_known, closure_kind), (WellKnownTrait::Fn, ClosureKind::Fn) diff --git a/chalk-solve/src/clauses/dyn_ty.rs b/chalk-solve/src/clauses/dyn_ty.rs index 505da43f972..416cdf521a4 100644 --- a/chalk-solve/src/clauses/dyn_ty.rs +++ b/chalk-solve/src/clauses/dyn_ty.rs @@ -52,15 +52,20 @@ pub(super) fn build_dyn_self_ty_clauses( builder.push_binders(generalized_dyn_ty, |builder, dyn_ty| { for exists_qwc in dyn_ty.bounds.map_ref(|r| r.iter(interner)) { + let arg: chalk_ir::GenericArg = chalk_ir::GenericArg::new( + interner, + chalk_ir::GenericArgData::Ty(chalk_ir::Ty::new( + interner, + TyKind::Dyn(dyn_ty.clone()), + )), + ); // Replace the `T` from `exists { .. }` 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)]); + let qwc = exists_qwc.cloned().substitute(interner, &[arg.clone()]); 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 diff --git a/chalk-solve/src/clauses/program_clauses.rs b/chalk-solve/src/clauses/program_clauses.rs index 19811ff8b30..1b28ff46778 100644 --- a/chalk-solve/src/clauses/program_clauses.rs +++ b/chalk-solve/src/clauses/program_clauses.rs @@ -5,7 +5,7 @@ use chalk_ir::cast::{Cast, Caster}; use chalk_ir::interner::Interner; use chalk_ir::*; use std::iter; -use tracing::instrument; +use tracing::{debug, instrument}; /// Trait for lowering a given piece of rust-ir source (e.g., an impl /// or struct definition) into its associated "program clauses" -- diff --git a/chalk-solve/src/display/stub.rs b/chalk-solve/src/display/stub.rs index ec209bc91a0..ff9ee6d7faf 100644 --- a/chalk-solve/src/display/stub.rs +++ b/chalk-solve/src/display/stub.rs @@ -199,7 +199,7 @@ impl> RustIrDatabase for StubWrapper<'_, D &self, _closure_id: chalk_ir::ClosureId, _substs: &chalk_ir::Substitution, - ) -> crate::rust_ir::ClosureKind { + ) -> Option { unimplemented!("cannot stub closures") } diff --git a/chalk-solve/src/lib.rs b/chalk-solve/src/lib.rs index a870a0c4961..59eb8c3b712 100644 --- a/chalk-solve/src/lib.rs +++ b/chalk-solve/src/lib.rs @@ -132,7 +132,10 @@ pub trait RustIrDatabase: Debug { fn is_object_safe(&self, trait_id: TraitId) -> bool; /// Gets the `ClosureKind` for a given closure and substitution. - fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> ClosureKind; + /// + /// Sometimes we don't know the `ClosureKind` yet. In that case, we return `None`. + /// This probably isn't right and should probably be changed back to be infallible later. + fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> Option; /// Gets the inputs and output for a given closure id and substitution. We /// pass both the `ClosureId` and it's `Substituion` to give implementors diff --git a/chalk-solve/src/logging_db.rs b/chalk-solve/src/logging_db.rs index 12d8b052a2b..8e2d53f8bce 100644 --- a/chalk-solve/src/logging_db.rs +++ b/chalk-solve/src/logging_db.rs @@ -262,7 +262,7 @@ where self.ws.db().fn_def_name(fn_def_id) } - fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> ClosureKind { + fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> Option { // TODO: record closure IDs self.ws.db().closure_kind(closure_id, substs) } @@ -516,7 +516,7 @@ where self.db.fn_def_name(fn_def_id) } - fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> ClosureKind { + fn closure_kind(&self, closure_id: ClosureId, substs: &Substitution) -> Option { // TODO: record closure IDs self.db.closure_kind(closure_id, substs) } diff --git a/tests/display/unique_names.rs b/tests/display/unique_names.rs index cd26f299ae3..996c67b3653 100644 --- a/tests/display/unique_names.rs +++ b/tests/display/unique_names.rs @@ -164,7 +164,7 @@ where &self, closure_id: chalk_ir::ClosureId, substs: &chalk_ir::Substitution, - ) -> chalk_solve::rust_ir::ClosureKind { + ) -> Option { self.db.closure_kind(closure_id, substs) } fn closure_inputs_and_output( diff --git a/tests/integration/panic.rs b/tests/integration/panic.rs index d0cbfdb7c92..4836630baf4 100644 --- a/tests/integration/panic.rs +++ b/tests/integration/panic.rs @@ -238,7 +238,7 @@ impl RustIrDatabase for MockDatabase { &self, closure_id: ClosureId, substs: &Substitution, - ) -> ClosureKind { + ) -> Option { unimplemented!() }