// 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
case *Const:
check.addDeclDep(obj)
- if typ == Typ[Invalid] {
+ if !isValid(typ) {
return
}
if obj == universeIota {
x.mode = constant_
case *TypeName:
- if check.isBrokenAlias(obj) {
+ if !check.enableAlias && check.isBrokenAlias(obj) {
check.errorf(e, InvalidDeclCycle, "invalid use of type alias %s in recursive type (see go.dev/issue/50729)", obj.name)
return
}
obj.used = true
}
check.addDeclDep(obj)
- if typ == Typ[Invalid] {
+ if !isValid(typ) {
return
}
x.mode = variable
}
// 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) {
func (check *Checker) genericType(e ast.Expr, cause *string) Type {
typ := check.typInternal(e, nil)
assert(isTyped(typ))
- if typ != Typ[Invalid] && !isGeneric(typ) {
+ if isValid(typ) && !isGeneric(typ) {
if cause != nil {
*cause = check.sprintf("%s is not a generic type", 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:
+ // t.fromRHS should always be set, either to an invalid type
+ // in the beginning, or to typ in certain cyclic declarations.
+ if t.fromRHS != Typ[Invalid] && t.fromRHS != typ {
+ panic(sprintf(nil, nil, true, "t.fromRHS = %s, typ = %s\n", t.fromRHS, typ))
+ }
+ t.fromRHS = typ
+ 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++
if cause != "" {
check.errorf(ix.Orig, NotAGenericType, invalidOp+"%s (%s)", ix.Orig, cause)
}
- if gtyp == Typ[Invalid] {
+ if !isValid(gtyp) {
return gtyp // error already reported
}
- orig, _ := gtyp.(*Named)
+ orig := asNamed(gtyp)
if orig == nil {
panic(fmt.Sprintf("%v: cannot instantiate %v", ix.Pos(), gtyp))
}
// 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 := check.instance(ix.Pos(), orig, targs, nil, check.context()).(*Named)
- def.setUnderlying(inst)
+ inst := asNamed(check.instance(ix.Pos(), orig, targs, nil, check.context()))
+ setDefType(def, inst)
// orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {
res := make([]Type, len(list)) // res != nil even if len(list) == 0
for i, x := range list {
t := check.varType(x)
- if t == Typ[Invalid] {
+ if !isValid(t) {
res = nil
}
if res != nil {