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

proposal: go/types: assign non-untyped types for all runtime expressions #62466

mdempsky opened this issue Sep 5, 2023 · 5 comments


Copy link

mdempsky commented Sep 5, 2023

Compilers like cmd/compile and x/tools/go/ssa prefer to work exclusively with true types, but there are several cases where go/types leaves expressions as untyped:

func idealType(tv syntax.TypeAndValue) types2.Type {

It would be convenient if go/types were to provide appropriate true types for each of these contexts, since it's already having to check that the untyped expressions are suitable.

Related: #47151 proposes adding a second map for the implicitly converted type of expressions. I'd suggest that's a reasonable way to avoid breaking users that expect the current untyped types (e.g., #47243).

/cc @griesemer @findleyr @alandonovan

@gopherbot gopherbot added this to the Proposal milestone Sep 5, 2023
Copy link

Many constant expressions only have "untyped" types. For example, const k = 0. For those, go/types records an untyped type.

In other cases, a constant expression is used in a context that implies a "true" (runtime) type. For example strings.Repeat("", 1) implicitly converts "" to string and 1 to int. In those cases, go/types already applies the contextually implied conversion to the constant, so the types of the literals are records as string and int, respectively. (You can verify this in the types playground.)

(Aside: I vaguely recall requesting this behavior a long time ago, but have since come to regret doing so as it makes it harder when analyzing typed syntax to notice implicit conversions. At least prior to generics, there were very few places where type information flowed top-down: only shifts, IIRC.)

So I'm not sure exactly what change this issue is asking for.

Copy link
Member Author

I think a better way to state my request would be that go/types should only assign "untyped" types to constant expressions. Any non-constant expression should have an assigned non-untyped type.

The linked to code mentions several cases where go/types assigns "untyped" types to non-constant expressions:

case types2.UntypedInt, types2.UntypedFloat, types2.UntypedComplex:
// Untyped rhs of non-constant shift, e.g. x << 1.0.
// If we have a constant value, it must be an int >= 0.
if tv.Value != nil {
s := constant.ToInt(tv.Value)
assert(s.Kind() == constant.Int && constant.Sign(s) >= 0)
typ = types2.Typ[types2.Uint]
case types2.UntypedBool:
typ = types2.Typ[types2.Bool] // expression in "if" or "for" condition
case types2.UntypedString:
typ = types2.Typ[types2.String] // argument to "append" or "copy" calls

Copy link

Funny, Rob sent me a CL today that introduced me to your unconvert tool, a comment in whose source led me to
#13061, in which you argue for keeping constants as untyped.

Copy link
Member Author

Oh, just hedging my proposals I suppose.

Copy link

griesemer commented Nov 29, 2023

I think this is fine and I was planning to do this, a few years in the past, if I recall correctly. But we ended up not doing it because (I'm not sure anymore) some backward-compatibility or other issues.

We should perhaps try again, and if need be introduce a flag to control the behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Status: Incoming

No branches or pull requests

4 participants