use super::linked; use dever::compiler::build; #[test] fn channel_types_require_transferable_elements_and_typed_values() { assert!(linked("main() () { values = channel(List, 2)\n send(values, [null, 1])\n close(values) }").is_ok()); assert!(linked("main() () { values = channel(Channel, 1)\n send(values, channel(Int, 1))\n close(values) }").is_ok()); assert!(linked("type Message { Value(value: Int?) }\nmain() () { values = channel(Message, 1)\n send(values, Message.Value(null))\n close(values) }").is_ok()); for (source, code) in [ ("main() () { values = channel(Int, true) }", "C005"), ("main() () { values = channel(Int?, 1) }", "C013"), ("main(values: Channel) () { close(values) }", "C013"), ( "type Unused { values: Channel }\nmain() () {}", "C013", ), ( "main() () { values = channel(Int, 1)\n send(values, true) }", "C005", ), ("main() () { values = channel(Stream, 1) }", "C013"), ( "main() () { values = channel(List>, 1) }", "C013", ), ( "main() () { values = channel(Map, Int>, 1) }", "C005", ), ("type Loop { next: Channel }\nmain() () {}", "C007"), ("main() () pure { values = channel(Int, 1) }", "C013"), ( "main(values: Stream, channel: Channel) () { close(channel)\n close(values) }", "C013", ), ] { assert_eq!(linked(source).unwrap_err().code, code, "{source}"); } } #[test] fn send_transfers_errors_and_receive_requires_handling_them() { let prefix = "type Result { Done\n error Failed(message: Text) }\n"; assert!(linked(&format!("{prefix}main() () {{ values = channel(Result, 1)\n send(values, Result.Failed(\"reason\"))\n close(values) }}")).is_ok()); assert_eq!( linked(&format!( "{prefix}main(values: Channel) () {{ lost = receive(values)\n close(values) }}" )) .unwrap_err() .code, "C012" ); assert!( linked(&format!( "{prefix}main(values: Channel) (answer: Result?) {{ answer = receive(values) }}" )) .is_ok() ); } #[test] fn channel_creation_and_type_references_enable_dependency_without_suspending() { for (source, required) in [ ( "main() (value: Channel) { value = channel(Int, 1) }", true, ), ("main() (value: Channel?) { value = null }", true), ("type Unused { value: Channel }\nmain() () {}", false), ] { let program = linked(source).unwrap(); let main = program .functions .iter() .position(|function| function.signature.name == "main") .unwrap(); assert!(!program.functions[main].signature.effects.suspend); assert!(!program.functions[main].signature.effects.schedule); assert_eq!( build::runtime_features(&program, &program.reachable([main])).contains(&"task"), required ); } }