diff --git a/compiler/analysis/info.go b/compiler/analysis/info.go index c984b726f..304c8808a 100644 --- a/compiler/analysis/info.go +++ b/compiler/analysis/info.go @@ -93,7 +93,10 @@ func (info *Info) newFuncInfo(n ast.Node) *FuncInfo { } func (info *Info) IsBlocking(fun *types.Func) bool { - return len(info.FuncDeclInfos[fun].Blocking) > 0 + if funInfo := info.FuncDeclInfos[fun]; funInfo != nil { + return len(funInfo.Blocking) > 0 + } + panic(fmt.Errorf(`info did not have function declaration for %s`, fun.FullName())) } func AnalyzePkg(files []*ast.File, fileSet *token.FileSet, typesInfo *types.Info, typesPkg *types.Package, isBlocking func(*types.Func) bool) *Info { diff --git a/compiler/expressions.go b/compiler/expressions.go index db08cc31f..21971ab5f 100644 --- a/compiler/expressions.go +++ b/compiler/expressions.go @@ -267,7 +267,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression { case token.ARROW: call := &ast.CallExpr{ - Fun: fc.newIdent("$recv", types.NewSignature(nil, types.NewTuple(types.NewVar(0, nil, "", t)), types.NewTuple(types.NewVar(0, nil, "", exprType), types.NewVar(0, nil, "", types.Typ[types.Bool])), false)), + Fun: fc.newIdent("$recv", types.NewSignatureType(nil, nil, nil, types.NewTuple(types.NewVar(0, nil, "", t)), types.NewTuple(types.NewVar(0, nil, "", exprType), types.NewVar(0, nil, "", types.Typ[types.Bool])), false)), Args: []ast.Expr{e.X}, } fc.Blocking[call] = true @@ -520,8 +520,11 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression { ) case *types.Basic: return fc.formatExpr("%e.charCodeAt(%f)", e.X, e.Index) + case *types.Signature: + err := bailout(fmt.Errorf(`unsupported type parameters used at %s`, fc.pkgCtx.fileSet.Position(e.Pos()))) + panic(err) default: - panic(fmt.Sprintf("Unhandled IndexExpr: %T\n", t)) + panic(fmt.Errorf(`unhandled IndexExpr: %T`, t)) } case *ast.SliceExpr: @@ -703,7 +706,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression { case "Float": return fc.internalize(recv, types.Typ[types.Float64]) case "Interface": - return fc.internalize(recv, types.NewInterface(nil, nil)) + return fc.internalize(recv, types.NewInterfaceType(nil, nil)) case "Unsafe": return recv default: @@ -998,7 +1001,7 @@ func (fc *funcContext) translateBuiltin(name string, sig *types.Signature, args panic(fmt.Sprintf("Unhandled cap type: %T\n", argType)) } case "panic": - return fc.formatExpr("$panic(%s)", fc.translateImplicitConversion(args[0], types.NewInterface(nil, nil))) + return fc.formatExpr("$panic(%s)", fc.translateImplicitConversion(args[0], types.NewInterfaceType(nil, nil))) case "append": if ellipsis || len(args) == 1 { argStr := fc.translateArgs(sig, args, ellipsis) diff --git a/compiler/package.go b/compiler/package.go index 93c22f1c5..ad918ba3e 100644 --- a/compiler/package.go +++ b/compiler/package.go @@ -131,6 +131,7 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor } if fe, ok := bailingOut(e); ok { // Orderly bailout, return whatever clues we already have. + fmt.Fprintf(fe, `building package %q`, importPath) err = fe return } @@ -269,7 +270,7 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor } sort.Strings(importedPaths) for _, impPath := range importedPaths { - id := funcCtx.newIdent(fmt.Sprintf(`%s.$init`, funcCtx.pkgCtx.pkgVars[impPath]), types.NewSignature(nil, nil, nil, false)) + id := funcCtx.newIdent(fmt.Sprintf(`%s.$init`, funcCtx.pkgCtx.pkgVars[impPath]), types.NewSignatureType(nil, nil, nil, nil, nil, false)) call := &ast.CallExpr{Fun: id} funcCtx.Blocking[call] = true funcCtx.Flattened[call] = true @@ -287,13 +288,6 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor switch d := decl.(type) { case *ast.FuncDecl: sig := funcCtx.pkgCtx.Defs[d.Name].(*types.Func).Type().(*types.Signature) - var recvType types.Type - if sig.Recv() != nil { - recvType = sig.Recv().Type() - if ptr, isPtr := recvType.(*types.Pointer); isPtr { - recvType = ptr.Elem() - } - } if sig.Recv() == nil { funcCtx.objectName(funcCtx.pkgCtx.Defs[d.Name].(*types.Func)) // register toplevel name } @@ -421,7 +415,7 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor d.DceObjectFilter = "" case "init": d.InitCode = funcCtx.CatchOutput(1, func() { - id := funcCtx.newIdent("", types.NewSignature(nil, nil, nil, false)) + id := funcCtx.newIdent("", types.NewSignatureType(nil, nil, nil, nil, nil, false)) funcCtx.pkgCtx.Uses[id] = o call := &ast.CallExpr{Fun: id} if len(funcCtx.pkgCtx.FuncDeclInfos[o].Blocking) != 0 { @@ -438,7 +432,14 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor if isPointer { namedRecvType = ptr.Elem().(*types.Named) } - d.NamedRecvType = funcCtx.objectName(namedRecvType.Obj()) + if namedRecvType.TypeParams() != nil { + return nil, scanner.Error{ + Pos: fileSet.Position(o.Pos()), + Msg: fmt.Sprintf("type %s: type parameters are not supported by GopherJS: https://github.com/gopherjs/gopherjs/issues/1013", o.FullName()), + } + } + name := funcCtx.objectName(namedRecvType.Obj()) + d.NamedRecvType = name d.DceObjectFilter = namedRecvType.Obj().Name() if !fun.Name.IsExported() { d.DceMethodFilter = o.Name() + "~" @@ -454,7 +455,7 @@ func Compile(importPath string, files []*ast.File, fileSet *token.FileSet, impor if mainFunc == nil { return nil, fmt.Errorf("missing main function") } - id := funcCtx.newIdent("", types.NewSignature(nil, nil, nil, false)) + id := funcCtx.newIdent("", types.NewSignatureType(nil, nil, nil, nil, nil, false)) funcCtx.pkgCtx.Uses[id] = mainFunc call := &ast.CallExpr{Fun: id} ifStmt := &ast.IfStmt{ @@ -636,9 +637,9 @@ func (fc *funcContext) initArgs(ty types.Type) string { case *types.Map: return fmt.Sprintf("%s, %s", fc.typeName(t.Key()), fc.typeName(t.Elem())) case *types.Pointer: - return fmt.Sprintf("%s", fc.typeName(t.Elem())) + return fc.typeName(t.Elem()) case *types.Slice: - return fmt.Sprintf("%s", fc.typeName(t.Elem())) + return fc.typeName(t.Elem()) case *types.Signature: params := make([]string, t.Params().Len()) for i := range params { @@ -660,6 +661,9 @@ func (fc *funcContext) initArgs(ty types.Type) string { fields[i] = fmt.Sprintf(`{prop: "%s", name: %s, embedded: %t, exported: %t, typ: %s, tag: %s}`, fieldName(t, i), encodeString(field.Name()), field.Anonymous(), field.Exported(), fc.typeName(field.Type()), encodeString(t.Tag(i))) } return fmt.Sprintf(`"%s", [%s]`, pkgPath, strings.Join(fields, ", ")) + case *types.TypeParam: + err := bailout(fmt.Errorf(`%v has unexpected generic type parameter %T`, ty, ty)) + panic(err) default: err := bailout(fmt.Errorf("%v has unexpected type %T", ty, ty)) panic(err) diff --git a/compiler/statements.go b/compiler/statements.go index f8d791948..8518f9b71 100644 --- a/compiler/statements.go +++ b/compiler/statements.go @@ -32,7 +32,7 @@ func (fc *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) { panic(err) // Continue orderly bailout. } - // Oh noes, we've tried to compile something so bad that compiler paniced + // Oh noes, we've tried to compile something so bad that compiler panicked // and ran away. Let's gather some debugging clues. bail := bailout(err) pos := stmt.Pos() @@ -471,7 +471,7 @@ func (fc *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) { case *ast.SendStmt: chanType := fc.pkgCtx.TypeOf(s.Chan).Underlying().(*types.Chan) call := &ast.CallExpr{ - Fun: fc.newIdent("$send", types.NewSignature(nil, types.NewTuple(types.NewVar(0, nil, "", chanType), types.NewVar(0, nil, "", chanType.Elem())), nil, false)), + Fun: fc.newIdent("$send", types.NewSignatureType(nil, nil, nil, types.NewTuple(types.NewVar(0, nil, "", chanType), types.NewVar(0, nil, "", chanType.Elem())), nil, false)), Args: []ast.Expr{s.Chan, fc.newIdent(fc.translateImplicitConversionWithCloning(s.Value, chanType.Elem()).String(), chanType.Elem())}, } fc.Blocking[call] = true @@ -522,8 +522,8 @@ func (fc *funcContext) translateStmt(stmt ast.Stmt, label *types.Label) { } selectCall := fc.setType(&ast.CallExpr{ - Fun: fc.newIdent("$select", types.NewSignature(nil, types.NewTuple(types.NewVar(0, nil, "", types.NewInterface(nil, nil))), types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])), false)), - Args: []ast.Expr{fc.newIdent(fmt.Sprintf("[%s]", strings.Join(channels, ", ")), types.NewInterface(nil, nil))}, + Fun: fc.newIdent("$select", types.NewSignatureType(nil, nil, nil, types.NewTuple(types.NewVar(0, nil, "", types.NewInterfaceType(nil, nil))), types.NewTuple(types.NewVar(0, nil, "", types.Typ[types.Int])), false)), + Args: []ast.Expr{fc.newIdent(fmt.Sprintf("[%s]", strings.Join(channels, ", ")), types.NewInterfaceType(nil, nil))}, }, types.Typ[types.Int]) if !hasDefault { fc.Blocking[selectCall] = true diff --git a/compiler/utils.go b/compiler/utils.go index 8b18c29c1..058437f67 100644 --- a/compiler/utils.go +++ b/compiler/utils.go @@ -518,13 +518,13 @@ func isBlank(expr ast.Expr) bool { // // For example, consider a Go type: // -// type SecretInt int -// func (_ SecretInt) String() string { return "" } +// type SecretInt int +// func (_ SecretInt) String() string { return "" } // -// func main() { -// var i SecretInt = 1 -// println(i.String()) -// } +// func main() { +// var i SecretInt = 1 +// println(i.String()) +// } // // For this example the compiler will generate code similar to the snippet below: // @@ -765,7 +765,7 @@ func (st signatureTypes) Param(i int, ellipsis bool) types.Type { } if !st.Sig.Variadic() { // This should never happen if the code was type-checked successfully. - panic(fmt.Errorf("Tried to access parameter %d of a non-variadic signature %s", i, st.Sig)) + panic(fmt.Errorf("tried to access parameter %d of a non-variadic signature %s", i, st.Sig)) } if ellipsis { return st.VariadicType()