cmd/compile: disallow embed of var inside func

Allowing embedding into []byte inside a func creates an
unfortunate problem: either all calls start with the same
underlying data and can see each other's changes to the
underlying data (surprising and racy!) or all calls start
by making their own copy of the underlying data
(surprising and expensive!).

After discussion on #43216, the consensus was to remove
support for all vars embedded inside functions.

Fixes #43216.


Change-Id: I01e62b5f0dcd9e8566c6d2286218e97803f54704
Reviewed-on: https://go-review.googlesource.com/c/go/+/282714
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
This commit is contained in:
Russ Cox 2021-01-08 15:35:19 -05:00
parent b386c735e7
commit 54198b04db
3 changed files with 13 additions and 42 deletions

View file

@ -133,13 +133,8 @@ func varEmbed(p *noder, names []*Node, typ *Node, exprs []*Node, embeds []Pragma
v := names[0] v := names[0]
if dclcontext != PEXTERN { if dclcontext != PEXTERN {
numLocalEmbed++ p.yyerrorpos(pos, "go:embed cannot apply to var inside func")
v = newnamel(v.Pos, lookupN("embed.", numLocalEmbed)) return exprs
v.Sym.Def = asTypesNode(v)
v.Name.Param.Ntype = typ
v.SetClass(PEXTERN)
externdcl = append(externdcl, v)
exprs = []*Node{v}
} }
v.Name.Param.SetEmbedFiles(list) v.Name.Param.SetEmbedFiles(list)

View file

@ -73,24 +73,11 @@ func TestGlobal(t *testing.T) {
testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n") testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
} }
func TestLocal(t *testing.T) { //go:embed testdata
//go:embed testdata/k*.txt var testDirAll embed.FS
var local embed.FS
testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}
func TestDir(t *testing.T) { func TestDir(t *testing.T) {
//go:embed testdata all := testDirAll
var all embed.FS
testFiles(t, all, "testdata/hello.txt", "hello, world\n") testFiles(t, all, "testdata/hello.txt", "hello, world\n")
testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n") testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n")
testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n") testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n")
@ -102,12 +89,15 @@ func TestDir(t *testing.T) {
testDir(t, all, "testdata/i/j/k", "k8s.txt") testDir(t, all, "testdata/i/j/k", "k8s.txt")
} }
func TestHidden(t *testing.T) {
//go:embed testdata //go:embed testdata
var dir embed.FS var testHiddenDir embed.FS
//go:embed testdata/* //go:embed testdata/*
var star embed.FS var testHiddenStar embed.FS
func TestHidden(t *testing.T) {
dir := testHiddenDir
star := testHiddenStar
t.Logf("//go:embed testdata") t.Logf("//go:embed testdata")

View file

@ -90,17 +90,3 @@ func TestXGlobal(t *testing.T) {
} }
bbig[0] = old bbig[0] = old
} }
func TestXLocal(t *testing.T) {
//go:embed testdata/*o.txt
var local embed.FS
testFiles(t, local, "testdata/hello.txt", "hello, world\n")
//go:embed testdata/k*.txt
var s string
testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
//go:embed testdata/h*.txt
var b []byte
testString(t, string(b), "local variable b", "hello, world\n")
}