fix: trait parameter bug

This commit is contained in:
Shunsuke Shibayama 2024-04-28 18:52:17 +09:00
parent 02a67567d3
commit 0ffa23affd
7 changed files with 73 additions and 32 deletions

View file

@ -369,6 +369,18 @@ macro_rules! ref_addr_eq {
#[macro_export]
macro_rules! power_assert {
($l: expr, $op: tt, $r: expr, $msg: expr $(,)*) => {
if !($l $op $r) {
let s_l = stringify!($l);
let s_r = stringify!($r);
let s_op = stringify!($op);
println!($msg);
panic!(
"assertion failed: `{s_l} {s_op} {s_r}` (`{s_l}` = {:#?}, `{s_r}` = {:#?})",
$l, $r,
)
}
};
($l: expr, $op: tt, $r: expr $(,)*) => {
if !($l $op $r) {
let s_l = stringify!($l);
@ -390,6 +402,11 @@ macro_rules! power_assert {
#[macro_export]
macro_rules! debug_power_assert {
($l: expr, $op: tt, $r: expr, $msg: expr) => {
if cfg!(debug_assertions) {
erg_common::power_assert!($l, $op, $r, $msg)
}
};
($l: expr, $op: tt, $r: expr) => {
if cfg!(debug_assertions) {
erg_common::power_assert!($l, $op, $r)

View file

@ -843,10 +843,10 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
/// sub_unify([?T; 0], Mutate): (/* OK */)
/// ```
fn sub_unify(&self, maybe_sub: &Type, maybe_sup: &Type) -> TyCheckResult<()> {
log!(info "trying {}sub_unify:\nmaybe_sub: {maybe_sub}\nmaybe_sup: {maybe_sup}", self.undoable.map_or("", |_| "undoable"));
log!(info "trying {}sub_unify:\nmaybe_sub: {maybe_sub}\nmaybe_sup: {maybe_sup}", self.undoable.map_or("", |_| "undoable_"));
// In this case, there is no new information to be gained
// この場合、特に新しく得られる情報はない
if maybe_sub == &Type::Never || maybe_sup == &Type::Obj || maybe_sup == maybe_sub {
if maybe_sub == &Type::Never || maybe_sup == &Type::Obj || maybe_sup.addr_eq(maybe_sub) {
log!(info "no-op:\nmaybe_sub: {maybe_sub}\nmaybe_sup: {maybe_sup}");
return Ok(());
}
@ -1640,6 +1640,7 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
list.push_tp(l_maybe_sub);
list.push_tp(r_maybe_sup);
}
// debug_power_assert!(variances.len(), >=, sup_params.len(), "{sub_instance} / {maybe_sup}");
let unifier = Unifier::new(self.ctx, self.loc, Some(&list), false, None);
for ((l_maybe_sub, r_maybe_sup), variance) in sub_params
.iter()

View file

@ -1720,6 +1720,20 @@ impl TyParam {
}
match self {
Self::FreeVar(fv) => fv.link(to),
Self::Type(t) => {
if let Ok(to) = <&Type>::try_from(to) {
t.destructive_link(to);
} else {
panic!("{to} is not a type");
}
}
Self::Value(ValueObj::Type(t)) => {
if let Ok(to) = <&Type>::try_from(to) {
t.typ().destructive_link(to);
} else {
panic!("{to} is not a type");
}
}
_ => panic!("{self} is not a free variable"),
}
}

View file

@ -1,3 +1,8 @@
fst|T| s: Sequence T = s[0]
assert fst([1, 2, 3]) + 1 == 2
assert fst(["a", "b", "c"]) + "b" == "ab"
assert fst((1, 2, 3)) + 1 == 2
Norm = Trait {.norm = (self: Self) -> Nat}
Point2D = Class {x = Int; y = Int}

View file

@ -0,0 +1,27 @@
# g: |T <: Ord and Eq and Show| T -> T
g x =
_ = x <= x
_ = x == x
_ = x.__str__()
x
g 1 # OK
g None # ERR
h x, y =
_ = x == y
_ = x - y
x + y
_ = h -1, -2 # OK
_ = h 1, 2 # OK
_ = h "a", "b" # ERR
i|T|(x: T): T =
_: Int = x
x + "a" # ERR
i2|T|(x: T): T =
x + "a"
_ = i 1
_ = i2 1 # ERR

View file

@ -16,7 +16,7 @@ for! zip([1], ["a"]), ((i: Int, s: Str),) =>
l = s + "b"
print! k, l
# ERR: i should be Int
for! zip([1], ["a"]), ((i: Str, s: Str),) =>
for! zip([1], ["a"]), ((i: Str, s: Str),) => # ERR
k = i + "a"
print! k
for! zip([1], ["a"]), ((i, s),) =>
@ -38,34 +38,6 @@ inty|T :> Nat, T <: Int|(x: T) = x + x
inty 0 # OK
inty 1.1 # ERR
# g: |T <: Ord and Eq and Show| T -> T
g x =
_ = x <= x
_ = x == x
_ = x.__str__()
x
g 1 # OK
g None # ERR
h x, y =
_ = x == y
_ = x - y
x + y
_ = h -1, -2 # OK
_ = h 1, 2 # OK
_ = h "a", "b" # ERR
i|T|(x: T): T =
_: Int = x
x + "a" # ERR
i2|T|(x: T): T =
x + "a"
_ = i 1
_ = i2 1 # ERR
_: List!({"a", "b"}, 2) = !["a", "b"] # OK
_: List!({"a", "b", "c"}, 2) = !["a", "b"] # OK
_: List!({"a", "c"}, 2) = !["a", "b"] # ERR

View file

@ -574,6 +574,11 @@ fn exec_incomplete_typespec() -> Result<(), ()> {
expect_failure("tests/should_err/incomplete_typespec.er", 0, 3)
}
#[test]
fn exec_infer_fn() -> Result<(), ()> {
expect_failure("tests/should_err/infer_fn.er", 2, 6)
}
#[test]
fn exec_infer_union_array() -> Result<(), ()> {
expect_failure("tests/should_err/infer_union_array.er", 2, 1)
@ -641,7 +646,7 @@ fn exec_structural_err() -> Result<(), ()> {
#[test]
fn exec_subtyping_err() -> Result<(), ()> {
// NOTE: The content of some errors is semantically redundant and can be reduced.
expect_failure("tests/should_err/subtyping.er", 0, 18)
expect_failure("tests/should_err/subtyping.er", 3, 13)
}
#[test]