Skip to content

Commit df09cc6

Browse files
authored
Merge pull request #244 from nikomatsakis/impls-for-trait
extend `impls_for_trait` callback to take `[Parameter]` values
2 parents aa0c058 + 4c7d946 commit df09cc6

File tree

4 files changed

+30
-14
lines changed

4 files changed

+30
-14
lines changed

chalk-ir/src/could_match.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use crate::zip::{Zip, Zipper};
22
use crate::*;
33

44
/// A fast check to see whether two things could ever possibly match.
5-
pub trait CouldMatch<T> {
5+
pub trait CouldMatch<T: ?Sized> {
66
fn could_match(&self, other: &T) -> bool;
77
}
88

9-
impl<T: Zip> CouldMatch<T> for T {
9+
impl<T: Zip + ?Sized> CouldMatch<T> for T {
1010
fn could_match(&self, other: &T) -> bool {
1111
return Zip::zip_with(&mut MatchZipper, self, other).is_ok();
1212

@@ -53,6 +53,7 @@ impl CouldMatch<DomainGoal> for ProgramClause {
5353
fn could_match(&self, other: &DomainGoal) -> bool {
5454
match self {
5555
ProgramClause::Implies(implication) => implication.consequence.could_match(other),
56+
5657
ProgramClause::ForAll(clause) => clause.value.consequence.could_match(other),
5758
}
5859
}

chalk-solve/src/clauses.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn program_clauses_that_could_match(
146146
// as for the `Implemented(Foo) :- FromEnv(Foo)` rule.
147147
db.trait_datum(trait_id).to_program_clauses(db, clauses);
148148

149-
for impl_id in db.impls_for_trait(trait_id) {
149+
for impl_id in db.impls_for_trait(trait_ref.trait_id, &trait_ref.parameters) {
150150
db.impl_datum(impl_id).to_program_clauses(db, clauses);
151151
}
152152

@@ -198,7 +198,13 @@ fn program_clauses_that_could_match(
198198
// ```
199199
let associated_ty_datum = db.associated_ty_data(projection.associated_ty_id);
200200
let trait_id = associated_ty_datum.trait_id;
201-
push_program_clauses_for_associated_type_values_in_impls_of(db, trait_id, clauses);
201+
let (_, trait_parameters, _) = db.split_projection(projection);
202+
push_program_clauses_for_associated_type_values_in_impls_of(
203+
db,
204+
trait_id,
205+
trait_parameters,
206+
clauses,
207+
);
202208
}
203209
DomainGoal::InScope(type_kind_id) => match_type_kind(db, *type_kind_id, clauses),
204210
DomainGoal::LocalImplAllowed(trait_ref) => db
@@ -225,9 +231,10 @@ fn program_clauses_that_could_match(
225231
fn push_program_clauses_for_associated_type_values_in_impls_of(
226232
db: &dyn RustIrDatabase,
227233
trait_id: TraitId,
234+
trait_parameters: &[Parameter],
228235
clauses: &mut Vec<ProgramClause>,
229236
) {
230-
for impl_id in db.impls_for_trait(trait_id) {
237+
for impl_id in db.impls_for_trait(trait_id, trait_parameters) {
231238
let impl_datum = db.impl_datum(impl_id);
232239
if !impl_datum.is_positive() {
233240
continue;

chalk-solve/src/lib.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,16 @@ pub trait RustIrDatabase: Debug {
3131
/// Returns the datum for the impl with the given id.
3232
fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum>;
3333

34-
/// Returns all the impls for a given trait.
35-
///
36-
/// FIXME: We should really be using some kind of "simplified self
37-
/// type" to help the impl use a hashing strategy and avoid
38-
/// returning a ton of entries here.
39-
fn impls_for_trait(&self, trait_id: TraitId) -> Vec<ImplId>;
34+
/// Returns a list of potentially relevant impls for a given
35+
/// trait-id; we also supply the type parameters that we are
36+
/// trying to match (if known: these parameters may contain
37+
/// inference variables, for example). The implementor is
38+
/// permitted to return any superset of the applicable impls;
39+
/// chalk will narrow down the list to only those that truly
40+
/// apply. The parameters are provided as a "hint" to help the
41+
/// implementor do less work, but can be completely ignored if
42+
/// desired.
43+
fn impls_for_trait(&self, trait_id: TraitId, parameters: &[Parameter]) -> Vec<ImplId>;
4044

4145
/// Returns the impls that require coherence checking. This is not the
4246
/// full set of impls that exist:

src/db.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::error::ChalkError;
22
use crate::lowering::LowerGoal;
33
use crate::program::Program;
44
use crate::query::{Lowering, LoweringDatabase};
5+
use chalk_ir::could_match::CouldMatch;
56
use chalk_ir::tls;
67
use chalk_ir::Goal;
78
use chalk_ir::Identifier;
@@ -86,14 +87,17 @@ impl RustIrDatabase for ChalkDatabase {
8687
self.program_ir().unwrap().struct_data[&id].clone()
8788
}
8889

89-
fn impls_for_trait(&self, trait_id: TraitId) -> Vec<ImplId> {
90+
fn impls_for_trait(&self, trait_id: TraitId, parameters: &[Parameter]) -> Vec<ImplId> {
9091
self.program_ir()
9192
.unwrap()
9293
.impl_data
9394
.iter()
9495
.filter(|(_, impl_datum)| {
95-
let impl_trait_id = impl_datum.binders.value.trait_ref.trait_ref().trait_id;
96-
impl_trait_id == trait_id
96+
let trait_ref = impl_datum.binders.value.trait_ref.trait_ref();
97+
trait_id == trait_ref.trait_id && {
98+
assert_eq!(trait_ref.parameters.len(), parameters.len());
99+
<[_] as CouldMatch<[_]>>::could_match(&parameters, &trait_ref.parameters)
100+
}
97101
})
98102
.map(|(&impl_id, _)| impl_id)
99103
.collect()

0 commit comments

Comments
 (0)