mirror of
https://github.com/golang/go
synced 2025-06-12 17:11:51 +00:00
[dev.typealias] cmd/compile: type-check type alias declarations
Known issues: - needs many more tests - duplicate method declarations via type alias names are not detected - type alias cycle error messages need to be improved - need to review setup of byte/rune type aliases For #18130. Change-Id: Icc2fefad6214e5e56539a9dcb3fe537bf58029f8 Reviewed-on: https://go-review.googlesource.com/35121 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
src/cmd/compile/internal/gc
test
@ -352,8 +352,8 @@ func export(out *bufio.Writer, trace bool) int {
|
|||||||
p.tracef("\n")
|
p.tracef("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if sym.Flags&SymAlias != 0 {
|
if sym.isAlias() {
|
||||||
Fatalf("exporter: unexpected alias %v in inlined function body", sym)
|
Fatalf("exporter: unexpected type alias %v in inlined function body", sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
p.obj(sym)
|
p.obj(sym)
|
||||||
@ -486,8 +486,7 @@ func (p *exporter) obj(sym *Sym) {
|
|||||||
Fatalf("exporter: export of incomplete type %v", sym)
|
Fatalf("exporter: export of incomplete type %v", sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
const alias = false // TODO(gri) fix this
|
if sym.isAlias() {
|
||||||
if alias {
|
|
||||||
p.tag(aliasTag)
|
p.tag(aliasTag)
|
||||||
p.pos(n)
|
p.pos(n)
|
||||||
p.qualifiedName(sym)
|
p.qualifiedName(sym)
|
||||||
|
@ -316,10 +316,10 @@ func (p *importer) obj(tag int) {
|
|||||||
importconst(sym, idealType(typ), nodlit(val))
|
importconst(sym, idealType(typ), nodlit(val))
|
||||||
|
|
||||||
case aliasTag:
|
case aliasTag:
|
||||||
// TODO(gri) hook up type alias
|
|
||||||
p.pos()
|
p.pos()
|
||||||
p.qualifiedName()
|
sym := p.qualifiedName()
|
||||||
p.typ()
|
typ := p.typ()
|
||||||
|
importalias(sym, typ)
|
||||||
|
|
||||||
case typeTag:
|
case typeTag:
|
||||||
p.typ()
|
p.typ()
|
||||||
@ -576,7 +576,7 @@ func (p *importer) fieldList() (fields []*Field) {
|
|||||||
|
|
||||||
func (p *importer) field() *Field {
|
func (p *importer) field() *Field {
|
||||||
p.pos()
|
p.pos()
|
||||||
sym := p.fieldName()
|
sym, alias := p.fieldName()
|
||||||
typ := p.typ()
|
typ := p.typ()
|
||||||
note := p.string()
|
note := p.string()
|
||||||
|
|
||||||
@ -589,8 +589,8 @@ func (p *importer) field() *Field {
|
|||||||
}
|
}
|
||||||
sym = sym.Pkg.Lookup(s.Name)
|
sym = sym.Pkg.Lookup(s.Name)
|
||||||
f.Embedded = 1
|
f.Embedded = 1
|
||||||
} else if sym.Flags&SymAlias != 0 {
|
} else if alias {
|
||||||
// anonymous field: we have an explicit name because it's an alias
|
// anonymous field: we have an explicit name because it's a type alias
|
||||||
f.Embedded = 1
|
f.Embedded = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,15 +625,15 @@ func (p *importer) method() *Field {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *importer) fieldName() *Sym {
|
func (p *importer) fieldName() (*Sym, bool) {
|
||||||
name := p.string()
|
name := p.string()
|
||||||
if p.version == 0 && name == "_" {
|
if p.version == 0 && name == "_" {
|
||||||
// version 0 didn't export a package for _ field names
|
// version 0 didn't export a package for _ field names
|
||||||
// but used the builtin package instead
|
// but used the builtin package instead
|
||||||
return builtinpkg.Lookup(name)
|
return builtinpkg.Lookup(name), false
|
||||||
}
|
}
|
||||||
pkg := localpkg
|
pkg := localpkg
|
||||||
var flag SymFlags
|
alias := false
|
||||||
switch name {
|
switch name {
|
||||||
case "":
|
case "":
|
||||||
// 1) field name matches base type name and is exported: nothing to do
|
// 1) field name matches base type name and is exported: nothing to do
|
||||||
@ -644,16 +644,14 @@ func (p *importer) fieldName() *Sym {
|
|||||||
case "@":
|
case "@":
|
||||||
// 3) field name doesn't match base type name (alias name): need name and possibly package
|
// 3) field name doesn't match base type name (alias name): need name and possibly package
|
||||||
name = p.string()
|
name = p.string()
|
||||||
flag = SymAlias
|
alias = true
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
if !exportname(name) {
|
if !exportname(name) {
|
||||||
pkg = p.pkg()
|
pkg = p.pkg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym := pkg.Lookup(name)
|
return pkg.Lookup(name), alias
|
||||||
sym.Flags |= flag
|
|
||||||
return sym
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *importer) methodName() *Sym {
|
func (p *importer) methodName() *Sym {
|
||||||
|
@ -695,10 +695,20 @@ func typedcl0(s *Sym) *Node {
|
|||||||
|
|
||||||
// node n, which was returned by typedcl0
|
// node n, which was returned by typedcl0
|
||||||
// is being declared to have uncompiled type t.
|
// is being declared to have uncompiled type t.
|
||||||
// return the ODCLTYPE node to use.
|
// returns the ODCLTYPE node to use.
|
||||||
func typedcl1(n *Node, t *Node, local bool) *Node {
|
func typedcl1(n *Node, t *Node, pragma Pragma, alias bool) *Node {
|
||||||
n.Name.Param.Ntype = t
|
if pragma != 0 && alias {
|
||||||
n.Local = local
|
yyerror("cannot specify directive with type alias")
|
||||||
|
pragma = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
n.Local = true
|
||||||
|
|
||||||
|
p := n.Name.Param
|
||||||
|
p.Ntype = t
|
||||||
|
p.Pragma = pragma
|
||||||
|
p.Alias = alias
|
||||||
|
|
||||||
return nod(ODCLTYPE, n, nil)
|
return nod(ODCLTYPE, n, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ func exportsym(n *Node) {
|
|||||||
fmt.Printf("export symbol %v\n", n.Sym)
|
fmt.Printf("export symbol %v\n", n.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure original object is on exportlist before aliases.
|
// Ensure original types are on exportlist before type aliases.
|
||||||
if n.Sym.Flags&SymAlias != 0 {
|
if n.Sym.isAlias() {
|
||||||
exportlist = append(exportlist, n.Sym.Def)
|
exportlist = append(exportlist, n.Sym.Def)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +348,27 @@ func importvar(s *Sym, t *Type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// importalias declares symbol s as an imported type alias with type t.
|
||||||
|
func importalias(s *Sym, t *Type) {
|
||||||
|
importsym(s, OTYPE)
|
||||||
|
if s.Def != nil && s.Def.Op == OTYPE {
|
||||||
|
if eqtype(t, s.Def.Type) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
yyerror("inconsistent definition for type alias %v during import\n\t%v (in %q)\n\t%v (in %q)", s, s.Def.Type, s.Importdef.Path, t, importpkg.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := newname(s)
|
||||||
|
n.Op = OTYPE
|
||||||
|
s.Importdef = importpkg
|
||||||
|
n.Type = t
|
||||||
|
declare(n, PEXTERN)
|
||||||
|
|
||||||
|
if Debug['E'] != 0 {
|
||||||
|
fmt.Printf("import type %v = %L\n", s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func dumpasmhdr() {
|
func dumpasmhdr() {
|
||||||
b, err := bio.Create(asmhdr)
|
b, err := bio.Create(asmhdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -63,9 +63,12 @@ const (
|
|||||||
SymSiggen
|
SymSiggen
|
||||||
SymAsm
|
SymAsm
|
||||||
SymAlgGen
|
SymAlgGen
|
||||||
SymAlias // alias, original is Sym.Def.Sym
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (sym *Sym) isAlias() bool {
|
||||||
|
return sym.Def != nil && sym.Def.Sym != sym
|
||||||
|
}
|
||||||
|
|
||||||
// The Class of a variable/function describes the "storage class"
|
// The Class of a variable/function describes the "storage class"
|
||||||
// of a variable or function. During parsing, storage classes are
|
// of a variable or function. During parsing, storage classes are
|
||||||
// called declaration contexts.
|
// called declaration contexts.
|
||||||
@ -87,7 +90,7 @@ const (
|
|||||||
// of the compilers arrays.
|
// of the compilers arrays.
|
||||||
//
|
//
|
||||||
// typedef struct
|
// typedef struct
|
||||||
// { // must not move anything
|
// { // must not move anything
|
||||||
// uchar array[8]; // pointer to data
|
// uchar array[8]; // pointer to data
|
||||||
// uchar nel[4]; // number of elements
|
// uchar nel[4]; // number of elements
|
||||||
// uchar cap[4]; // allocated number of elements
|
// uchar cap[4]; // allocated number of elements
|
||||||
@ -104,7 +107,7 @@ var sizeof_Array int // runtime sizeof(Array)
|
|||||||
// of the compilers strings.
|
// of the compilers strings.
|
||||||
//
|
//
|
||||||
// typedef struct
|
// typedef struct
|
||||||
// { // must not move anything
|
// { // must not move anything
|
||||||
// uchar array[8]; // pointer to data
|
// uchar array[8]; // pointer to data
|
||||||
// uchar nel[4]; // number of elements
|
// uchar nel[4]; // number of elements
|
||||||
// } String;
|
// } String;
|
||||||
|
@ -927,7 +927,7 @@ func mkpackage(pkgname string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Def.Sym != s && s.Flags&SymAlias == 0 {
|
if s.isAlias() {
|
||||||
// throw away top-level name left over
|
// throw away top-level name left over
|
||||||
// from previous import . "x"
|
// from previous import . "x"
|
||||||
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
|
if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
|
||||||
|
@ -177,21 +177,12 @@ func (p *noder) constDecl(decl *syntax.ConstDecl) []*Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
func (p *noder) typeDecl(decl *syntax.TypeDecl) *Node {
|
||||||
if decl.Alias {
|
|
||||||
yyerror("type alias declarations unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
name := typedcl0(p.name(decl.Name))
|
name := typedcl0(p.name(decl.Name))
|
||||||
pragma := Pragma(decl.Pragma)
|
|
||||||
if pragma != 0 && decl.Alias {
|
|
||||||
yyerror("cannot specify directive with type alias")
|
|
||||||
pragma = 0
|
|
||||||
}
|
|
||||||
name.Name.Param.Pragma = pragma
|
|
||||||
|
|
||||||
|
// decl.Type may be nil but in that case we got a syntax error during parsing
|
||||||
typ := p.typeExprOrNil(decl.Type)
|
typ := p.typeExprOrNil(decl.Type)
|
||||||
|
|
||||||
return typedcl1(name, typ, true)
|
return typedcl1(name, typ, Pragma(decl.Pragma), decl.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
func (p *noder) declNames(names []*syntax.Name) []*Node {
|
||||||
|
@ -27,7 +27,7 @@ type Node struct {
|
|||||||
// func
|
// func
|
||||||
Func *Func
|
Func *Func
|
||||||
|
|
||||||
// ONAME
|
// ONAME, OTYPE, OPACK, OLABEL, some OLITERAL
|
||||||
Name *Name
|
Name *Name
|
||||||
|
|
||||||
Sym *Sym // various
|
Sym *Sym // various
|
||||||
@ -59,8 +59,8 @@ type Node struct {
|
|||||||
Noescape bool // func arguments do not escape; TODO(rsc): move Noescape to Func struct (see CL 7360)
|
Noescape bool // func arguments do not escape; TODO(rsc): move Noescape to Func struct (see CL 7360)
|
||||||
Walkdef uint8 // tracks state during typecheckdef; 2 == loop detected
|
Walkdef uint8 // tracks state during typecheckdef; 2 == loop detected
|
||||||
Typecheck uint8 // tracks state during typechecking; 2 == loop detected
|
Typecheck uint8 // tracks state during typechecking; 2 == loop detected
|
||||||
Local bool
|
Local bool // type created in this file (see also Type.Local); TODO(gri): move this into flags
|
||||||
IsStatic bool // whether this Node will be converted to purely static data
|
IsStatic bool // whether this Node will be converted to purely static data
|
||||||
Initorder uint8
|
Initorder uint8
|
||||||
Used bool // for variable/label declared and not used error
|
Used bool // for variable/label declared and not used error
|
||||||
Isddd bool // is the argument variadic
|
Isddd bool // is the argument variadic
|
||||||
@ -180,14 +180,14 @@ func (n *Node) SetIota(x int64) {
|
|||||||
n.Xoffset = x
|
n.Xoffset = x
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name holds Node fields used only by named nodes (ONAME, OPACK, OLABEL, some OLITERAL).
|
// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL).
|
||||||
type Name struct {
|
type Name struct {
|
||||||
Pack *Node // real package for import . names
|
Pack *Node // real package for import . names
|
||||||
Pkg *Pkg // pkg for OPACK nodes
|
Pkg *Pkg // pkg for OPACK nodes
|
||||||
Heapaddr *Node // temp holding heap address of param (could move to Param?)
|
Heapaddr *Node // temp holding heap address of param (could move to Param?)
|
||||||
Defn *Node // initializing assignment
|
Defn *Node // initializing assignment
|
||||||
Curfn *Node // function for local variables
|
Curfn *Node // function for local variables
|
||||||
Param *Param // additional fields for ONAME
|
Param *Param // additional fields for ONAME, OTYPE
|
||||||
Decldepth int32 // declaration loop depth, increased for every loop or label
|
Decldepth int32 // declaration loop depth, increased for every loop or label
|
||||||
Vargen int32 // unique name for ONAME within a function. Function outputs are numbered starting at one.
|
Vargen int32 // unique name for ONAME within a function. Function outputs are numbered starting at one.
|
||||||
Funcdepth int32
|
Funcdepth int32
|
||||||
@ -280,10 +280,11 @@ type Param struct {
|
|||||||
Innermost *Node
|
Innermost *Node
|
||||||
Outer *Node
|
Outer *Node
|
||||||
|
|
||||||
// OTYPE pragmas
|
// OTYPE
|
||||||
//
|
//
|
||||||
// TODO: Should Func pragmas also be stored on the Name?
|
// TODO: Should Func pragmas also be stored on the Name?
|
||||||
Pragma Pragma
|
Pragma Pragma
|
||||||
|
Alias bool // node is alias for Ntype
|
||||||
}
|
}
|
||||||
|
|
||||||
// Func holds Node fields used only with function-like nodes.
|
// Func holds Node fields used only with function-like nodes.
|
||||||
@ -382,7 +383,7 @@ const (
|
|||||||
ODCLFUNC // func f() or func (r) f()
|
ODCLFUNC // func f() or func (r) f()
|
||||||
ODCLFIELD // struct field, interface field, or func/method argument/return value.
|
ODCLFIELD // struct field, interface field, or func/method argument/return value.
|
||||||
ODCLCONST // const pi = 3.14
|
ODCLCONST // const pi = 3.14
|
||||||
ODCLTYPE // type Int int
|
ODCLTYPE // type Int int or type Int = int
|
||||||
|
|
||||||
ODELETE // delete(Left, Right)
|
ODELETE // delete(Left, Right)
|
||||||
ODOT // Left.Sym (Left is of struct type)
|
ODOT // Left.Sym (Left is of struct type)
|
||||||
|
@ -3578,8 +3578,6 @@ func typecheckdeftype(n *Node) {
|
|||||||
|
|
||||||
// copy new type and clear fields
|
// copy new type and clear fields
|
||||||
// that don't come along.
|
// that don't come along.
|
||||||
// anything zeroed here must be zeroed in
|
|
||||||
// typedcl2 too.
|
|
||||||
copytype(n, t)
|
copytype(n, t)
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
@ -3758,12 +3756,29 @@ func typecheckdef(n *Node) *Node {
|
|||||||
n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
|
n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
|
||||||
|
|
||||||
case OTYPE:
|
case OTYPE:
|
||||||
|
if p := n.Name.Param; p.Alias {
|
||||||
|
// Type alias declaration: Simply use the rhs type - no need
|
||||||
|
// to create a new type.
|
||||||
|
// If we have a syntax error, p.Ntype may be nil.
|
||||||
|
if p.Ntype != nil {
|
||||||
|
p.Ntype = typecheck(p.Ntype, Etype)
|
||||||
|
n.Type = p.Ntype.Type
|
||||||
|
if n.Type == nil {
|
||||||
|
n.Diag = true
|
||||||
|
goto ret
|
||||||
|
}
|
||||||
|
n.Sym.Def = p.Ntype
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// regular type declaration
|
||||||
if Curfn != nil {
|
if Curfn != nil {
|
||||||
defercheckwidth()
|
defercheckwidth()
|
||||||
}
|
}
|
||||||
n.Walkdef = 1
|
n.Walkdef = 1
|
||||||
n.Type = typ(TFORW)
|
n.Type = typ(TFORW)
|
||||||
n.Type.Sym = n.Sym
|
n.Type.Sym = n.Sym // TODO(gri) this also happens in typecheckdeftype(n) - where should it happen?
|
||||||
nerrors0 := nerrors
|
nerrors0 := nerrors
|
||||||
typecheckdeftype(n)
|
typecheckdeftype(n)
|
||||||
if n.Type.Etype == TFORW && nerrors > nerrors0 {
|
if n.Type.Etype == TFORW && nerrors > nerrors0 {
|
||||||
@ -3771,7 +3786,6 @@ func typecheckdef(n *Node) *Node {
|
|||||||
// but it was reported. Silence future errors.
|
// but it was reported. Silence future errors.
|
||||||
n.Type.Broke = true
|
n.Type.Broke = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if Curfn != nil {
|
if Curfn != nil {
|
||||||
resumecheckwidth()
|
resumecheckwidth()
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,6 @@
|
|||||||
|
|
||||||
// Test basic restrictions on type aliases.
|
// Test basic restrictions on type aliases.
|
||||||
|
|
||||||
// The compiler doesn't implement type aliases yet,
|
|
||||||
// so for now we get the same error (unimplemented)
|
|
||||||
// everywhere, OR-ed into the ERROR checks.
|
|
||||||
// TODO(gri) remove the need for "unimplemented"
|
|
||||||
|
|
||||||
package p
|
package p
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -18,41 +13,87 @@ import (
|
|||||||
. "reflect"
|
. "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type T0 struct{}
|
||||||
|
|
||||||
// Valid type alias declarations.
|
// Valid type alias declarations.
|
||||||
|
|
||||||
type _ = int // ERROR "unimplemented"
|
type _ = T0
|
||||||
type _ = struct{} // ERROR "unimplemented"
|
type _ = int
|
||||||
type _ = reflect.Value // ERROR "unimplemented"
|
type _ = struct{}
|
||||||
type _ = Value // ERROR "unimplemented"
|
type _ = reflect.Value
|
||||||
|
type _ = Value
|
||||||
|
|
||||||
type (
|
type (
|
||||||
a1 = int // ERROR "unimplemented"
|
A0 = T0
|
||||||
a2 = struct{} // ERROR "unimplemented"
|
A1 = int
|
||||||
a3 = reflect.Value // ERROR "unimplemented"
|
A2 = struct{}
|
||||||
a4 = Value // ERROR "unimplemented"
|
A3 = reflect.Value
|
||||||
|
A4 = Value
|
||||||
|
A5 = Value
|
||||||
|
|
||||||
|
N0 A0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Methods can be declared on the original named type and the alias.
|
||||||
|
func (T0) m1() {}
|
||||||
|
func (A0) m1() {} // TODO(gri) this should be an error
|
||||||
|
func (A0) m2() {}
|
||||||
|
|
||||||
|
// Type aliases and the original type name can be used interchangeably.
|
||||||
|
var _ A0 = T0{}
|
||||||
|
var _ T0 = A0{}
|
||||||
|
|
||||||
|
// But aliases and original types cannot be used with new types based on them.
|
||||||
|
var _ N0 = T0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment"
|
||||||
|
var _ N0 = A0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment"
|
||||||
|
|
||||||
|
var _ A5 = Value{}
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
m1()
|
||||||
|
m2()
|
||||||
|
} = T0{}
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
m1()
|
||||||
|
m2()
|
||||||
|
} = A0{}
|
||||||
|
|
||||||
func _() {
|
func _() {
|
||||||
type _ = int // ERROR "unimplemented"
|
type _ = T0
|
||||||
type _ = struct{} // ERROR "unimplemented"
|
type _ = int
|
||||||
type _ = reflect.Value // ERROR "unimplemented"
|
type _ = struct{}
|
||||||
type _ = Value // ERROR "unimplemented"
|
type _ = reflect.Value
|
||||||
|
type _ = Value
|
||||||
|
|
||||||
type (
|
type (
|
||||||
a1 = int // ERROR "unimplemented"
|
A0 = T0
|
||||||
a2 = struct{} // ERROR "unimplemented"
|
A1 = int
|
||||||
a3 = reflect.Value // ERROR "unimplemented"
|
A2 = struct{}
|
||||||
a4 = Value // ERROR "unimplemented"
|
A3 = reflect.Value
|
||||||
|
A4 = Value
|
||||||
|
A5 Value
|
||||||
|
|
||||||
|
N0 A0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ A0 = T0{}
|
||||||
|
var _ T0 = A0{}
|
||||||
|
|
||||||
|
var _ N0 = T0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment"
|
||||||
|
var _ N0 = A0{} // ERROR "cannot use T0 literal \(type T0\) as type N0 in assignment"
|
||||||
|
|
||||||
|
var _ A5 = Value{} // ERROR "cannot use reflect\.Value literal \(type reflect.Value\) as type A5 in assignment"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalid type alias declarations.
|
// Invalid type alias declarations.
|
||||||
|
|
||||||
type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|unimplemented"
|
type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type"
|
||||||
|
|
||||||
type b1 = struct{} // ERROR "unimplemented"
|
func (A1) m() {} // ERROR "cannot define new methods on non-local type int"
|
||||||
func (b1) m() {} // disabled ERROR "invalid receiver type"
|
|
||||||
|
type B1 = struct{}
|
||||||
|
|
||||||
|
func (B1) m() {} // ERROR "invalid receiver type"
|
||||||
|
|
||||||
// TODO(gri) expand
|
// TODO(gri) expand
|
||||||
// It appears that type-checking exits after some more severe errors, so we may
|
|
||||||
// need more test files.
|
|
||||||
|
Reference in New Issue
Block a user