blob: 85952f36b2b6d5acf7408080c4f2fbf825a55a76 [file]
// Copyright 2026 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 ptrtoerror defines an analyzer that detects inconsistent
// conversions of concrete error types to the error interface.
//
// # Analyzer ptrtoerror
//
// ptrtoerror: detect inconsistent conversions of concrete types to error
//
// The ptrtoerror analyzer detects when a concrete type E is converted
// to the error interface inconsistently, both as a value of type E
// and as a pointer of type *E. Such inconsistency defeats attempts by
// client code to test for specific error types using type assertions
// or library functions such as [errors.As] and [errors.Is].
//
// The analyzer also detects when both E and *E implement error but
// neither of those types is converted to error within the defining
// package, leaving the intended error form (E or *E) ambiguous. This
// diagnostic offers two alternative fixes to add declarations that
// make the intent explicit.
//
// # Examples
//
// In this example, both MyError and *MyError implement error, and
// both types are used as errors:
//
// type MyError struct{ Msg string } // error: type MyError is converted to error both as a value and as a pointer
//
// func (MyError) Error() string { return "error" }
//
// func foo() error { return MyError{"foo"} } // "conversion of MyError (value) to error" here
// func bar() error { return &MyError{"bar"} } // "conversion of *MyError (pointer) to error" here
//
// To fix the issue, adopt a single conversion form consistently:
//
// func foo() error { return &MyError{"foo"} } // pointer conversion (*E)
// func bar() error { return &MyError{"bar"} } // pointer conversion (*E)
//
// In this example, again both CustomError and *CustomError implement
// error, but neither type is used as an error:
//
// type CustomError struct{ error } // "both CustomError and *CustomError implement the error interface, making the intent ambiguous"
//
// func (e *CustomError) Unwrap() error ( return e.error }
//
// To resolve the ambiguity, apply one of the two suggested fixes to
// add a declaration that makes the intent explicit:
//
// var _ error = *new(CustomError) // (declares that CustomError is the intended form)
//
// or:
//
// var _ error = (*CustomError)(nil) // (declares that *CustomError is the intended form)
//
// In this example, the presence of the Unwrap method is a clue that
// *CustomError is the preferred form. An alternative fix would be to
// declare an explicit Error method so that CustomError is no longer
// assignable to error:
//
// func (err *CustomError) Error() string ( return err.error.Error() }
package ptrtoerror