Skip to content

types2: Generics allow creating values of unexported or internal types #56669

Closed
@Merovius

Description

@Merovius

I'm not sure if this is a bug or should be a proposal, or if it is just a curiosity. But I noticed a thing and I think it's weird.

Say package a wants to make sure that of some type, only well-controlled values are ever used (in my use case, its an interface which I want to share between packages but be able to change without breaking compatibility). It uses an internal package to do so:

-- a/a.go --
package a

import "a/internal"

func MakeX() internal.X {
	return internal.Make(42)
}

func F(x internal.X) {
	if x.V() != 42 {
		panic(fmt.Errorf("invalid %#v", x))
	}
}
-- a/internal/internal.go --
package internal

type X struct { v int }

func Make(v int) X { return X{v} }

func (x X) V() int { return x.v }

-- b/b.go --
package main

import (
	"a"
	// illegal: use of internal package a/internal not allowed
	// "a/internal"
)

func main() {
	// doesn't work
	// a.F(internal.X{})
	a.F(a.MakeX())
}

As a/internal cannot be imported, there is no way to get an internal.X that isn't sanctioned by a. reflect can be used to construct an any with dynamic type internal.X, but that can't be type-asserted, so it can't be passed to a.F.

However, using generics, we can do this trick:

package main

import "x/a"

func main() {
	a.F(trick(a.MakeX))
}

func trick[T any](f func() T) T {
	return *new(T)
}

The same also applies if the type is not from an internal package, but an unexported type. I suspect a similar issue would apply to #21498 (there is currently no way for a different package to write a func(unexported), but #21498 would allow it by spelling it (x) => { … }).

I'm not sure how important it is to prevent this. But I don't think this is how it should work. I think if an inferred type argument is from an internal package or is a defined type with unexported name from a different package, it should fail. But doing that would technically be a breaking change.

Just thought I'd bring this up, at least.

Metadata

Metadata

Assignees

Labels

NeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.genericsIssue is related to generics

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions