mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-28 23:58:40 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6645f412ae |
@@ -8,6 +8,7 @@ import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -365,6 +366,22 @@ func (c *compilerContext) localTypeArgsSuffix(f *ssa.Function) string {
|
||||
if isLocal {
|
||||
hasLocal = true
|
||||
}
|
||||
// A function-local type alias (e.g. `type F = float64` inside a
|
||||
// function body) is invisible to getTypeCodeName because it calls
|
||||
// types.Unalias first. Two callers that use distinct aliases with
|
||||
// the same name (e.g. Go 1.27's internal/strconv.ftoa32 and ftoa64
|
||||
// both declare a local `type F = ...`) then produce identical
|
||||
// RelStrings for their shortFloat[F] instantiations and collide on
|
||||
// mod.NamedFunction. Treat these aliases as local so the suffix
|
||||
// disambiguates them.
|
||||
if alias, ok := ta.(*types.Alias); ok {
|
||||
if obj := alias.Obj(); obj.Pkg() != nil && obj.Parent() != obj.Pkg().Scope() {
|
||||
hasLocal = true
|
||||
pos := c.program.Fset.PositionFor(obj.Pos(), false)
|
||||
parts[i] = fmt.Sprintf("%s$alias:%s:%d:%d", name, filepath.Base(pos.Filename), pos.Line, pos.Column)
|
||||
continue
|
||||
}
|
||||
}
|
||||
parts[i] = name
|
||||
}
|
||||
if !hasLocal {
|
||||
|
||||
Vendored
+31
-1
@@ -1,6 +1,9 @@
|
||||
package main
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type checker = func(any) bool
|
||||
|
||||
@@ -216,6 +219,28 @@ func issue5180CopyIgnoreNilMembers() (ok bool) {
|
||||
return ok
|
||||
}
|
||||
|
||||
// aliasSize is the pattern used by Go 1.27's internal/strconv.ftoa32 and
|
||||
// ftoa64 (and by shortFloat in internal/strconv/uscale.go): a generic
|
||||
// function parameterized on F={float32|float64} that switches on
|
||||
// unsafe.Sizeof(F(0)). Callers pass F via a function-local `type F = ...`
|
||||
// alias. If the two instantiations share an SSA function name (because
|
||||
// x/tools' go/ssa targstr uses the alias's declared name), TinyGo's
|
||||
// getFunction reuses the first LLVM function for the second call and the
|
||||
// second instantiation returns the first's result.
|
||||
func aliasSize[F float32 | float64]() int {
|
||||
return 8 * int(unsafe.Sizeof(F(0)))
|
||||
}
|
||||
|
||||
func aliasSizeCaller32() int {
|
||||
type F = float32
|
||||
return aliasSize[F]()
|
||||
}
|
||||
|
||||
func aliasSizeCaller64() int {
|
||||
type F = float64
|
||||
return aliasSize[F]()
|
||||
}
|
||||
|
||||
func main() {
|
||||
expect("issue5180 TestCopy1", issue5180Copy1())
|
||||
expect("issue5180 TestCopyIgnoreNilMembers", issue5180CopyIgnoreNilMembers())
|
||||
@@ -300,4 +325,9 @@ func main() {
|
||||
println("issue4931PairB labels:", issue4931PairB())
|
||||
println("issue4931MethodA labels:", issue4931MethodA())
|
||||
println("issue4931MethodB labels:", issue4931MethodB())
|
||||
|
||||
// Generic instances distinguished only by function-local type aliases
|
||||
// must not share bodies either (the Go 1.27 strconv shortFloat pattern).
|
||||
expect("aliasSize[float32]==32", aliasSizeCaller32() == 32)
|
||||
expect("aliasSize[float64]==64", aliasSizeCaller64() == 64)
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -47,3 +47,5 @@ issue4931PairA labels: 0
|
||||
issue4931PairB labels: 0
|
||||
issue4931MethodA labels: 0
|
||||
issue4931MethodB labels: 0
|
||||
ok: aliasSize[float32]==32
|
||||
ok: aliasSize[float64]==64
|
||||
|
||||
Reference in New Issue
Block a user