Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dyn program clause generation and make returning a ClosureKind optional #785

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion chalk-integration/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl RustIrDatabase<ChalkIr> for ChalkDatabase {
&self,
closure_id: ClosureId<ChalkIr>,
substs: &Substitution<ChalkIr>,
) -> ClosureKind {
) -> Option<ClosureKind> {
self.program_ir().unwrap().closure_kind(closure_id, substs)
}

Expand Down
2 changes: 1 addition & 1 deletion chalk-integration/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ impl RustIrDatabase<ChalkIr> for Program {
&self,
closure_id: ClosureId<ChalkIr>,
_substs: &Substitution<ChalkIr>,
) -> ClosureKind {
) -> Option<ClosureKind> {
self.closure_closure_kind[&closure_id]
}

Expand Down
12 changes: 8 additions & 4 deletions chalk-solve/src/clauses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ pub fn push_auto_trait_impls<I: Interner>(
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
Expand Down Expand Up @@ -1062,9 +1063,12 @@ fn match_ty<I: Interner>(
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 dyn_ty_ty = chalk_ir::Ty::new(interner, TyKind::Dyn(dyn_ty.clone()));
let arg: chalk_ir::GenericArg<I> = 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();

Expand All @@ -1081,7 +1085,7 @@ fn match_ty<I: Interner>(
})
}));

builder.push_clause(WellFormed::Ty(ty.clone()), wf_goals);
builder.push_clause(WellFormed::Ty(dyn_ty_ty), wf_goals);
});
}
}
Expand Down
3 changes: 3 additions & 0 deletions chalk-solve/src/clauses/builtin_traits.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -99,6 +101,7 @@ pub fn add_builtin_assoc_program_clauses<I: Interner>(

/// 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<I: Interner>(
db: &dyn RustIrDatabase<I>,
builder: &mut ClauseBuilder<'_, I>,
Expand Down
6 changes: 6 additions & 0 deletions chalk-solve/src/clauses/builtin_traits/fn_family.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ pub fn add_fn_trait_program_clauses<I: Interner>(
}
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)
Expand Down
11 changes: 8 additions & 3 deletions chalk-solve/src/clauses/dyn_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,20 @@ pub(super) fn build_dyn_self_ty_clauses<I: Interner>(

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<I> = chalk_ir::GenericArg::new(
interner,
chalk_ir::GenericArgData::Ty(chalk_ir::Ty::new(
interner,
TyKind::Dyn(dyn_ty.clone()),
)),
);
// 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)]);
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
Expand Down
2 changes: 1 addition & 1 deletion chalk-solve/src/clauses/program_clauses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" --
Expand Down
2 changes: 1 addition & 1 deletion chalk-solve/src/display/stub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ impl<I: Interner, DB: RustIrDatabase<I>> RustIrDatabase<I> for StubWrapper<'_, D
&self,
_closure_id: chalk_ir::ClosureId<I>,
_substs: &chalk_ir::Substitution<I>,
) -> crate::rust_ir::ClosureKind {
) -> Option<crate::rust_ir::ClosureKind> {
unimplemented!("cannot stub closures")
}

Expand Down
5 changes: 4 additions & 1 deletion chalk-solve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ pub trait RustIrDatabase<I: Interner>: Debug {
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;
///
/// 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<I>, substs: &Substitution<I>) -> Option<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
Expand Down
4 changes: 2 additions & 2 deletions chalk-solve/src/logging_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ where
self.ws.db().fn_def_name(fn_def_id)
}

fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Option<ClosureKind> {
// TODO: record closure IDs
self.ws.db().closure_kind(closure_id, substs)
}
Expand Down Expand Up @@ -516,7 +516,7 @@ where
self.db.fn_def_name(fn_def_id)
}

fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> ClosureKind {
fn closure_kind(&self, closure_id: ClosureId<I>, substs: &Substitution<I>) -> Option<ClosureKind> {
// TODO: record closure IDs
self.db.closure_kind(closure_id, substs)
}
Expand Down
2 changes: 1 addition & 1 deletion tests/display/unique_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ where
&self,
closure_id: chalk_ir::ClosureId<I>,
substs: &chalk_ir::Substitution<I>,
) -> chalk_solve::rust_ir::ClosureKind {
) -> Option<chalk_solve::rust_ir::ClosureKind> {
self.db.closure_kind(closure_id, substs)
}
fn closure_inputs_and_output(
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ impl RustIrDatabase<ChalkIr> for MockDatabase {
&self,
closure_id: ClosureId<ChalkIr>,
substs: &Substitution<ChalkIr>,
) -> ClosureKind {
) -> Option<ClosureKind> {
unimplemented!()
}

Expand Down