@@ -7,7 +7,7 @@ use ir::*;
7
7
use cast:: * ;
8
8
use solve:: { SolverChoice , Solution } ;
9
9
10
- struct OverlapSolver {
10
+ struct DisjointSolver {
11
11
env : Arc < ProgramEnvironment > ,
12
12
solver_choice : SolverChoice ,
13
13
}
@@ -21,7 +21,7 @@ impl Program {
21
21
where
22
22
F : FnMut ( ItemId , ItemId ) ,
23
23
{
24
- let mut solver = OverlapSolver {
24
+ let mut solver = DisjointSolver {
25
25
env : Arc :: new ( self . environment ( ) ) ,
26
26
solver_choice,
27
27
} ;
@@ -65,7 +65,7 @@ impl Program {
65
65
// Check if the impls overlap, then if they do, check if one specializes
66
66
// the other. Note that specialization can only run one way - if both
67
67
// specialization checks return *either* true or false, that's an error.
68
- if solver. overlap ( lhs, rhs) {
68
+ if ! solver. disjoint ( lhs, rhs) {
69
69
match ( solver. specializes ( lhs, rhs) , solver. specializes ( rhs, lhs) ) {
70
70
( true , false ) => record_specialization ( l_id, r_id) ,
71
71
( false , true ) => record_specialization ( r_id, l_id) ,
@@ -82,36 +82,41 @@ impl Program {
82
82
}
83
83
}
84
84
85
- impl OverlapSolver {
85
+ impl DisjointSolver {
86
86
// Test if the set of types that these two impls apply to overlap. If the test succeeds, these
87
- // two impls overlap .
87
+ // two impls are disjoint .
88
88
//
89
- // We combine the binders of the two impls & treat them as existential
90
- // quantifiers. Then we attempt to unify the input types to the trait provided
91
- // by each impl, as well as prove that the where clauses from both impls all
92
- // hold.
89
+ // We combine the binders of the two impls & treat them as existential quantifiers. Then we
90
+ // attempt to unify the input types to the trait provided by each impl, as well as prove that
91
+ // the where clauses from both impls all hold. At the end, we apply the `compatible` modality
92
+ // and negate the query. Negating the query means that we are asking chalk to prove that no
93
+ // such overlapping impl exists. By applying `compatible { G }`, chalk attempts to prove that
94
+ // "there exists a compatible world where G is provable." When we negate compatible, it turns
95
+ // into the statement "for all compatible worlds, G is not provable." This is exactly what we
96
+ // want since we want to ensure that there is no overlap in *all* compatible worlds, not just
97
+ // that there is no overlap in *some* compatible world.
93
98
//
94
99
// Examples:
95
100
//
96
101
// Impls:
97
102
// impl<T> Foo for T { }
98
103
// impl Foo for i32 { }
99
104
// Generates:
100
- // compatible { exists<T> { T = i32 } }
105
+ // not { compatible { exists<T> { T = i32 } } }
101
106
//
102
107
// Impls:
103
108
// impl<T1, U> Foo<T1> for Vec<U> { }
104
109
// impl<T2> Foo<T2> for Vec<i32> { }
105
110
// Generates:
106
- // compatible { exists<T1, U, T2> { Vec<U> = Vec<i32>, T1 = T2 } }
111
+ // not { compatible { exists<T1, U, T2> { Vec<U> = Vec<i32>, T1 = T2 } } }
107
112
//
108
113
// Impls:
109
114
// impl<T> Foo for Vec<T> where T: Bar { }
110
115
// impl<U> Foo for Vec<U> where U: Baz { }
111
116
// Generates:
112
- // compatible { exists<T, U> { Vec<T> = Vec<U>, T: Bar, U: Baz } }
117
+ // not { compatible { exists<T, U> { Vec<T> = Vec<U>, T: Bar, U: Baz } } }
113
118
//
114
- fn overlap ( & self , lhs : & ImplDatum , rhs : & ImplDatum ) -> bool {
119
+ fn disjoint ( & self , lhs : & ImplDatum , rhs : & ImplDatum ) -> bool {
115
120
debug_heading ! ( "overlaps(lhs={:#?}, rhs={:#?})" , lhs, rhs) ;
116
121
117
122
let lhs_len = lhs. binders . len ( ) ;
@@ -150,19 +155,20 @@ impl OverlapSolver {
150
155
. fold1 ( |goal, leaf| Goal :: And ( Box :: new ( goal) , Box :: new ( leaf) ) )
151
156
. expect ( "Every trait takes at least one input type" )
152
157
. quantify ( QuantifierKind :: Exists , binders)
153
- . compatible ( ) ;
158
+ . compatible ( )
159
+ . negate ( ) ;
154
160
155
161
let canonical_goal = & goal. into_closed_goal ( ) ;
156
162
let solution = self . solver_choice
157
163
. solve_root_goal ( & self . env , canonical_goal)
158
164
. unwrap ( ) ; // internal errors in the solver are fatal
159
165
let result = match solution {
160
- // Goal was proven with a unique solution, so an impl was found that causes these two
166
+ // Goal was proven with a unique solution, so no impl was found that causes these two
161
167
// to overlap
162
- Some ( Solution :: Unique ( _) ) |
168
+ Some ( Solution :: Unique ( _) ) => true ,
163
169
// Goal was ambiguous, so there *may* be overlap
164
- Some ( Solution :: Ambig ( _) ) => true ,
165
- // Goal cannot be proven, so impls are disjoint
170
+ Some ( Solution :: Ambig ( _) ) |
171
+ // Goal cannot be proven, so there is some impl that causes overlap
166
172
None => false ,
167
173
} ;
168
174
debug ! ( "overlaps: result = {:?}" , result) ;
0 commit comments