Skip to content

Commit 96f2f7e

Browse files
committed
Allow unification of general and specific Ty inference var kinds
The recursive solver would fail on these new tests without this change.
1 parent 6a945f3 commit 96f2f7e

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

chalk-solve/src/infer/unify.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,30 @@ impl<'t, I: Interner> Unifier<'t, I> {
115115
.expect("unification of two unbound variables cannot fail"))
116116
}
117117

118-
// Tried to unify mis-matching inference variables (not caught by prior match arm)
118+
// General inference variables can be unified with more specific
119+
// inference variables, but they need to inherit the specific
120+
// variable's type kind. The general_var kind != the specific_var
121+
// kind because of the prior match arm
122+
(
123+
&TyData::InferenceVar(general_var, TyKind::General),
124+
specific_ty_data @ &TyData::InferenceVar(_, _)
125+
)
126+
| (
127+
specific_ty_data @ &TyData::InferenceVar(_, _),
128+
&TyData::InferenceVar(general_var, TyKind::General)
129+
) => {
130+
let specific_ty = specific_ty_data.clone().intern(interner);
131+
self.table
132+
.unify
133+
.unify_var_value(general_var, InferenceValue::from_ty(interner, specific_ty.clone()))
134+
.unwrap();
135+
136+
debug!("unify_ty_ty: general kinded var {:?} set to {:?}", general_var, specific_ty);
137+
Ok(())
138+
}
139+
140+
// Tried to unify inference variables with mis-matching specific type kinds (not caught
141+
// by prior match arms)
119142
(
120143
&TyData::InferenceVar(_, kind1),
121144
&TyData::InferenceVar(_, kind2),

tests/test/numerics.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,53 @@ fn float_ambiguity() {
119119
}
120120
}
121121
}
122+
123+
/// Integer/float type kinds are just specialized type kinds, so they can unify
124+
/// with general type kinds.
125+
#[test]
126+
fn integer_and_float_are_specialized_ty_kinds() {
127+
test! {
128+
program {}
129+
130+
goal {
131+
exists<T, int N> {
132+
T = N, N = usize
133+
}
134+
} yields {
135+
"Unique; substitution [?0 := Uint(Usize), ?1 := Uint(Usize)], lifetime constraints []"
136+
}
137+
138+
goal {
139+
exists<T, float N> {
140+
T = N, N = f32
141+
}
142+
} yields {
143+
"Unique; substitution [?0 := Float(F32), ?1 := Float(F32)], lifetime constraints []"
144+
}
145+
}
146+
}
147+
148+
/// Once a general type kind is unified with a specific type kind, it cannot be
149+
/// unified with an incompatible type (ex. integer type kind with char)
150+
#[test]
151+
fn general_ty_kind_becomes_specific() {
152+
test! {
153+
program {}
154+
155+
goal {
156+
exists<T, int N> {
157+
T = N, T = char
158+
}
159+
} yields {
160+
"No possible solution"
161+
}
162+
163+
goal {
164+
exists<T, float N> {
165+
T = N, T = char
166+
}
167+
} yields {
168+
"No possible solution"
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)