Commit d178c588 authored by Damien Neil's avatar Damien Neil

os: don't consult Is methods on non-syscall error types

CL #163058 moves interpretation of platform-specific errors to the
syscall package. Package syscall errors implement an Is method which
os.IsPermission etc. consult. This results in an unintended semantic
change to the os package predicate functions: The following program
now prints 'true' where it used to print 'false':

	package main
	import "os"
	type myError struct{ error }
	func (e myError) Is(target error) bool { return target == os.ErrPermission }
	func main() { println(os.IsPermission(myError{})) }

Change the os package error predicate functions to only examine syscall
errors, avoiding this semantic change.

This CL does retain one minor semantic change: On Plan9, os.IsPermission
used to return true for any error with text containing the string
"permission denied". It now only returns true for a syscall.ErrorString
containing that text.

Change-Id: I6b512b1de6ced46c2f1cc8d264fa2495ae7bf9f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/188817
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 55e23cb1
......@@ -115,7 +115,8 @@ func underlyingErrorIs(err, target error) bool {
if err == target {
return true
}
e, ok := err.(interface{ Is(error) bool })
// To preserve prior behavior, only examine syscall errors.
e, ok := err.(syscallErrorType)
return ok && e.Is(target)
}
......
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !plan9
package os
import "syscall"
type syscallErrorType = syscall.Errno
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package os
import "syscall"
type syscallErrorType = syscall.ErrorString
......@@ -175,3 +175,13 @@ func TestPathErrorUnwrap(t *testing.T) {
t.Error("errors.Is failed, wanted success")
}
}
type myErrorIs struct{ error }
func (e myErrorIs) Is(target error) bool { return target == e.error }
func TestErrorIsMethods(t *testing.T) {
if os.IsPermission(myErrorIs{os.ErrPermission}) {
t.Error("os.IsPermission(err) = true when err.Is(os.ErrPermission), wanted false")
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment