Skip to content

Commit

Permalink
Handle newly-introduced types.Alias type (#286)
Browse files Browse the repository at this point in the history
Go 1.22 [1] introduces a proper `types.Alias` type for type aliases.
This PR adds handling (by simply unwrapping alias node - effectively
restoring previous behavior) for such a type.

Further simplification and refactors will be in future PRs.
  • Loading branch information
yuxincs authored Oct 10, 2024
1 parent 045b340 commit f74befd
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 7 deletions.
4 changes: 2 additions & 2 deletions annotation/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func collectMethods(t *types.Named, visitedMethods map[string]*types.Func, visit
for i := 0; i < s.NumFields(); i++ {
f := s.Field(i)
if f.Embedded() {
if n, ok := util.UnwrapPtr(f.Type()).(*types.Named); ok {
if n, ok := util.UnwrapPtr(types.Unalias(f.Type())).(*types.Named); ok {
collectMethods(n, visitedMethods, visitedStructs)
}
}
Expand Down Expand Up @@ -197,7 +197,7 @@ func structsImplementingInterface(interfaceName string, packageName ...string) m
if sObj == nil {
return true
}
sType, ok := sObj.Type().(*types.Named)
sType, ok := types.Unalias(sObj.Type()).(*types.Named)
if !ok {
return true
}
Expand Down
2 changes: 1 addition & 1 deletion assertion/function/assertiontree/backprop.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ func backpropAcrossRange(rootNode *RootAssertionNode, lhs []ast.Expr, rhs ast.Ex
}
}

rhsType := rootNode.Pass().TypesInfo.Types[rhs].Type
rhsType := types.Unalias(rootNode.Pass().TypesInfo.Types[rhs].Type)

// This block breaks down the cases for the `range` statement being analyzed,
// starting by switching on how many left-hand operands there are
Expand Down
7 changes: 7 additions & 0 deletions nilaway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// Go 1.22 [1] introduces a proper `types.Alias` type for type aliases. The current default is
// disabling such a feature. However, Go official doc suggests that it will be enabled in future Go
// releases. Therefore, here we explicitly set this to `1` to enable the feature to test NilAway's
// ability to handle it.
// [1]: https://tip.golang.org/doc/go1.22
//go:debug gotypesalias=1

package nilaway

import (
Expand Down
11 changes: 11 additions & 0 deletions testdata/src/go.uber.org/looprange/looprange.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,14 @@ func testRangeOverBasicTypes(j int) {
}
}
}

type Set map[string]bool

type MyAlias = Set

//nilable(s)
func testAlias(s MyAlias) {
for myStr := range s {
print(myStr)
}
}
8 changes: 4 additions & 4 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func TypeAsDeeplyStruct(typ types.Type) *types.Struct {
}

if ptType, ok := typ.(*types.Pointer); ok {
if namedType, ok := ptType.Elem().(*types.Named); ok {
if namedType, ok := types.Unalias(ptType.Elem()).(*types.Named); ok {
if resType, ok := namedType.Underlying().(*types.Struct); ok {
return resType
}
Expand Down Expand Up @@ -262,7 +262,7 @@ func TypeBarsNilness(t types.Type) bool {
return false
case *types.Chan:
return false
case *types.Named:
case *types.Alias, *types.Named:
return TypeBarsNilness(t.Underlying())
case *types.Interface:
return false
Expand Down Expand Up @@ -314,11 +314,11 @@ func funcIsRichCheckEffectReturning(fdecl *types.Func, expectedType types.Type)
if n == 0 {
return false
}
if results.At(n-1).Type() != expectedType {
if !types.Identical(results.At(n-1).Type(), expectedType) {
return false
}
for i := 0; i < n-1; i++ {
if results.At(i).Type() == expectedType {
if types.Identical(results.At(i).Type(), expectedType) {
return false
}
}
Expand Down

0 comments on commit f74befd

Please sign in to comment.