Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: allow typechecking loops with & #17533

Closed
randall77 opened this issue Oct 20, 2016 · 11 comments
Closed

cmd/compile: allow typechecking loops with & #17533

randall77 opened this issue Oct 20, 2016 · 11 comments

Comments

@randall77
Copy link
Contributor

type T struct {
    p *T
}
var x = T{p: &x}

This code does not compile:

tmp1.go:7: typechecking loop involving x = T literal

I don't see any obvious reason why this wouldn't be typecheckable.

This comes up when trying to compile descriptors for recursive .proto messages.

message Recursive {
    optional Recursive x = 1;
}

The current proto compiler accepts such a message. I'm doing some experiments to optimize the proto-generated code. Part of that is having a descriptor for a Recursive message being able to point to itself (to describe its x field).

@griesemer @mdempsky @dsnet

@griesemer
Copy link
Contributor

The current initialization rules disallow this: It's not about how x is used, it's the fact that it is used in the initialization of itself.

(go/types also disallows this.)

@randall77
Copy link
Contributor Author

p.s. if I do:

var x T = T{p: &x}

Then it typechecks, but then dies with:

tmp1.go:7: initialization loop:

@randall77
Copy link
Contributor Author

So why can't I use the address of x to initialize x? It seems the & should break the loop somehow.

@griesemer
Copy link
Contributor

Same thing: it's an initialization loop per the spec rules.

@griesemer
Copy link
Contributor

griesemer commented Oct 20, 2016

We could change the rules I guess, but it general, taking the address of a variable being initialized and using that address during initialization doesn't guarantee that we don't indirect that address and then use the variable during initialization.

@griesemer
Copy link
Contributor

Per the spec: "Dependency analysis does not rely on the actual values of the variables, only on lexical references to them in the source, analyzed transitively." (https://golang.org/ref/spec#Package_initialization)

@mdempsky
Copy link
Member

Agreed that it seems to be an initialization loop, so it's not allowed by the spec currently.

FWIW, it does seem like a bug though that we fail to typecheck "var x = T{&x}" the same as "var x T = T{&x}", but since it's an initialization loop anyway, I'm not sure it's worth fixing that corner case.

@griesemer
Copy link
Contributor

PS: I guess we could change the spec as it would be a backward-compatible change. But it wouldn't catch e.g. the following error anymore:

var x T = f(&x) // & breaks the cycle
func f(p *T) T { return *p }

@randall77
Copy link
Contributor Author

Yes, I guess that makes sense. I'll have to figure out some other way to get those pointers initialized. Maybe some init functions to patch up those links later.

@griesemer
Copy link
Contributor

https://play.golang.org/p/fvNEJWTH8c
:-)

@randall77
Copy link
Contributor Author

I've always wanted to make my code depend on linker layout order...

@golang golang locked and limited conversation to collaborators Oct 20, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants