mirror of
https://github.com/golang/go
synced 2024-11-23 00:10:07 -07:00
go/types, types2: reorder object processing to avoid broken aliases
By processing non-alias type declarations before alias type declaration, and those before everything else we can avoid some of the remaining errors which are due to alias types not being available. For #25838. For #50259. For #50276. For #50729. Change-Id: I233da2899a6d4954c239638624dfa8c08662e6b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/380056 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
fe85c24431
commit
671e1150c6
@ -656,25 +656,31 @@ func (check *Checker) packageObjects() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We process non-alias declarations first, in order to avoid situations where
|
// We process non-alias type declarations first, followed by alias declarations,
|
||||||
// the type of an alias declaration is needed before it is available. In general
|
// and then everything else. This appears to avoid most situations where the type
|
||||||
// this is still not enough, as it is possible to create sufficiently convoluted
|
// of an alias is needed before it is available.
|
||||||
// recursive type definitions that will cause a type alias to be needed before it
|
// There may still be cases where this is not good enough (see also issue #25838).
|
||||||
// is available (see issue #25838 for examples).
|
// In those cases Checker.ident will report an error ("invalid use of type alias").
|
||||||
// As an aside, the cmd/compiler suffers from the same problem (#25838).
|
|
||||||
var aliasList []*TypeName
|
var aliasList []*TypeName
|
||||||
// phase 1
|
var othersList []Object // everything that's not a type
|
||||||
|
// phase 1: non-alias type declarations
|
||||||
for _, obj := range objList {
|
for _, obj := range objList {
|
||||||
// If we have a type alias, collect it for the 2nd phase.
|
if tname, _ := obj.(*TypeName); tname != nil {
|
||||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Alias {
|
if check.objMap[tname].tdecl.Alias {
|
||||||
aliasList = append(aliasList, tname)
|
aliasList = append(aliasList, tname)
|
||||||
continue
|
} else {
|
||||||
|
check.objDecl(obj, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
othersList = append(othersList, obj)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// phase 2: alias type declarations
|
||||||
|
for _, obj := range aliasList {
|
||||||
check.objDecl(obj, nil)
|
check.objDecl(obj, nil)
|
||||||
}
|
}
|
||||||
// phase 2
|
// phase 3: all other declarations
|
||||||
for _, obj := range aliasList {
|
for _, obj := range othersList {
|
||||||
check.objDecl(obj, nil)
|
check.objDecl(obj, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/cmd/compile/internal/types2/testdata/fixedbugs/issue25838.go
vendored
Normal file
26
src/cmd/compile/internal/types2/testdata/fixedbugs/issue25838.go
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2022 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 p
|
||||||
|
|
||||||
|
// examples from the issue
|
||||||
|
|
||||||
|
type (
|
||||||
|
e = f
|
||||||
|
f = g
|
||||||
|
g = []h
|
||||||
|
h i
|
||||||
|
i = j
|
||||||
|
j = e
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
e1 = []h1
|
||||||
|
h1 e1
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
P = *T
|
||||||
|
T P
|
||||||
|
)
|
@ -7,7 +7,7 @@ package p
|
|||||||
var x T[B]
|
var x T[B]
|
||||||
|
|
||||||
type T[_ any] struct{}
|
type T[_ any] struct{}
|
||||||
type A T[B /* ERROR invalid use of type alias */ ]
|
type A T[B]
|
||||||
type B = T[A]
|
type B = T[A]
|
||||||
|
|
||||||
// test case from issue
|
// test case from issue
|
||||||
@ -15,4 +15,4 @@ type B = T[A]
|
|||||||
var v Box[Step]
|
var v Box[Step]
|
||||||
type Box[T any] struct{}
|
type Box[T any] struct{}
|
||||||
type Step = Box[StepBox]
|
type Step = Box[StepBox]
|
||||||
type StepBox Box[Step /* ERROR invalid use of type alias */ ]
|
type StepBox Box[Step]
|
||||||
|
@ -11,7 +11,7 @@ type pair[S any] struct {}
|
|||||||
|
|
||||||
var _ transform[step]
|
var _ transform[step]
|
||||||
|
|
||||||
type box transform[step /* ERROR invalid use of type alias */ ]
|
type box transform[step]
|
||||||
type step = pair[box]
|
type step = pair[box]
|
||||||
|
|
||||||
// test case from issue
|
// test case from issue
|
||||||
@ -27,7 +27,7 @@ var first Transform[Step]
|
|||||||
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
|
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
|
||||||
var second Transform[Pair[Box, interface{}]]
|
var second Transform[Pair[Box, interface{}]]
|
||||||
|
|
||||||
type Box *Transform[Step /* ERROR invalid use of type alias */ ]
|
type Box *Transform[Step]
|
||||||
|
|
||||||
// This line is the same as the `first` line, but it comes after the Box declaration and
|
// This line is the same as the `first` line, but it comes after the Box declaration and
|
||||||
// does not break the compile.
|
// does not break the compile.
|
||||||
|
@ -629,25 +629,31 @@ func (check *Checker) packageObjects() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We process non-alias declarations first, in order to avoid situations where
|
// We process non-alias type declarations first, followed by alias declarations,
|
||||||
// the type of an alias declaration is needed before it is available. In general
|
// and then everything else. This appears to avoid most situations where the type
|
||||||
// this is still not enough, as it is possible to create sufficiently convoluted
|
// of an alias is needed before it is available.
|
||||||
// recursive type definitions that will cause a type alias to be needed before it
|
// There may still be cases where this is not good enough (see also issue #25838).
|
||||||
// is available (see issue #25838 for examples).
|
// In those cases Checker.ident will report an error ("invalid use of type alias").
|
||||||
// As an aside, the cmd/compiler suffers from the same problem (#25838).
|
|
||||||
var aliasList []*TypeName
|
var aliasList []*TypeName
|
||||||
// phase 1
|
var othersList []Object // everything that's not a type
|
||||||
|
// phase 1: non-alias type declarations
|
||||||
for _, obj := range objList {
|
for _, obj := range objList {
|
||||||
// If we have a type alias, collect it for the 2nd phase.
|
if tname, _ := obj.(*TypeName); tname != nil {
|
||||||
if tname, _ := obj.(*TypeName); tname != nil && check.objMap[tname].tdecl.Assign.IsValid() {
|
if check.objMap[tname].tdecl.Assign.IsValid() {
|
||||||
aliasList = append(aliasList, tname)
|
aliasList = append(aliasList, tname)
|
||||||
continue
|
} else {
|
||||||
|
check.objDecl(obj, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
othersList = append(othersList, obj)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// phase 2: alias type declarations
|
||||||
|
for _, obj := range aliasList {
|
||||||
check.objDecl(obj, nil)
|
check.objDecl(obj, nil)
|
||||||
}
|
}
|
||||||
// phase 2
|
// phase 3: all other declarations
|
||||||
for _, obj := range aliasList {
|
for _, obj := range othersList {
|
||||||
check.objDecl(obj, nil)
|
check.objDecl(obj, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/go/types/testdata/fixedbugs/issue25838.go
vendored
Normal file
26
src/go/types/testdata/fixedbugs/issue25838.go
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2022 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 p
|
||||||
|
|
||||||
|
// examples from the issue
|
||||||
|
|
||||||
|
type (
|
||||||
|
e = f
|
||||||
|
f = g
|
||||||
|
g = []h
|
||||||
|
h i
|
||||||
|
i = j
|
||||||
|
j = e
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
e1 = []h1
|
||||||
|
h1 e1
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
P = *T
|
||||||
|
T P
|
||||||
|
)
|
@ -7,7 +7,7 @@ package p
|
|||||||
var x T[B]
|
var x T[B]
|
||||||
|
|
||||||
type T[_ any] struct{}
|
type T[_ any] struct{}
|
||||||
type A T[B /* ERROR invalid use of type alias */ ]
|
type A T[B]
|
||||||
type B = T[A]
|
type B = T[A]
|
||||||
|
|
||||||
// test case from issue
|
// test case from issue
|
||||||
@ -15,4 +15,4 @@ type B = T[A]
|
|||||||
var v Box[Step]
|
var v Box[Step]
|
||||||
type Box[T any] struct{}
|
type Box[T any] struct{}
|
||||||
type Step = Box[StepBox]
|
type Step = Box[StepBox]
|
||||||
type StepBox Box[Step /* ERROR invalid use of type alias */ ]
|
type StepBox Box[Step]
|
||||||
|
@ -11,7 +11,7 @@ type pair[S any] struct {}
|
|||||||
|
|
||||||
var _ transform[step]
|
var _ transform[step]
|
||||||
|
|
||||||
type box transform[step /* ERROR invalid use of type alias */ ]
|
type box transform[step]
|
||||||
type step = pair[box]
|
type step = pair[box]
|
||||||
|
|
||||||
// test case from issue
|
// test case from issue
|
||||||
@ -27,7 +27,7 @@ var first Transform[Step]
|
|||||||
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
|
// This line doesn't use the Step alias, and it compiles fine if you uncomment it.
|
||||||
var second Transform[Pair[Box, interface{}]]
|
var second Transform[Pair[Box, interface{}]]
|
||||||
|
|
||||||
type Box *Transform[Step /* ERROR invalid use of type alias */ ]
|
type Box *Transform[Step]
|
||||||
|
|
||||||
// This line is the same as the `first` line, but it comes after the Box declaration and
|
// This line is the same as the `first` line, but it comes after the Box declaration and
|
||||||
// does not break the compile.
|
// does not break the compile.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// errorcheck -G=3
|
// compile -G=3
|
||||||
|
|
||||||
// Copyright 2022 The Go Authors. All rights reserved.
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
@ -9,5 +9,5 @@ package p
|
|||||||
var x T[B]
|
var x T[B]
|
||||||
|
|
||||||
type T[_ any] struct{}
|
type T[_ any] struct{}
|
||||||
type A T[B] // ERROR "invalid use of type alias B in recursive type"
|
type A T[B]
|
||||||
type B = T[A]
|
type B = T[A]
|
||||||
|
Loading…
Reference in New Issue
Block a user