compiler/
lib/
examples/
std/
arch/
char/
collections/
graph/
lang/
alloc/
ast/
gen/
il/
module/
parser/
resolver/
tests/
opaqueTests.rad
6.6 KiB
printer.rad
25.5 KiB
tests.rad
410.1 KiB
scanner/
alloc.rad
7.1 KiB
ast.rad
26.9 KiB
gen.rad
513 B
il.rad
20.4 KiB
lower.rad
321.7 KiB
module.rad
17.3 KiB
package.rad
1.3 KiB
parser.rad
92.2 KiB
resolver.rad
511.1 KiB
scanner.rad
17.9 KiB
sexpr.rad
6.7 KiB
strings.rad
2.2 KiB
types.rad
1.6 KiB
sys/
arch.rad
68 B
char.rad
855 B
collections.rad
39 B
fmt.rad
8.3 KiB
graph.rad
4.3 KiB
intrinsics.rad
467 B
io.rad
1.7 KiB
lang.rad
276 B
mem.rad
2.3 KiB
sys.rad
179 B
testing.rad
2.4 KiB
tests.rad
15.7 KiB
vec.rad
3.2 KiB
std.rad
299 B
scripts/
seed/
sublime/
test/
vim/
.gitignore
336 B
.gitsigners
112 B
CELL_PERMISSIONS
6.8 KiB
CONTRIBUTING
2.1 KiB
LICENSE
1.1 KiB
Makefile
5.4 KiB
README
2.5 KiB
STYLE
2.5 KiB
std.lib
1.5 KiB
std.lib.test
808 B
lib/std/lang/resolver/opaqueTests.rad
raw
| 1 | //! Module-owned record representation tests. |
| 2 | |
| 3 | use std::testing; |
| 4 | use std::io; |
| 5 | use std::lang::ast; |
| 6 | use std::lang::resolver; |
| 7 | use super::tests; |
| 8 | |
| 9 | /// Types used to check access to module-owned record representations. |
| 10 | constant OPAQUE_RECORD_MODEL: *[u8] = "export opaque record Value: Copy { number: u32 } export opaque record Word: Copy(u32); export opaque record Empty: Copy {} export opaque record View: 'r + Copy { number: &'r cell u32 } opaque record Hidden: Copy { number: u32 } export fn hidden() -> Hidden { return Hidden { number: 42 }; } export union Wrapped: Copy { Value(Value) }"; |
| 11 | |
| 12 | /// External record operations cannot expose or construct private fields. |
| 13 | @test unsafe fn testOpaqueRecordAccess() throws (testing::TestError) { |
| 14 | for program in [ |
| 15 | "mod model; fn f(p: model::Value) -> u32 { return p.number; }", |
| 16 | "mod model; fn f(p: &model::Value) -> u32 { return p.number; }", |
| 17 | "mod model; fn f(p: &mut model::Value) { set p.number = 1; }", |
| 18 | "mod model; fn f(p: &mut model::Value) { set p.number += 1; }", |
| 19 | "mod model; fn f(p: &model::Value) { let field = &p.number; }", |
| 20 | "mod model; fn f(p: &mut model::Value) { let field = &mut p.number; }", |
| 21 | "mod model; unsafe fn f(p: model::Value) -> u32 { return p.number; }", |
| 22 | "mod model; fn f() -> u32 { return model::hidden().number; }", |
| 23 | "mod model; fn f() -> model::Value { return model::Value { number: 1 }; }", |
| 24 | "mod model; fn f() -> model::Value { return { number: 1 }; }", |
| 25 | "mod model; fn f() -> ?model::Value { return { number: 1 }; }", |
| 26 | "mod model; fn f() -> model::Value { return model::Value { .. }; }", |
| 27 | "mod model; fn f() -> model::Empty { return model::Empty {}; }", |
| 28 | "mod model; fn f() -> model::Word { return model::Word(1); }", |
| 29 | "mod model; fn f(p: model::Value) { let case model::Value { number } = p else panic; }", |
| 30 | "mod model; fn f(p: &model::Value) { let case model::Value { number } = p else panic; }", |
| 31 | "mod model; fn f(p: model::Value) { let case model::Value { .. } = p else panic; }", |
| 32 | "mod model; fn f(p: model::Value) { if let case model::Value { number } = p; number > 0 {} }", |
| 33 | "mod model; fn f(p: model::Value) { while let case model::Value { number } = p { break; } }", |
| 34 | "mod model; fn f(p: model::Value) { match p { case model::Value { number } => {} } }", |
| 35 | "mod model; fn f(p: model::Wrapped) { match p { case model::Wrapped::Value(model::Value { number }) => {} } }", |
| 36 | "mod model; fn f(p: model::Word) { let case model::Word(number) = p else panic; }", |
| 37 | "mod model; fn f(p: model::Word) -> u32 { return *p; }", |
| 38 | "mod model; fn f(p: &mut model::Word) { set **p = 2; }", |
| 39 | "mod model; fn f(p: model::Word) { let field = &*p; }", |
| 40 | "mod model; fn f 'r (p: &model::View 'r) -> u32 { return *p.number; }", |
| 41 | "mod model; fn f 'r (p: &model::View 'r) { set *p.number = 1; }", |
| 42 | "mod model; fn f 'r (number: &'r cell u32) -> model::View 'r { return model::View 'r { number }; }", |
| 43 | "mod model; fn f 'r (number: &'r cell u32) -> model::View 'r { return { number }; }", |
| 44 | "mod model; fn f 'r (p: model::View 'r) { let case model::View 'r { number } = p else panic; }", |
| 45 | "mod model; use root::model::*; fn f(p: Value) -> u32 { return p.number; }", |
| 46 | ] { |
| 47 | let mut storage = tests::testArena(); |
| 48 | let memory: 'test = &mut storage in { |
| 49 | let mut res = tests::testResolver(memory); |
| 50 | let mut arena = ast::nodeArena(&mut tests::AST_ARENA[..]); |
| 51 | let root = try tests::registerModule(&mut tests::MODULE_GRAPH, nil, "root", program, &mut arena); |
| 52 | let model = try tests::registerModule(&mut tests::MODULE_GRAPH, root, "model", OPAQUE_RECORD_MODEL, &mut arena); |
| 53 | let result = try tests::resolveModuleTree(&mut res, root); |
| 54 | try tests::expectErrorKind(&result, resolver::ErrorKind::OpaqueRecordAccess) catch error { |
| 55 | io::print(program); |
| 56 | io::print("\n"); |
| 57 | tests::printDiagnostics(&result.diagnostics, &res); |
| 58 | throw error; |
| 59 | }; |
| 60 | } |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | /// Child and sibling modules cannot access an opaque record's fields. |
| 65 | @test unsafe fn testOpaqueRecordModuleBoundary() throws (testing::TestError) { |
| 66 | for child in [false, true] { |
| 67 | let mut storage = tests::testArena(); |
| 68 | let memory: 'test = &mut storage in { |
| 69 | let mut res = tests::testResolver(memory); |
| 70 | let mut arena = ast::nodeArena(&mut tests::AST_ARENA[..]); |
| 71 | let root = try tests::registerModule(&mut tests::MODULE_GRAPH, nil, "root", "export mod model; mod client;", &mut arena); |
| 72 | let model = try tests::registerModule(&mut tests::MODULE_GRAPH, root, "model", "mod child; export opaque record Value: Copy { number: u32 }", &mut arena); |
| 73 | let program = "use root::model; fn f(p: model::Value) -> u32 { return p.number; }"; |
| 74 | let nested = try tests::registerModule(&mut tests::MODULE_GRAPH, model, "child", program if child else "", &mut arena); |
| 75 | let client = try tests::registerModule(&mut tests::MODULE_GRAPH, root, "client", "" if child else program, &mut arena); |
| 76 | let result = try tests::resolveModuleTree(&mut res, root); |
| 77 | try tests::expectErrorKind(&result, resolver::ErrorKind::OpaqueRecordAccess) catch error { |
| 78 | tests::printDiagnostics(&result.diagnostics, &res); |
| 79 | throw error; |
| 80 | }; |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | /// Defining modules can access opaque representations through all source forms. |
| 86 | @test unsafe fn testOpaqueRecordLocalAccess() throws (testing::TestError) { |
| 87 | let mut storage = tests::testArena(); |
| 88 | let memory: 'test = &mut storage in { |
| 89 | let mut res = tests::testResolver(memory); |
| 90 | let result = try tests::resolveProgramStr(&mut res, |
| 91 | "opaque record Value: Copy { number: u32 } opaque record Word: Copy(u32); opaque record View: 'r + Copy { number: &'r cell u32 } fn f() { let mut p = Value { number: 1 }; set p.number += 2; let q: Value = { number: p.number }; let r: ?Value = { number: 4 }; let case Value { number } = q else panic; if let case Value { number: n } = p; n > 0 {} while let case Value { number: n } = p { break; } match p { case Value { number: n } => {} else => {} } let mut w = Word(1); set *w = 2; { let field = &mut *w; set *field = 3; } let case Word(n) = w else panic; } fn g 'r (number: &'r cell u32) -> View 'r { let p = View 'r { number }; set *p.number = 42; let case View 'r { number: value } = p else panic; return { number: value }; }" |
| 92 | ); |
| 93 | try tests::expectNoErrors(&result) catch error { |
| 94 | tests::printDiagnostics(&result.diagnostics, &res); |
| 95 | throw error; |
| 96 | }; |
| 97 | } |
| 98 | } |