@@ -44,30 +44,43 @@ impl<I: Interner> Solution<I> {
44
44
/// There are multiple candidate solutions, which may or may not agree on
45
45
/// the values for existential variables; attempt to combine them. This
46
46
/// operation does not depend on the order of its arguments.
47
- //
48
- // This actually isn't as precise as it could be, in two ways:
49
- //
50
- // a. It might be that while there are multiple distinct candidates, they
51
- // all agree about *some things*. To be maximally precise, we would
52
- // compute the intersection of what they agree on. It's not clear though
53
- // that this is actually what we want Rust's inference to do, and it's
54
- // certainly not what it does today.
55
- //
56
- // b. There might also be an ambiguous candidate and a successful candidate,
57
- // both with the same refined-goal. In that case, we could probably claim
58
- // success, since if the conditions of the ambiguous candidate were met,
59
- // we know the success would apply. Example: `?0: Clone` yields ambiguous
60
- // candidate `Option<?0>: Clone` and successful candidate `Option<?0>:
61
- // Clone`.
62
- //
63
- // But you get the idea.
47
+ ///
48
+ /// This actually isn't as precise as it could be, in two ways:
49
+ ///
50
+ /// a. It might be that while there are multiple distinct candidates, they
51
+ /// all agree about *some things*. To be maximally precise, we would
52
+ /// compute the intersection of what they agree on. It's not clear though
53
+ /// that this is actually what we want Rust's inference to do, and it's
54
+ /// certainly not what it does today.
55
+ ///
56
+ /// b. There might also be an ambiguous candidate and a successful candidate,
57
+ /// both with the same refined-goal. In that case, we could probably claim
58
+ /// success, since if the conditions of the ambiguous candidate were met,
59
+ /// we know the success would apply. Example: `?0: Clone` yields ambiguous
60
+ /// candidate `Option<?0>: Clone` and successful candidate `Option<?0>:
61
+ /// Clone`.
62
+ ///
63
+ /// But you get the idea.
64
64
pub fn combine ( self , other : Solution < I > , interner : I ) -> Solution < I > {
65
65
use self :: Guidance :: * ;
66
66
67
67
if self == other {
68
68
return self ;
69
69
}
70
70
71
+ // Special case hack: if one solution is "true" without any constraints,
72
+ // that is always the combined result.
73
+ //
74
+ // This is not as general as it could be: ideally, if we had one solution
75
+ // that is Unique with a simpler substitution than the other one, or region constraints
76
+ // which are a subset, we'd combine them.
77
+ if self . is_trivial_and_always_true ( interner) {
78
+ return self ;
79
+ }
80
+ if other. is_trivial_and_always_true ( interner) {
81
+ return other;
82
+ }
83
+
71
84
debug ! (
72
85
"combine {} with {}" ,
73
86
self . display( interner) ,
@@ -88,6 +101,16 @@ impl<I: Interner> Solution<I> {
88
101
Solution :: Ambig ( guidance)
89
102
}
90
103
104
+ pub fn is_trivial_and_always_true ( & self , interner : I ) -> bool {
105
+ match self {
106
+ Solution :: Unique ( constrained_subst) => {
107
+ constrained_subst. value . subst . is_identity_subst ( interner)
108
+ && constrained_subst. value . constraints . is_empty ( interner)
109
+ }
110
+ Solution :: Ambig ( _) => false ,
111
+ }
112
+ }
113
+
91
114
/// View this solution purely in terms of type inference guidance
92
115
pub fn into_guidance ( self ) -> Guidance < I > {
93
116
match self {
0 commit comments