"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, wantType bool) {
+func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
switch x.mode {
case typexpr:
// don't crash for "type T T.x" (was go.dev/issue/51509)
- if def != nil && x.typ == def {
- check.cycleError([]Object{def.obj})
+ if def != nil && def.typ == x.typ {
+ check.cycleError([]Object{def})
goto Error
}
case builtin:
// objDecl type-checks the declaration of obj in its respective (file) environment.
// For the meaning of def, see Checker.definedType, in typexpr.go.
-func (check *Checker) objDecl(obj Object, def *Named) {
+func (check *Checker) objDecl(obj Object, def *TypeName) {
if check.conf.Trace && obj.Type() == nil {
if check.indent == 0 {
fmt.Println() // empty line between top-level objects for readability
return u != nil && !u.IsMethodSet()
}
-func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) {
+func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeName) {
assert(obj.typ == nil)
var rhs Type
// type definition or generic type declaration
named := check.newNamed(obj, nil, nil)
- def.setUnderlying(named)
+ setDefType(def, named)
if tdecl.TParamList != nil {
check.openScope(tdecl, "type parameters")
}
// determine underlying type of named
- rhs = check.definedType(tdecl.Type, named)
+ rhs = check.definedType(tdecl.Type, obj)
assert(rhs != nil)
named.fromRHS = rhs
t.embedPos = nil
}
-func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) {
+func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *TypeName) {
addEmbedded := func(pos syntax.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
if ityp.embedPos == nil {
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
- recvTyp = def
+ if named, _ := def.typ.(*Named); named != nil {
+ recvTyp = named
+ }
}
sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp)
return u
}
-func (n *Named) setUnderlying(typ Type) {
- if n != nil {
- n.underlying = typ
- }
-}
-
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
n.resolve()
// If n is an instance, we may not have yet instantiated all of its methods.
// If an error occurred, x.mode is set to invalid.
// For the meaning of def, see Checker.definedType, below.
// If wantType is set, the identifier e is expected to denote a type.
-func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType bool) {
+func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType bool) {
x.mode = invalid
x.expr = e
}
// definedType is like typ but also accepts a type name def.
-// If def != nil, e is the type specification for the defined type def, declared
-// in a type declaration, and def.underlying will be set to the type of e before
-// any components of e are type-checked.
-func (check *Checker) definedType(e syntax.Expr, def *Named) Type {
+// If def != nil, e is the type specification for the type named def, declared
+// in a type declaration, and def.typ.underlying will be set to the type of e
+// before any components of e are type-checked.
+func (check *Checker) definedType(e syntax.Expr, def *TypeName) Type {
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
// typInternal drives type checking of types.
// Must only be called by definedType or genericType.
-func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
+func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) {
if check.conf.Trace {
check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
switch x.mode {
case typexpr:
typ := x.typ
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
switch x.mode {
case typexpr:
typ := x.typ
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
case *syntax.ArrayType:
typ := new(Array)
- def.setUnderlying(typ)
+ setDefType(def, typ)
if e.Len != nil {
typ.len = check.arrayLength(e.Len)
} else {
case *syntax.SliceType:
typ := new(Slice)
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.elem = check.varType(e.Elem)
return typ
case *syntax.StructType:
typ := new(Struct)
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.structType(typ, e)
return typ
if e.Op == syntax.Mul && e.Y == nil {
typ := new(Pointer)
typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.base = check.varType(e.X)
// If typ.base is invalid, it's unlikely that *base is particularly
// useful - even a valid dereferenciation will lead to an invalid
case *syntax.FuncType:
typ := new(Signature)
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.funcType(typ, nil, nil, e)
return typ
case *syntax.InterfaceType:
typ := check.newInterface()
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.interfaceType(typ, e, def)
return typ
case *syntax.MapType:
typ := new(Map)
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.key = check.varType(e.Key)
typ.elem = check.varType(e.Value)
case *syntax.ChanType:
typ := new(Chan)
- def.setUnderlying(typ)
+ setDefType(def, typ)
dir := SendRecv
switch e.Dir {
}
typ := Typ[Invalid]
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
}
-func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *Named) (res Type) {
+func setDefType(def *TypeName, typ Type) {
+ if def != nil {
+ switch t := def.typ.(type) {
+ // case *_Alias:
+ case *Basic:
+ assert(t == Typ[Invalid])
+ case *Named:
+ t.underlying = typ
+ default:
+ panic(fmt.Sprintf("unexpected type %T", t))
+ }
+ }
+}
+
+func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *TypeName) (res Type) {
if check.conf.Trace {
check.trace(x.Pos(), "-- instantiating type %s with %s", x, xlist)
check.indent++
// evaluate arguments
targs := check.typeList(xlist)
if targs == nil {
- def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
+ setDefType(def, Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
// create the instance
inst := asNamed(check.instance(x.Pos(), orig, targs, nil, check.context()))
- def.setUnderlying(inst)
+ setDefType(def, inst)
// orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, wantType bool) {
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
switch x.mode {
case typexpr:
// don't crash for "type T T.x" (was go.dev/issue/51509)
- if def != nil && x.typ == def {
- check.cycleError([]Object{def.obj})
+ if def != nil && def.typ == x.typ {
+ check.cycleError([]Object{def})
goto Error
}
case builtin:
// objDecl type-checks the declaration of obj in its respective (file) environment.
// For the meaning of def, see Checker.definedType, in typexpr.go.
-func (check *Checker) objDecl(obj Object, def *Named) {
+func (check *Checker) objDecl(obj Object, def *TypeName) {
if check.conf._Trace && obj.Type() == nil {
if check.indent == 0 {
fmt.Println() // empty line between top-level objects for readability
return u != nil && !u.IsMethodSet()
}
-func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
+func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *TypeName) {
assert(obj.typ == nil)
var rhs Type
// type definition or generic type declaration
named := check.newNamed(obj, nil, nil)
- def.setUnderlying(named)
+ setDefType(def, named)
if tdecl.TypeParams != nil {
check.openScope(tdecl, "type parameters")
}
// determine underlying type of named
- rhs = check.definedType(tdecl.Type, named)
+ rhs = check.definedType(tdecl.Type, obj)
assert(rhs != nil)
named.fromRHS = rhs
t.embedPos = nil
}
-func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
+func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *TypeName) {
addEmbedded := func(pos token.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
if ityp.embedPos == nil {
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
- recvTyp = def
+ if named, _ := def.typ.(*Named); named != nil {
+ recvTyp = named
+ }
}
sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)
return u
}
-func (n *Named) setUnderlying(typ Type) {
- if n != nil {
- n.underlying = typ
- }
-}
-
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
n.resolve()
// If n is an instance, we may not have yet instantiated all of its methods.
// If an error occurred, x.mode is set to invalid.
// For the meaning of def, see Checker.definedType, below.
// If wantType is set, the identifier e is expected to denote a type.
-func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) {
+func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bool) {
x.mode = invalid
x.expr = e
}
// definedType is like typ but also accepts a type name def.
-// If def != nil, e is the type specification for the defined type def, declared
-// in a type declaration, and def.underlying will be set to the type of e before
-// any components of e are type-checked.
-func (check *Checker) definedType(e ast.Expr, def *Named) Type {
+// If def != nil, e is the type specification for the type named def, declared
+// in a type declaration, and def.typ.underlying will be set to the type of e
+// before any components of e are type-checked.
+func (check *Checker) definedType(e ast.Expr, def *TypeName) Type {
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
// typInternal drives type checking of types.
// Must only be called by definedType or genericType.
-func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
+func (check *Checker) typInternal(e0 ast.Expr, def *TypeName) (T Type) {
if check.conf._Trace {
check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
switch x.mode {
case typexpr:
typ := x.typ
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
switch x.mode {
case typexpr:
typ := x.typ
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
case *ast.ArrayType:
if e.Len == nil {
typ := new(Slice)
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.elem = check.varType(e.Elt)
return typ
}
typ := new(Array)
- def.setUnderlying(typ)
+ setDefType(def, typ)
// Provide a more specific error when encountering a [...] array
// rather than leaving it to the handling of the ... expression.
if _, ok := e.Len.(*ast.Ellipsis); ok {
case *ast.StructType:
typ := new(Struct)
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.structType(typ, e)
return typ
case *ast.StarExpr:
typ := new(Pointer)
typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.base = check.varType(e.X)
return typ
case *ast.FuncType:
typ := new(Signature)
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.funcType(typ, nil, e)
return typ
case *ast.InterfaceType:
typ := check.newInterface()
- def.setUnderlying(typ)
+ setDefType(def, typ)
check.interfaceType(typ, e, def)
return typ
case *ast.MapType:
typ := new(Map)
- def.setUnderlying(typ)
+ setDefType(def, typ)
typ.key = check.varType(e.Key)
typ.elem = check.varType(e.Value)
case *ast.ChanType:
typ := new(Chan)
- def.setUnderlying(typ)
+ setDefType(def, typ)
dir := SendRecv
switch e.Dir {
}
typ := Typ[Invalid]
- def.setUnderlying(typ)
+ setDefType(def, typ)
return typ
}
-func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (res Type) {
+func setDefType(def *TypeName, typ Type) {
+ if def != nil {
+ switch t := def.typ.(type) {
+ // case *_Alias:
+ case *Basic:
+ assert(t == Typ[Invalid])
+ case *Named:
+ t.underlying = typ
+ default:
+ panic(fmt.Sprintf("unexpected type %T", t))
+ }
+ }
+}
+
+func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *TypeName) (res Type) {
if check.conf._Trace {
check.trace(ix.Pos(), "-- instantiating type %s with %s", ix.X, ix.Indices)
check.indent++
// evaluate arguments
targs := check.typeList(ix.Indices)
if targs == nil {
- def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
+ setDefType(def, Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
// create the instance
inst := asNamed(check.instance(ix.Pos(), orig, targs, nil, check.context()))
- def.setUnderlying(inst)
+ setDefType(def, inst)
// orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {