aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--check/absolute.go4
-rw-r--r--cmd/earlyinit/modprobe.go4
-rw-r--r--cmd/hakurei/json.go11
-rw-r--r--cmd/mbf/internal/pkgserver/search.go2
-rw-r--r--cmd/sharefs/fuse.go4
-rw-r--r--command/parse.go4
-rw-r--r--container/container.go7
-rw-r--r--container/dispatcher_test.go2
-rw-r--r--container/errors.go14
-rw-r--r--container/init_test.go16
-rw-r--r--ext/ext_test.go2
-rw-r--r--hst/fs.go13
-rw-r--r--hst/fs_test.go4
-rw-r--r--hst/fsephemeral.go7
-rw-r--r--internal/dbus/address.go4
-rw-r--r--internal/lockedfile/transform_test.go2
-rw-r--r--internal/outcome/finalise.go3
-rw-r--r--internal/outcome/hsu.go10
-rw-r--r--internal/outcome/process.go6
-rw-r--r--internal/outcome/shim.go4
-rw-r--r--internal/pipewire/pod.go8
-rw-r--r--internal/pkg/pkg.go36
-rw-r--r--internal/report/report.go3
-rw-r--r--internal/rosa/azalea/evaluate.go11
-rw-r--r--internal/rosa/azalea/evaluate_test.go2
-rw-r--r--internal/rosa/report.go5
-rw-r--r--internal/rosa/state.go2
-rw-r--r--internal/store/store_test.go4
-rw-r--r--internal/stub/errors.go7
-rw-r--r--internal/system/dbus.go6
-rw-r--r--internal/wayland/wayland.go6
-rw-r--r--ldd/exec_test.go4
-rw-r--r--message/message.go52
-rw-r--r--test/internal/sandbox/assert.go16
-rw-r--r--vfs/mountinfo.go2
35 files changed, 146 insertions, 141 deletions
diff --git a/check/absolute.go b/check/absolute.go
index 4df3c59b..1a050d06 100644
--- a/check/absolute.go
+++ b/check/absolute.go
@@ -20,8 +20,8 @@ func (e AbsoluteError) Error() string {
}
func (e AbsoluteError) Is(target error) bool {
- var ce AbsoluteError
- if !errors.As(target, &ce) {
+ ce, ok := errors.AsType[AbsoluteError](target)
+ if !ok {
return errors.Is(target, syscall.EINVAL)
}
return e == ce
diff --git a/cmd/earlyinit/modprobe.go b/cmd/earlyinit/modprobe.go
index 5a9868d4..8addf973 100644
--- a/cmd/earlyinit/modprobe.go
+++ b/cmd/earlyinit/modprobe.go
@@ -57,8 +57,8 @@ func dispatchModprobe(
continue
}
- var exitError *exec.ExitError
- if !errors.As(err, &exitError) || exitError == nil {
+ exitError, ok := errors.AsType[*exec.ExitError](err)
+ if !ok || exitError == nil {
r.Dispatch(report.Degraded, "invoke modprobe", err)
continue
}
diff --git a/cmd/hakurei/json.go b/cmd/hakurei/json.go
index 30eb4334..d0d978d3 100644
--- a/cmd/hakurei/json.go
+++ b/cmd/hakurei/json.go
@@ -7,7 +7,8 @@ import (
"strconv"
)
-// decodeJSON decodes json from r and stores it in v. A non-nil error results in a call to fatal.
+// decodeJSON decodes json from r and stores it in v. A non-nil error results in
+// a call to fatal.
func decodeJSON(fatal func(v ...any), op string, r io.Reader, v any) {
err := json.NewDecoder(r).Decode(v)
if err == nil {
@@ -47,14 +48,14 @@ func encodeJSON(fatal func(v ...any), output io.Writer, short bool, v any) {
}
if err := encoder.Encode(v); err != nil {
- var marshalerError *json.MarshalerError
- if errors.As(err, &marshalerError) && marshalerError != nil {
+ if e, ok := errors.AsType[*json.MarshalerError](err); ok && e != nil {
// this likely indicates an implementation error in hst
- fatal("cannot encode json for " + marshalerError.Type.String() + ": " + marshalerError.Err.Error())
+ fatal("cannot encode json for " + e.Type.String() + ": " + e.Err.Error())
return
}
- // UnsupportedTypeError, UnsupportedValueError: incorrect usage, does not need to be handled
+ // UnsupportedTypeError, UnsupportedValueError: incorrect usage, does
+ // not need to be handled
fatal("cannot write json: " + err.Error())
}
}
diff --git a/cmd/mbf/internal/pkgserver/search.go b/cmd/mbf/internal/pkgserver/search.go
index 5756512f..15947804 100644
--- a/cmd/mbf/internal/pkgserver/search.go
+++ b/cmd/mbf/internal/pkgserver/search.go
@@ -74,7 +74,7 @@ func (s *searchCache) clean() {
}
func indexsum(in [][]int) int {
sum := 0
- for i := 0; i < len(in); i++ {
+ for i := range in {
sum += in[i][1] - in[i][0]
}
return sum
diff --git a/cmd/sharefs/fuse.go b/cmd/sharefs/fuse.go
index c9855eb7..5dfbf385 100644
--- a/cmd/sharefs/fuse.go
+++ b/cmd/sharefs/fuse.go
@@ -508,8 +508,8 @@ func _main(s ...string) (exitCode int) {
if !z.AllowOrphan {
if err := z.Wait(); err != nil {
- var exitError *exec.ExitError
- if !errors.As(err, &exitError) || exitError == nil {
+ exitError, ok := errors.AsType[*exec.ExitError](err)
+ if !ok || exitError == nil {
log.Println(err)
return 5
}
diff --git a/command/parse.go b/command/parse.go
index 8e21433c..1a3f2ce3 100644
--- a/command/parse.go
+++ b/command/parse.go
@@ -91,8 +91,8 @@ func (n *node) MustParse(arguments []string, handleError func(error)) {
case ErrEmptyTree:
os.Exit(1)
default:
- var flagError FlagError
- if !errors.As(err, &flagError) { // returned by HandlerFunc
+ flagError, ok := errors.AsType[FlagError](err)
+ if !ok { // returned by HandlerFunc
handleError(err)
os.Exit(1)
}
diff --git a/container/container.go b/container/container.go
index 8af77315..3571d04a 100644
--- a/container/container.go
+++ b/container/container.go
@@ -154,11 +154,8 @@ func (e *StartError) Error() string {
return e.Step
}
- {
- var syscallError *os.SyscallError
- if errors.As(e.Err, &syscallError) && syscallError != nil {
- return e.Step + " " + syscallError.Error()
- }
+ if se, ok := errors.AsType[*os.SyscallError](e.Err); ok && se != nil {
+ return e.Step + " " + se.Error()
}
return e.Step + ": " + e.Err.Error()
diff --git a/container/dispatcher_test.go b/container/dispatcher_test.go
index 49631854..242af1bf 100644
--- a/container/dispatcher_test.go
+++ b/container/dispatcher_test.go
@@ -235,8 +235,6 @@ func checkOpBehaviour(t *testing.T, testCases []opBehaviourTestCase) {
})
}
-func sliceAddr[S any](s []S) *[]S { return &s }
-
func newCheckedFile(t *testing.T, name, wantData string, closeErr error) osFile {
f := &checkedOsFile{t: t, name: name, want: wantData, closeErr: closeErr}
// check happens in Close, and cleanup is not guaranteed to run, so relying
diff --git a/container/errors.go b/container/errors.go
index 5a67bb4c..053bdeb7 100644
--- a/container/errors.go
+++ b/container/errors.go
@@ -46,9 +46,8 @@ func messageFromError(err error) (m string, ok bool) {
// While this is usable for pointer errors, such use should be avoided as nil
// check is omitted.
func messagePrefix[T error](prefix string, err error) (string, bool) {
- var targetError T
- if errors.As(err, &targetError) {
- return prefix + targetError.Error(), true
+ if e, ok := errors.AsType[T](err); ok {
+ return prefix + e.Error(), true
}
return zeroString, false
}
@@ -58,9 +57,8 @@ func messagePrefixP[V any, T interface {
*V
error
}](prefix string, err error) (string, bool) {
- var targetError T
- if errors.As(err, &targetError) && targetError != nil {
- return prefix + targetError.Error(), true
+ if e, ok := errors.AsType[T](err); ok && e != nil {
+ return prefix + e.Error(), true
}
return zeroString, false
}
@@ -109,8 +107,8 @@ func optionalErrorUnwrap(err error) error {
// errnoFallback returns the concrete errno from an error, or a [os.PathError] fallback.
func errnoFallback(op, path string, err error) (syscall.Errno, *os.PathError) {
- var errno syscall.Errno
- if !errors.As(err, &errno) {
+ errno, ok := errors.AsType[syscall.Errno](err)
+ if !ok {
return 0, &os.PathError{Op: op, Path: path, Err: err}
}
return errno, nil
diff --git a/container/init_test.go b/container/init_test.go
index 23d0a7b3..fe0e627a 100644
--- a/container/init_test.go
+++ b/container/init_test.go
@@ -95,7 +95,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -123,7 +123,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -152,7 +152,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -182,7 +182,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -213,7 +213,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -245,7 +245,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -279,7 +279,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
@@ -315,7 +315,7 @@ func TestInitEntrypoint(t *testing.T) {
Uid: 1 << 16,
Gid: 1 << 15,
Hostname: "hakurei-check",
- Ops: (*Ops)(sliceAddr(make(Ops, 1))),
+ Ops: new(make(Ops, 1)),
SeccompRules: make([]std.NativeRule, 0),
SeccompPresets: std.PresetStrict,
RetainSession: true,
diff --git a/ext/ext_test.go b/ext/ext_test.go
index a93a1b52..74d825cd 100644
--- a/ext/ext_test.go
+++ b/ext/ext_test.go
@@ -39,7 +39,7 @@ func TestSyscall(t *testing.T) {
t.Errorf("Unmarshal: %v, want %v", got, tc.want)
}
})
- if errors.As(tc.err, new(ext.SyscallNameError)) {
+ if _, ok := errors.AsType[ext.SyscallNameError](tc.err); ok {
return
}
diff --git a/hst/fs.go b/hst/fs.go
index 13645d1a..cb35f925 100644
--- a/hst/fs.go
+++ b/hst/fs.go
@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"reflect"
+ "strings"
"hakurei.app/check"
)
@@ -78,17 +79,17 @@ type FSImplError struct{ Value FilesystemConfig }
func (f FSImplError) Error() string {
implType := reflect.TypeOf(f.Value)
- var name string
- for implType != nil && implType.Kind() == reflect.Ptr {
- name += "*"
+ var buf strings.Builder
+ for implType != nil && implType.Kind() == reflect.Pointer {
+ buf.WriteByte('*')
implType = implType.Elem()
}
if implType != nil {
- name += implType.Name()
+ buf.WriteString(implType.Name())
} else {
- name += "nil"
+ buf.WriteString("nil")
}
- return fmt.Sprintf("implementation %s not supported", name)
+ return "implementation " + buf.String() + " not supported"
}
// FilesystemConfigJSON is the [json] adapter for [FilesystemConfig].
diff --git a/hst/fs_test.go b/hst/fs_test.go
index 94d44078..a88970b7 100644
--- a/hst/fs_test.go
+++ b/hst/fs_test.go
@@ -103,7 +103,7 @@ func TestFilesystemConfigJSON(t *testing.T) {
t.Run("marshal", func(t *testing.T) {
t.Parallel()
wantErr := tc.wantErr
- if errors.As(wantErr, new(hst.FSTypeError)) {
+ if _, ok := errors.AsType[hst.FSTypeError](wantErr); ok {
// for unsupported implementation tc
wantErr = hst.FSImplError{Value: stubFS{"cat"}}
}
@@ -139,7 +139,7 @@ func TestFilesystemConfigJSON(t *testing.T) {
t.Run("unmarshal", func(t *testing.T) {
t.Parallel()
if tc.data == "\x00" && tc.sData == "\x00" {
- if errors.As(tc.wantErr, new(hst.FSImplError)) {
+ if _, ok := errors.AsType[hst.FSImplError](tc.wantErr); ok {
// this error is only returned on marshal
return
}
diff --git a/hst/fsephemeral.go b/hst/fsephemeral.go
index 9da79003..d1c01bca 100644
--- a/hst/fsephemeral.go
+++ b/hst/fsephemeral.go
@@ -43,18 +43,13 @@ func (e *FSEphemeral) Apply(z *ApplyState) {
return
}
- size := e.Size
- if size < 0 {
- size = 0
- }
-
perm := e.Perm
if perm == 0 {
perm = fsEphemeralDefaultPerm
}
if e.Write {
- z.Tmpfs(e.Target, size, perm)
+ z.Tmpfs(e.Target, max(e.Size, 0), perm)
} else {
z.Readonly(e.Target, perm)
}
diff --git a/internal/dbus/address.go b/internal/dbus/address.go
index edee7e20..4afea9e1 100644
--- a/internal/dbus/address.go
+++ b/internal/dbus/address.go
@@ -80,7 +80,7 @@ func unescapeValue(v []byte) (val []byte, errno ParseError) {
continue
}
- if ib := bytes.IndexByte([]byte("-_/.\\*"), b); ib != -1 { // - // _/.\*
+ if found := bytes.Contains([]byte("-_/.\\*"), []byte{b}); found { // - // _/.\*
goto opt
} else if b >= '0' && b <= '9' { // 0-9
goto opt
@@ -101,7 +101,7 @@ func unescapeValue(v []byte) (val []byte, errno ParseError) {
break
}
if c, err := hex.Decode(val[i:i+1], v[iu+1:iu+3]); err != nil {
- if errors.As(err, new(hex.InvalidByteError)) {
+ if _, ok := errors.AsType[hex.InvalidByteError](err); ok {
errno = ErrBadValHexByte
break
}
diff --git a/internal/lockedfile/transform_test.go b/internal/lockedfile/transform_test.go
index 1394ada7..95807493 100644
--- a/internal/lockedfile/transform_test.go
+++ b/internal/lockedfile/transform_test.go
@@ -40,7 +40,7 @@ func TestTransform(t *testing.T) {
const maxChunkWords = 8 << 10
buf := make([]byte, 2*maxChunkWords*8)
- for i := uint64(0); i < 2*maxChunkWords; i++ {
+ for i := range uint64(2 * maxChunkWords) {
binary.LittleEndian.PutUint64(buf[i*8:], i)
}
if err := lockedfile.Write(path, bytes.NewReader(buf[:8]), 0666); err != nil {
diff --git a/internal/outcome/finalise.go b/internal/outcome/finalise.go
index d74c648c..4049b8d3 100644
--- a/internal/outcome/finalise.go
+++ b/internal/outcome/finalise.go
@@ -58,8 +58,7 @@ func (k *outcome) finalise(
supp := make([]string, len(config.Groups))
for i, name := range config.Groups {
if gid, err := k.lookupGroupId(name); err != nil {
- var unknownGroupError user.UnknownGroupError
- if errors.As(err, &unknownGroupError) {
+ if unknownGroupError, ok := errors.AsType[user.UnknownGroupError](err); ok {
return newWithMessageError(fmt.Sprintf("unknown group %q", name), unknownGroupError)
} else {
return &hst.AppError{Step: "look up group by name", Err: err, Msg: err.Error()}
diff --git a/internal/outcome/hsu.go b/internal/outcome/hsu.go
index 118fd681..ecb616c0 100644
--- a/internal/outcome/hsu.go
+++ b/internal/outcome/hsu.go
@@ -51,18 +51,16 @@ func (h *Hsu) ID() (int, error) {
cmd.Stderr = os.Stderr // pass through fatal messages
cmd.Env = make([]string, 0)
cmd.Dir = fhs.Root
- var (
- p []byte
- exitError *exec.ExitError
- )
-
+ var p []byte
const step = "obtain uid from hsu"
if p, h.idErr = h.k.cmdOutput(cmd); h.idErr == nil {
h.id, h.idErr = strconv.Atoi(string(p))
if h.idErr != nil {
h.idErr = &hst.AppError{Step: step, Err: h.idErr, Msg: "invalid uid string from hsu"}
}
- } else if errors.As(h.idErr, &exitError) && exitError != nil && exitError.ExitCode() == 1 {
+ } else if exitError, ok := errors.AsType[*exec.ExitError](h.idErr); ok &&
+ exitError != nil &&
+ exitError.ExitCode() == 1 {
// hsu prints an error message in this case
h.idErr = &hst.AppError{Step: step, Err: ErrHsuAccess}
} else if errors.Is(h.idErr, os.ErrNotExist) {
diff --git a/internal/outcome/process.go b/internal/outcome/process.go
index 67851edc..614b22fc 100644
--- a/internal/outcome/process.go
+++ b/internal/outcome/process.go
@@ -328,11 +328,11 @@ func (k *outcome) main(msg message.Msg, identifierFd int) {
}
if err := k.sys.Revert((*system.Criteria)(&ec)); err != nil {
- var joinError interface {
+ joinError, ok := errors.AsType[interface {
Unwrap() []error
error
- }
- if !errors.As(err, &joinError) || joinError == nil {
+ }](err)
+ if !ok || joinError == nil {
perror(err, "revert system setup")
} else {
for _, v := range joinError.Unwrap() {
diff --git a/internal/outcome/shim.go b/internal/outcome/shim.go
index b2074928..6e039b65 100644
--- a/internal/outcome/shim.go
+++ b/internal/outcome/shim.go
@@ -390,8 +390,8 @@ func shimEntrypoint(k syscallDispatcher) {
if err := k.containerWait(z); err != nil {
sp.destroy()
- var exitError *exec.ExitError
- if !errors.As(err, &exitError) {
+ exitError, ok := errors.AsType[*exec.ExitError](err)
+ if !ok {
if errors.Is(err, context.Canceled) {
k.exit(hst.ExitCancel)
}
diff --git a/internal/pipewire/pod.go b/internal/pipewire/pod.go
index 7cfafc87..e085af3d 100644
--- a/internal/pipewire/pod.go
+++ b/internal/pipewire/pod.go
@@ -176,8 +176,8 @@ func marshalValueAppendRaw(data []byte, v reflect.Value) ([]byte, error) {
case reflect.Struct:
data = SPA_TYPE_Struct.append(data)
var err error
- for i := 0; i < v.NumField(); i++ {
- data, err = marshalValueAppend(data, v.Field(i))
+ for _, field := range v.Fields() {
+ data, err = marshalValueAppend(data, field)
if err != nil {
return data, err
}
@@ -370,8 +370,8 @@ func unmarshalValue(data []byte, v reflect.Value, wireSizeP *Word) error {
}
var fieldWireSize Word
- for i := 0; i < v.NumField(); i++ {
- if err := unmarshalValue(data, v.Field(i), &fieldWireSize); err != nil {
+ for _, field := range v.Fields() {
+ if err := unmarshalValue(data, field, &fieldWireSize); err != nil {
return err
}
// bounds check completed in successful call to unmarshalValue
diff --git a/internal/pkg/pkg.go b/internal/pkg/pkg.go
index e90bb72c..7b4c9637 100644
--- a/internal/pkg/pkg.go
+++ b/internal/pkg/pkg.go
@@ -238,8 +238,8 @@ func (t *TContext) destroy(errP *error) {
if chmodErr != nil || removeErr != nil {
*errP = errors.Join(*errP, chmodErr, removeErr)
} else if errors.Is(*errP, os.ErrExist) {
- var linkError *os.LinkError
- if errors.As(*errP, &linkError) && linkError != nil &&
+ if linkError, ok := errors.AsType[*os.LinkError](*errP); ok &&
+ linkError != nil &&
linkError.Op == "rename" {
// two artifacts may be backed by the same file
*errP = nil
@@ -974,36 +974,42 @@ func (e *ScrubError) Unwrap() []error {
// Error returns a multi-line representation of [ScrubError].
func (e *ScrubError) Error() string {
var segments []string
+ var buf strings.Builder
+
if len(e.ChecksumMismatches) > 0 {
- s := "checksum mismatches:\n"
+ buf.Reset()
+ buf.WriteString("checksum mismatches:\n")
for _, m := range e.ChecksumMismatches {
- s += m.Error() + "\n"
+ buf.WriteString(m.Error() + "\n")
}
- segments = append(segments, s)
+ segments = append(segments, buf.String())
}
if len(e.DanglingIdentifiers) > 0 {
- s := "dangling identifiers:\n"
+ buf.Reset()
+ buf.WriteString("dangling identifiers:\n")
for _, id := range e.DanglingIdentifiers {
- s += Encode(id) + "\n"
+ buf.WriteString(Encode(id) + "\n")
}
- segments = append(segments, s)
+ segments = append(segments, buf.String())
}
if len(e.DanglingStatus) > 0 {
- s := "dangling status:\n"
+ buf.Reset()
+ buf.WriteString("dangling status:\n")
for _, id := range e.DanglingStatus {
- s += Encode(id) + "\n"
+ buf.WriteString(Encode(id) + "\n")
}
- segments = append(segments, s)
+ segments = append(segments, buf.String())
}
if len(e.Errs) > 0 {
- s := "errors during scrub:\n"
+ buf.Reset()
+ buf.WriteString("errors during scrub:\n")
for pathname, errs := range e.errs {
- s += " " + pathname.Value() + ":\n"
+ buf.WriteString(" " + pathname.Value() + ":\n")
for _, err := range errs {
- s += " " + err.Error() + "\n"
+ buf.WriteString(" " + err.Error() + "\n")
}
}
- segments = append(segments, s)
+ segments = append(segments, buf.String())
}
return strings.Join(segments, "\n")
}
diff --git a/internal/report/report.go b/internal/report/report.go
index cbac1c34..c418c709 100644
--- a/internal/report/report.go
+++ b/internal/report/report.go
@@ -102,8 +102,7 @@ func (e Error) MarshalJSON() (data []byte, err error) {
v.Severity = e.Severity
}
- var re RepresentableError
- if errors.As(e.Err, &re) {
+ if re, ok := errors.AsType[RepresentableError](e.Err); ok {
v.Err, err = json.Marshal(re)
} else {
v.Err, err = json.Marshal(e.Err.Error())
diff --git a/internal/rosa/azalea/evaluate.go b/internal/rosa/azalea/evaluate.go
index 32c4f066..044e6826 100644
--- a/internal/rosa/azalea/evaluate.go
+++ b/internal/rosa/azalea/evaluate.go
@@ -6,6 +6,7 @@ import (
"maps"
"reflect"
"slices"
+ "strings"
"unique"
)
@@ -107,8 +108,8 @@ func (e TypeError) Error() string {
}
func (e TypeError) Is(err error) bool {
- var v TypeError
- return errors.As(err, &v) &&
+ v, ok := errors.AsType[TypeError](err)
+ return ok &&
e.Asserted == v.Asserted &&
e.Concrete == v.Concrete
}
@@ -233,14 +234,14 @@ func evaluateAny(d PF, s []Frame, expr, rp any) bool {
return evaluateAny(d, s, e[0], rp)
}
}
- var v string
+ var v strings.Builder
for i := range e {
var _r string
if evaluate(d, s, e[i], &_r) {
- v += _r
+ v.WriteString(_r)
}
}
- store(rp, v)
+ store(rp, v.String())
return true
case Array:
diff --git a/internal/rosa/azalea/evaluate_test.go b/internal/rosa/azalea/evaluate_test.go
index 801b07a3..4a6c2f56 100644
--- a/internal/rosa/azalea/evaluate_test.go
+++ b/internal/rosa/azalea/evaluate_test.go
@@ -214,7 +214,7 @@ func TestEvaluate(t *testing.T) {
}
var errEquals bool
- if errors.As(err, new(TypeError)) {
+ if _, ok := errors.AsType[TypeError](err); ok {
errEquals = errors.Is(err, tc.err)
} else {
errEquals = reflect.DeepEqual(err, tc.err)
diff --git a/internal/rosa/report.go b/internal/rosa/report.go
index 54f60fb3..a97ff8e8 100644
--- a/internal/rosa/report.go
+++ b/internal/rosa/report.go
@@ -212,11 +212,10 @@ func (r *Report) HandleAccess(errP *error) func() {
*errP = err
}
- var runtimeError interface {
+ if runtimeError, ok := errors.AsType[interface {
Addr() uintptr
runtime.Error
- }
- if errors.As(*errP, &runtimeError) {
+ }](*errP); ok {
offset := int(runtimeError.Addr() - uintptr(unsafe.Pointer(unsafe.SliceData(r.data))))
// best effort for fragile uintptr
if offset >= 0 {
diff --git a/internal/rosa/state.go b/internal/rosa/state.go
index feb06f82..8f9aba6d 100644
--- a/internal/rosa/state.go
+++ b/internal/rosa/state.go
@@ -1063,7 +1063,7 @@ func (ctx *evalContext) pf(
checksum, ok := kc.(string)
if !ok {
err = azalea.TypeError{
- Concrete: reflect.TypeOf(checksum),
+ Concrete: reflect.TypeOf(kc),
Asserted: reflect.TypeFor[string](),
}
return
diff --git a/internal/store/store_test.go b/internal/store/store_test.go
index 2210f543..cdaad24e 100644
--- a/internal/store/store_test.go
+++ b/internal/store/store_test.go
@@ -29,7 +29,7 @@ func TestStoreBigLock(t *testing.T) {
{
s := store.New(check.MustAbs(t.TempDir()).Append("state"))
- for i := 0; i < 2; i++ { // check once behaviour
+ for range 2 { // check once behaviour
if unlock, err := bigLock(s); err != nil {
t.Fatalf("bigLock: error = %v", err)
} else {
@@ -43,7 +43,7 @@ func TestStoreBigLock(t *testing.T) {
wantErr := &hst.AppError{Step: "create state store directory",
Err: &os.PathError{Op: "mkdir", Path: "/proc/nonexistent", Err: syscall.ENOENT}}
- for i := 0; i < 2; i++ { // check once behaviour
+ for range 2 { // check once behaviour
if _, err := bigLock(store.New(check.MustAbs("/proc/nonexistent"))); !reflect.DeepEqual(err, wantErr) {
t.Errorf("bigLock: error = %#v, want %#v", err, wantErr)
}
diff --git a/internal/stub/errors.go b/internal/stub/errors.go
index c89149be..560bde6e 100644
--- a/internal/stub/errors.go
+++ b/internal/stub/errors.go
@@ -20,9 +20,6 @@ func (e UniqueError) Error() string {
}
func (e UniqueError) Is(target error) bool {
- var u UniqueError
- if !errors.As(target, &u) {
- return false
- }
- return e == u
+ u, ok := errors.AsType[UniqueError](target)
+ return ok && e == u
}
diff --git a/internal/system/dbus.go b/internal/system/dbus.go
index 70acdbdb..a6587ed5 100644
--- a/internal/system/dbus.go
+++ b/internal/system/dbus.go
@@ -172,12 +172,12 @@ func (s *linePrefixWriter) write(p []byte, a int) (int, error) {
return a, syscall.ENOMEM
}
- if i := bytes.IndexByte(p, '\n'); i == -1 {
+ if before, after, ok := bytes.Cut(p, []byte{'\n'}); !ok {
n, _ := s.buf.Write(p)
s.n += n
return a + n, nil
} else {
- n, _ := s.buf.Write(p[:i])
+ n, _ := s.buf.Write(before)
s.n += n + 1
v := s.buf.String()
@@ -190,7 +190,7 @@ func (s *linePrefixWriter) write(p []byte, a int) (int, error) {
}
s.buf.Reset()
- return s.write(p[i+1:], a+n+1)
+ return s.write(after, a+n+1)
}
}
diff --git a/internal/wayland/wayland.go b/internal/wayland/wayland.go
index 544f5cc9..1b5d5b64 100644
--- a/internal/wayland/wayland.go
+++ b/internal/wayland/wayland.go
@@ -130,13 +130,11 @@ func (e *Error) Error() string {
return e.withPrefix("cannot connect to " + e.Host)
case RCleanup:
- var pathError *os.PathError
- if errors.As(e.Errno, &pathError) && pathError != nil {
+ if pathError, ok := errors.AsType[*os.PathError](e.Errno); ok && pathError != nil {
return pathError.Error()
}
- var errno syscall.Errno
- if errors.As(e.Errno, &errno) && errno != 0 {
+ if errno, ok := errors.AsType[syscall.Errno](e.Errno); ok && errno != 0 {
return "cannot close wayland close_fd pipe: " + errno.Error()
}
diff --git a/ldd/exec_test.go b/ldd/exec_test.go
index b24b30e4..4621d335 100644
--- a/ldd/exec_test.go
+++ b/ldd/exec_test.go
@@ -20,8 +20,8 @@ func TestExec(t *testing.T) {
_, err := ldd.Resolve(t.Context(), nil, check.MustAbs("/proc/nonexistent"))
- var exitError *exec.ExitError
- if !errors.As(err, &exitError) {
+ exitError, ok := errors.AsType[*exec.ExitError](err)
+ if !ok {
t.Fatalf("Exec: error has incorrect concrete type: %#v", err)
}
diff --git a/message/message.go b/message/message.go
index aa4870f9..3bb223a1 100644
--- a/message/message.go
+++ b/message/message.go
@@ -1,4 +1,5 @@
-// Package message provides interfaces and a base implementation for extended reporting on top of [log.Logger]
+// Package message provides interfaces and a base implementation for extended
+// reporting on top of [log.Logger]
package message
import (
@@ -15,10 +16,11 @@ type Error interface {
error
}
-// GetMessage returns whether an error implements [Error], and the message if it does.
+// GetMessage returns whether an error implements [Error], and the message if
+// it does.
func GetMessage(err error) (string, bool) {
- var e Error
- if !errors.As(err, &e) || e == nil {
+ e, ok := errors.AsType[Error](err)
+ if !ok || e == nil {
return "", false
}
return e.Message(), true
@@ -29,30 +31,43 @@ type Msg interface {
// GetLogger returns the address of the underlying [log.Logger].
GetLogger() *log.Logger
- // IsVerbose atomically loads and returns whether [Msg] has verbose logging enabled.
+ // IsVerbose atomically loads and returns whether [Msg] has verbose logging
+ // enabled.
IsVerbose() bool
- // SwapVerbose atomically stores a new verbose state and returns the previous value held by [Msg].
+ // SwapVerbose atomically stores a new verbose state and returns the
+ // previous value held by [Msg].
SwapVerbose(verbose bool) bool
- // Verbose passes its argument to the Println method of the underlying [log.Logger] if IsVerbose returns true.
+ // Verbose passes its argument to the Println method of the underlying
+ // [log.Logger] if IsVerbose returns true.
Verbose(v ...any)
- // Verbosef passes its argument to the Printf method of the underlying [log.Logger] if IsVerbose returns true.
+ // Verbosef passes its argument to the Printf method of the underlying
+ // [log.Logger] if IsVerbose returns true.
Verbosef(format string, v ...any)
- // Suspend causes the embedded [Suspendable] to withhold writes to its downstream [io.Writer].
- // Suspend returns false and is a noop if called between calls to Suspend and Resume.
+ // Suspend causes the embedded [Suspendable] to withhold writes to its
+ // downstream [io.Writer].
+ //
+ // Suspend returns false and is a noop if called between calls to Suspend
+ // and Resume.
Suspend() bool
- // Resume dumps the entire buffer held by the embedded [Suspendable] and stops withholding future writes.
+ // Resume dumps the entire buffer held by the embedded [Suspendable] and
+ // stops withholding future writes.
+ //
// Resume returns false and is a noop if a call to Suspend does not precede it.
Resume() bool
- // BeforeExit runs implementation-specific cleanup code, and optionally prints warnings.
+ // BeforeExit runs implementation-specific cleanup code, and optionally
+ // prints warnings.
+ //
// BeforeExit is called before [os.Exit].
BeforeExit()
}
// defaultMsg is the default implementation of the [Msg] interface.
-// The zero value is not safe for use. Callers should use the [New] function instead.
+//
+// The zero value is not safe for use. Callers should use the [New] function
+// instead.
type defaultMsg struct {
verbose atomic.Bool
@@ -61,8 +76,9 @@ type defaultMsg struct {
}
// New initialises a downstream [log.Logger] for a new [Msg].
-// The [log.Logger] should no longer be configured after [New] returns.
-// If downstream is nil, a new logger is initialised in its place.
+//
+// The [log.Logger] should no longer be configured after [New] returns. If
+// downstream is nil, a new logger is initialised in its place.
func New(downstream *log.Logger) Msg {
if downstream == nil {
downstream = log.New(log.Writer(), "container: ", 0)
@@ -94,7 +110,8 @@ func (msg *defaultMsg) Verbosef(format string, v ...any) {
func (msg *defaultMsg) Resume() bool {
resumed, dropped, _, err := msg.Suspendable.Resume()
if err != nil {
- // probably going to result in an error as well, so this message is as good as unreachable
+ // probably going to result in an error as well, so this message is as
+ // good as unreachable
msg.logger.Printf("cannot dump buffer on resume: %v", err)
}
if resumed && dropped > 0 {
@@ -103,7 +120,8 @@ func (msg *defaultMsg) Resume() bool {
return resumed
}
-// BeforeExit prints a message if called between calls to [Suspendable.Suspend] and Resume.
+// BeforeExit prints a message if called between calls to [Suspendable.Suspend]
+// and Resume.
func (msg *defaultMsg) BeforeExit() {
if msg.Resume() {
msg.logger.Printf("beforeExit reached on suspended output")
diff --git a/test/internal/sandbox/assert.go b/test/internal/sandbox/assert.go
index 343c1586..e6fe926b 100644
--- a/test/internal/sandbox/assert.go
+++ b/test/internal/sandbox/assert.go
@@ -1,11 +1,11 @@
//go:build testtool
-/*
-Package sandbox provides utilities for checking sandbox outcome.
-
-This package must never be used outside integration tests, there is a much better native implementation of mountinfo
-in the public sandbox/vfs package. Files in this package are excluded by the build system to prevent accidental misuse.
-*/
+// Package sandbox provides utilities for checking sandbox outcome.
+//
+// This package must never be used outside integration tests, there is a much
+// better native implementation of mountinfo in the public sandbox/vfs package.
+// Files in this package are excluded by the build system to prevent accidental
+// misuse.
package sandbox
import (
@@ -204,8 +204,8 @@ func MustCheckFilter(pid int, want string) {
return
}
- var perr *ptraceError
- if !errors.As(err, &perr) {
+ perr, ok := errors.AsType[*ptraceError](err)
+ if !ok {
fatalf("%s", err)
}
switch perr.op {
diff --git a/vfs/mountinfo.go b/vfs/mountinfo.go
index 77f6a35d..3c9e65ca 100644
--- a/vfs/mountinfo.go
+++ b/vfs/mountinfo.go
@@ -103,7 +103,7 @@ type (
// Flags interprets VfsOptstr and returns the resulting flags and unmatched options.
func (e *MountInfoEntry) Flags() (flags uintptr, unmatched []string) {
- for _, s := range strings.Split(e.VfsOptstr, ",") {
+ for s := range strings.SplitSeq(e.VfsOptstr, ",") {
switch s {
case "rw":
case "ro":