1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
|
use rt::{compile, status};
type err_int = !int;
type err_recur = !*err_recur;
fn assignability() void = {
// Error and non-error types are interchangable:
let a: !int = 10;
let b: int = a;
assert(a == b);
compile(status::CHECK, `
type err = !void;
fn reterr() (int | err) = {
return err;
};
fn properr() void = {
reterr()?;
};
export fn main() void = void;
`)!; // error types cannot be assigned to void
};
type error = !void;
fn err_if_false(in: bool) (error | int) = {
if (in) {
return 1337;
};
return error;
};
fn indirect(in: bool) (error | int) = {
let x = err_if_false(in)?;
return x;
};
fn propagate() void = {
assert(indirect(true) as int == 1337);
assert(indirect(false) is error);
};
fn cannotignore() void = {
compile(status::CHECK, "
type error = !void;
export fn main() void = {
error;
};
")!;
compile(status::CHECK, "
type error = !int;
export fn main() void = {
let x: error = 0;
x;
};
")!;
compile(status::CHECK, "
type error = !int;
export fn main() void = {
let x: (error | void) = void;
x;
};
")!;
err_if_false(true)!;
};
fn discard() void = {
let x: error = error;
let x: (int | error) = error;
let x = err_if_false(false);
x = error;
x = err_if_false(false);
// XXX: type inference currently doesn't work because of the temporary
// fix for https://todo.sr.ht/~sircmpwn/hare/951. once that ticket is
// actually fixed, the explicit type here can be removed
let _: error = error;
let _ = err_if_false(false);
_ = error;
_ = err_if_false(false);
for (let x => done: (int | done | !void)) void;
for (let _ => done: (int | done | !void)) void;
compile(status::CHECK, `fn f() void = for (let x => done: (int | done | !void)) x;`)!;
};
fn measurements() void = {
assert(size(!int) == size(int));
assert(size(!f64) == size(f64));
assert(size(!(int | void)) == size((int | void)));
assert(size(!(i8, rune)) == size((i8, rune)));
assert(size(!struct { x: int, y: str }) == size(struct { x: int, y: str }));
assert(size(!union { x: int, y: str }) == size(union { x: int, y: str }));
assert(size(![2]int) == size([2]int));
assert(size(![]int) == size([]int));
assert(size(!*size) == size(*size));
assert(align(!int) == align(int));
assert(align(!f64) == align(f64));
assert(align(!(int | void)) == align((int | void)));
assert(align(!(i8, rune)) == align((i8, rune)));
assert(align(!struct { x: int, y: str }) == align(struct { x: int, y: str }));
assert(align(!union { x: int, y: str }) == align(union { x: int, y: str }));
assert(align(![2]int) == align([2]int));
assert(align(![*]int) == align([*]int));
assert(align(![]int) == align([]int));
assert(align(!*size) == align(*size));
};
type err_done_tagged_union = !(int | done);
type done_tagged_union = (int | done);
type err_done_tagged_union_alias = !done_tagged_union;
fn disallowed_types() void = {
compile(status::CHECK, `type t = !done;`)!;
compile(status::CHECK, `type t = done; type u = t; type v = !u;`)!;
compile(status::CHECK, `fn f() !never;`)!;
};
export fn main() void = {
assignability();
propagate();
cannotignore();
discard();
measurements();
disallowed_types();
};
|