aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-10-05 17:45:03 +0200
committerAleksandr Nogikh <nogikh@google.com>2023-10-06 11:42:31 +0000
commitc2e799237fe66134b015442bc6db181319bef0c1 (patch)
treed68a9608a4b16fe6d5e65cb5504ae81d322f27e8 /pkg/compiler
parent160f76ea821e29048389ecb03e8961c4e9cdf519 (diff)
pkg/compiler: prohibit not DirIn resources inside fmt
The problem mentioned in the previous commit is actually not only ANY-specific, it's only by a happy coincidence that all our descriptions already avoided such situations. Enforce this rule at the compilation stage.
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/check.go16
-rw-r--r--pkg/compiler/testdata/errors2.txt4
-rw-r--r--pkg/compiler/types.go2
3 files changed, 17 insertions, 5 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 5f7bb7108..44c354606 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -672,10 +672,10 @@ func (comp *compiler) checkConstructors() {
switch n := decl.(type) {
case *ast.Call:
for _, arg := range n.Args {
- comp.checkTypeCtors(arg.Type, prog.DirIn, true, true, ctors, inputs, checked)
+ comp.checkTypeCtors(arg.Type, prog.DirIn, true, true, ctors, inputs, checked, nil)
}
if n.Ret != nil {
- comp.checkTypeCtors(n.Ret, prog.DirOut, true, true, ctors, inputs, checked)
+ comp.checkTypeCtors(n.Ret, prog.DirOut, true, true, ctors, inputs, checked, nil)
}
}
}
@@ -699,17 +699,23 @@ func (comp *compiler) checkConstructors() {
}
func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate bool,
- ctors, inputs map[string]bool, checked map[structDir]bool) {
+ ctors, inputs map[string]bool, checked map[structDir]bool, neverOutAt *ast.Pos) {
desc, args, base := comp.getArgsBase(t, isArg)
if base.IsOptional {
canCreate = false
}
+ if desc.CantHaveOut {
+ neverOutAt = &t.Pos
+ }
if desc == typeResource {
// TODO(dvyukov): consider changing this to "dir == prog.DirOut".
// We have few questionable cases where resources can be created
// only by inout struct fields. These structs should be split
// into two different structs: one is in and second is out.
// But that will require attaching dir to individual fields.
+ if dir != prog.DirIn && neverOutAt != nil {
+ comp.error(*neverOutAt, "resource %s cannot be created in fmt", t.Ident)
+ }
if canCreate && dir != prog.DirIn {
r := comp.resources[t.Ident]
for r != nil && !ctors[r.Name.Name] {
@@ -742,7 +748,7 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate
if !fldHasDir {
fldDir = dir
}
- comp.checkTypeCtors(fld.Type, fldDir, false, canCreate, ctors, inputs, checked)
+ comp.checkTypeCtors(fld.Type, fldDir, false, canCreate, ctors, inputs, checked, neverOutAt)
}
return
}
@@ -751,7 +757,7 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate
}
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
- comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, canCreate, ctors, inputs, checked)
+ comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, canCreate, ctors, inputs, checked, neverOutAt)
}
}
}
diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt
index 3cd63ebd2..e99610c58 100644
--- a/pkg/compiler/testdata/errors2.txt
+++ b/pkg/compiler/testdata/errors2.txt
@@ -421,3 +421,7 @@ foo$non_generatable(a compressed_image) (no_minimize) ### call foo$non_generatab
foo$non_minimizable(a compressed_image) (no_generate) ### call foo$non_minimizable refers to type compressed_image and so must be marked no_minimize
foo$non_generatable_via_struct(a ptr[in, struct_non_generatable]) (no_minimize) ### call foo$non_generatable_via_struct refers to type compressed_image and so must be marked no_generate
foo$non_minimizable_via_union(a ptr[in, union_non_minimizable]) (no_generate) ### call foo$non_minimizable_via_union refers to type compressed_image and so must be marked no_minimize
+
+resource for_fmt[int32]
+foo$fmt_copyin(a ptr[in, fmt[dec, for_fmt]])
+foo$fmt_copyout(a ptr[out, fmt[dec, for_fmt]]) ### resource for_fmt cannot be created in fmt
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index 099ab0009..a55a6c50d 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -20,6 +20,7 @@ type typeDesc struct {
CanBeTypedef bool // can be type alias target?
CantBeOpt bool // can't be marked as opt?
CantBeOut bool // can't be used as an explicitly output argument?
+ CantHaveOut bool // everything inside can only be in
NeedBase bool // needs base type when used as field?
MaxColon int // max number of colons (int8:2) on fields
OptArgs int // number of optional arguments in Args array
@@ -764,6 +765,7 @@ var typeFmt = &typeDesc{
CanBeTypedef: true,
CantBeOpt: true,
CantBeOut: true,
+ CantHaveOut: true,
Args: []namedArg{
{Name: "format", Type: typeFmtFormat},
{Name: "value", Type: typeArgType, IsArg: true},