Skip to content

[checklocks] Support iterators #12176

@fancycode

Description

@fancycode

Description

Currently locked access to struct members inside a loop over an iterator is not detected correctly.

Example:

package main

import (
	"strings"
	"sync"
)

type Entries struct {
	mu sync.Mutex
	// +checklocks:mu
	entries []string
}

func (e *Entries) Add(s string) {
	e.mu.Lock()
	defer e.mu.Unlock()

	for item := range strings.SplitSeq(s, " ") {
		e.entries = append(e.entries, item)
	}
}

Error:

go vet -vettool=$HOME/go/bin/checklocks iter_seq_checklocks.go 
# command-line-arguments
./iter_seq_checklocks.go:19:24: invalid field access, mu (&({freevar:e}.mu)) must be locked when accessing entries (locks: no locks held)
./iter_seq_checklocks.go:19:5: invalid field access, mu (&({freevar:e}.mu)) must be locked when accessing entries (locks: no locks held)

This works if the lock is acquired inside the loop.

func (e *Entries) Add(s string) {
	for item := range strings.SplitSeq(s, " ") {
		e.mu.Lock()
		e.entries = append(e.entries, item)
		e.mu.Unlock()
	}
}

Is this feature related to a specific bug?

No response

Do you have a specific solution in mind?

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions