/* ----------------------------------------------------------------------------- Copyright 2021 Kevin P. Barry Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------------------------------------------------------------- */ // Author: Kevin P. Barry [ta0kira@gmail.com] testcase "immutable concrete protects @value members" { error require "value" require "read-only" } concrete Test { immutable } define Test { @value Int value @value call () -> () call () { value <- 2 } } testcase "immutable concrete skips @category members" { compiles } concrete Test { immutable } define Test { @category Int value <- 0 @value call () -> () call () { value <- 2 } } testcase "immutable is transitively inherited from @value interface" { error require "value" require "read-only" } @value interface Base0 { immutable } @value interface Base1 { refines Base0 } concrete Test { refines Base1 } define Test { @value Int value @value call () -> () call () { value <- 2 } } testcase "immutable is transitively inherited from internal @value interface" { error require "value" require "read-only" } @value interface Base0 { immutable } @value interface Base1 { refines Base0 } concrete Test { } define Test { refines Base1 @value Int value @value call () -> () call () { value <- 2 } } testcase "immutable is inherited from @type interface" { error require "value" require "read-only" } @type interface Base { immutable } concrete Test { defines Base } define Test { @value Int value @value call () -> () call () { value <- 2 } } testcase "immutable is inherited from internal @type interface" { error require "value" require "read-only" } @type interface Base { immutable } concrete Test { } define Test { defines Base @value Int value @value call () -> () call () { value <- 2 } } testcase "@value members must have immutable types" { error require "immutable" require "value0" require "value1" require "value2" } @value interface Foo { } concrete Test { immutable } define Test { @value Foo value0 @value optional Foo value1 @value weak Foo value2 } testcase "literal built-in types are immutable" { compiles } concrete Test { immutable } define Test { @value Bool bool @value Char char @value Float float @value Int int @value String string } testcase "intersection requires at least one immutable type" { error require "immutable" require "value" } @value interface Foo { } @value interface Bar { } concrete Test { immutable } define Test { @value [Foo & Bar] value } testcase "intersection only requires one immutable type" { compiles } @value interface Foo { } @value interface Bar { immutable } concrete Test { immutable } define Test { @value [Foo & Bar] value } testcase "union requires all immutable types" { error require "immutable" require "value" } @value interface Foo { } @value interface Bar { immutable } concrete Test { immutable } define Test { @value [Foo | Bar] value } testcase "union works with all immutable types" { compiles } @value interface Foo { immutable } @value interface Bar { immutable } concrete Test { immutable } define Test { @value [Foo | Bar] value } testcase "param members must be immutable" { error require "immutable" require "value" } concrete Test<#x> { immutable } define Test { @value #x value } testcase "explicit immutable filter is sufficient for param members" { compiles } concrete Test<#x> { immutable #x immutable } define Test { @value #x value } testcase "indirect immutable via requires filter is sufficient for param members" { compiles } @value interface Foo { immutable } concrete Test<#x> { immutable #x requires Foo } define Test { @value #x value } testcase "indirect immutable via defines filter is sufficient for param members" { compiles } @type interface Foo { immutable } concrete Test<#x> { immutable #x defines Foo } define Test { @value #x value } testcase "indirect immutable via allows filter is not sufficient for param members" { error require "immutable" require "value" } @value interface Foo { immutable } concrete Test<#x> { immutable #x allows Foo } define Test { @value #x value } testcase "param substitution checked for @type calls" { error require "immutable" require "Foo" } @value interface Foo { } concrete Test<#x> { #x immutable @type call () -> () } define Test { call () { } @category run () -> () run () { \ Test.call() } } testcase "immutable type allowed for @type calls" { compiles } @value interface Foo { immutable } concrete Test<#x> { #x immutable @type call () -> () } define Test { call () { } @category run () -> () run () { \ Test.call() } } testcase "param substitution checked for function params" { error require "immutable" require "Foo" } @value interface Foo { } concrete Test { @type call<#x> #x immutable () -> () } define Test { call () { } @category run () -> () run () { \ Test.call() } } testcase "immutable type allowed for function params" { compiles } @value interface Foo { immutable } concrete Test { @type call<#x> #x immutable () -> () } define Test { call () { } @category run () -> () run () { \ Test.call() } } testcase "immutable type checked for internal refines inheritance" { error require "immutable" require "value" exclude "value2" } @value interface Base { immutable } @value interface Foo { } concrete Test { } define Test { refines Base @value Foo value @value Test value2 } testcase "immutable type checked for internal defines inheritance" { error require "immutable" require "value" exclude "value2" } @type interface Base { immutable } @value interface Foo { } concrete Test { } define Test { defines Base @value Foo value @value Test value2 }