diff --git a/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala b/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala index 53e12293..4962dfff 100644 --- a/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala +++ b/semantics/src/test/scala/aqua/semantics/SemanticsSpec.scala @@ -1012,4 +1012,25 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside { atLeast(1, errors.toChain.toList) shouldBe a[RulesViolated[Span.S]] } } + + // NOTE: This should be true until aqua has immutable map type + it should "prohibit putting stream maps into collection" in { + def test(prefix: String = "") = { + val script = s"""|func test(arr: []⊤) -> string: + | <- "test" + | + |func main() -> string: + | map: %string + | <- test(${prefix}[map])""".stripMargin + + insideSemErrors(script) { errors => + errors.collect { case RulesViolated(_, messages) => messages }.toList.flatten + .contains("Value of type '%string' could not be put into a collection") shouldBe (true) + } + } + + test() + test("?") + test("*") + } } diff --git a/types/src/main/scala/aqua/types/Type.scala b/types/src/main/scala/aqua/types/Type.scala index 85829685..9091444b 100644 --- a/types/src/main/scala/aqua/types/Type.scala +++ b/types/src/main/scala/aqua/types/Type.scala @@ -330,6 +330,7 @@ object CollectionType { sealed trait ImmutableCollectionType extends CollectionType with DataType { def withElement(t: DataType): ImmutableCollectionType } + sealed trait MutableStreamType extends CollectionType { def toCanon: ImmutableCollectionType } @@ -389,7 +390,7 @@ case class StreamMapType(override val element: DataType) extends MutableStreamTy override def toString: String = s"%$element" - def getFunc(f: Func): ArrowType ={ + def getFunc(f: Func): ArrowType = { val (args, rets) = f match { case Get => (ScalarType.string :: Nil) -> (ArrayType(element) :: Nil) @@ -431,7 +432,7 @@ object StreamMapType { def funcByString(s: String): Option[Func] = Func.values.find(_.name == s) - lazy val allFuncs: List[Func] = Func.values.toList + lazy val allFuncs: List[Func] = Func.values.toList def top(): StreamMapType = StreamMapType(TopType) } @@ -602,9 +603,11 @@ case class ArrowType(domain: ProductType, codomain: ProductType) extends Type { object Type { /** - * `StreamType` is collectible with canonicalization + * `StreamType` is collectible with canonicalization. + * Note: until aqua type system has immutable maps, + * they are not collectible */ - type CollectibleType = DataType | MutableStreamType + type CollectibleType = DataType | StreamType def isStreamType(t: Type): Boolean = t match {