diff options
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/compiler/check.go | 32 | ||||
| -rw-r--r-- | pkg/compiler/testdata/errors2.txt | 5 |
2 files changed, 27 insertions, 10 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index e8abc574e..9bb8c1c0c 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -547,16 +547,17 @@ type structDir struct { } func (comp *compiler) checkConstructors() { - ctors := make(map[string]bool) // resources for which we have ctors + ctors := make(map[string]bool) // resources for which we have ctors + inputs := make(map[string]bool) // resources which are used as inputs checked := make(map[structDir]bool) for _, decl := range comp.desc.Nodes { switch n := decl.(type) { case *ast.Call: for _, arg := range n.Args { - comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, checked) + comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, inputs, checked) } if n.Ret != nil { - comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, checked) + comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, inputs, checked) } } } @@ -564,17 +565,23 @@ func (comp *compiler) checkConstructors() { switch n := decl.(type) { case *ast.Resource: name := n.Name.Name - if !ctors[name] && comp.used[name] { + if !comp.used[name] { + continue + } + if !ctors[name] { comp.error(n.Pos, "resource %v can't be created"+ - " (never mentioned as a syscall return value or output argument/field)", - name) + " (never mentioned as a syscall return value or output argument/field)", name) + } + if !inputs[name] { + comp.error(n.Pos, "resource %v is never used as an input"+ + "(such resources are not useful)", name) } } } } func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, - ctors map[string]bool, checked map[structDir]bool) { + ctors, inputs map[string]bool, checked map[structDir]bool) { desc := comp.getTypeDesc(t) if desc == typeResource { // TODO(dvyukov): consider changing this to "dir == prog.DirOut". @@ -589,6 +596,13 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, r = comp.resources[r.Base.Ident] } } + if dir != prog.DirOut { + r := comp.resources[t.Ident] + for r != nil && !inputs[r.Name.Name] { + inputs[r.Name.Name] = true + r = comp.resources[r.Base.Ident] + } + } return } if desc == typeStruct { @@ -600,7 +614,7 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, } checked[key] = true for _, fld := range s.Fields { - comp.checkTypeCtors(fld.Type, dir, false, ctors, checked) + comp.checkTypeCtors(fld.Type, dir, false, ctors, inputs, checked) } return } @@ -610,7 +624,7 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool, _, args, _ := comp.getArgsBase(t, isArg) for i, arg := range args { if desc.Args[i].Type == typeArgType { - comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, ctors, checked) + comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, ctors, inputs, checked) } } } diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt index fb69c8c5f..68b8a66df 100644 --- a/pkg/compiler/testdata/errors2.txt +++ b/pkg/compiler/testdata/errors2.txt @@ -11,6 +11,7 @@ resource r2[r1] ### recursive resource r2->r1->r2 resource r3[int32] ### unused resource r3 foo$0(a0 ptr[out, r0], a1 ptr[out, r1], a2 ptr[out, r2]) +foo$1(a0 r0, a1 r1, a2 r2) # Recursive structs/unions. @@ -175,9 +176,11 @@ resource r104[int8] resource r105[int8] resource r106[int8] ### resource r106 can't be created (never mentioned as a syscall return value or output argument/field) resource r107[int8] ### resource r107 can't be created (never mentioned as a syscall return value or output argument/field) +resource r108[int8] ### resource r108 is never used as an input(such resources are not useful) -foo$300(a r100) +foo$300(a0 r100, a1 r101, a2 r102, a3 r103, a4 r104) foo$301(a ptr[out, array[r103]], b ptr[in, s300], c r107) r104 +foo$302() r108 s300 { f1 ptr[inout, s301] |
