diff --git a/ast.go b/ast.go index 71079ea9..9748b965 100644 --- a/ast.go +++ b/ast.go @@ -714,6 +714,15 @@ retry: switch t := fn.Val.(type) { case *ast.BinaryExpr: t.X, t.Y = checkParenExpr(args[0].Val), checkParenExpr(args[1].Val) + // update untyped + if pkg.cb.rec != nil { + if isBasicUntyped(args[0].Type) { + pkg.cb.rec.UpdateUntyped(args[0], tyRet) + } + if (t.Op != token.SHL && t.Op != token.SHR) && isBasicUntyped(args[1].Type) { + pkg.cb.rec.UpdateUntyped(args[1], tyRet) + } + } return &internal.Elem{Val: t, Type: tyRet, CVal: cval}, nil case *ast.UnaryExpr: t.X = args[0].Val @@ -741,8 +750,9 @@ func matchTypeCast(pkg *Package, typ types.Type, fn *internal.Elem, args []*inte fnVal = &ast.ParenExpr{X: fnVal} } if len(args) == 1 && ConvertibleTo(pkg, args[0].Type, typ) { + // update untyped if pkg.cb.rec != nil && isBasicUntyped(args[0].Type) { - pkg.cb.rec.UpdateType(args[0], typ) + pkg.cb.rec.UpdateUntyped(args[0], typ) } if args[0].CVal != nil { if t, ok := typ.(*types.Named); ok { @@ -1190,6 +1200,7 @@ func (p *MatchError) Error() string { // TODO: use matchType to all assignable check func matchType(pkg *Package, arg *internal.Elem, param types.Type, at interface{}) (r error) { + // update untyped if pkg.cb.rec != nil && isBasicUntyped(arg.Type) { defer func() { if r == nil { @@ -1200,7 +1211,7 @@ func matchType(pkg *Package, arg *internal.Elem, param types.Type, at interface{ typ = t.tBound goto retry case *types.Basic: - pkg.cb.rec.UpdateType(arg, t) + pkg.cb.rec.UpdateUntyped(arg, t) } } }() diff --git a/codebuild.go b/codebuild.go index 2af7fe65..3a58b4ae 100644 --- a/codebuild.go +++ b/codebuild.go @@ -1075,8 +1075,9 @@ func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool, src ...a pos, "cannot use %s (type %v) as type %v in value of field %s", src, args[i+1].Type, eltTy, eltName) } + // update untyped if pkg.cb.rec != nil && isBasicUntyped(args[i+1].Type) { - pkg.cb.rec.UpdateType(args[i+1], eltTy) + pkg.cb.rec.UpdateUntyped(args[i+1], eltTy) } elts[i>>1] = &ast.KeyValueExpr{Key: ident(eltName), Value: args[i+1].Val} } @@ -1100,8 +1101,9 @@ func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool, src ...a pos, "cannot use %s (type %v) as type %v in value of field %s", src, arg.Type, eltTy, t.Field(i).Name()) } + // update untyped if pkg.cb.rec != nil && isBasicUntyped(arg.Type) { - pkg.cb.rec.UpdateType(arg, eltTy) + pkg.cb.rec.UpdateUntyped(arg, eltTy) } } } @@ -1151,15 +1153,16 @@ func (p *CodeBuilder) Slice(slice3 bool, src ...ast.Node) *CodeBuilder { // a[i: if slice3 { exprMax = args[3].Val } + // update untyped if p.rec != nil { if isBasicUntyped(args[1].Type) { - p.rec.UpdateType(args[1], types.Default(args[1].Type)) + p.rec.UpdateUntyped(args[1], types.Default(args[1].Type)) } if isBasicUntyped(args[2].Type) { - p.rec.UpdateType(args[2], types.Default(args[2].Type)) + p.rec.UpdateUntyped(args[2], types.Default(args[2].Type)) } if slice3 && isBasicUntyped(args[3].Type) { - p.rec.UpdateType(args[3], types.Default(args[3].Type)) + p.rec.UpdateUntyped(args[3], types.Default(args[3].Type)) } } @@ -2072,6 +2075,16 @@ retry: if !ComparableTo(pkg, args[0], args[1]) { return nil, errors.New("mismatched types") } + // update untyped + if pkg.cb.rec != nil { + b0 := isBasicUntyped(args[0].Type) + b1 := isBasicUntyped(args[1].Type) + if b0 && !b1 { + pkg.cb.rec.UpdateUntyped(args[0], args[1].Type) + } else if b1 && !b0 { + pkg.cb.rec.UpdateUntyped(args[1], args[0].Type) + } + } ret = &internal.Elem{ Val: &ast.BinaryExpr{ X: checkParenExpr(args[0].Val), Op: op, diff --git a/package.go b/package.go index ef3aab41..b88aba01 100644 --- a/package.go +++ b/package.go @@ -73,7 +73,7 @@ func fatal(msg string) { type Recorder interface { // Member maps identifiers to the objects they denote. Member(id ast.Node, obj types.Object) - UpdateType(e *Element, typ types.Type) + UpdateUntyped(e *Element, typ types.Type) } // ---------------------------------------------------------------------------- diff --git a/package_test.go b/package_test.go index b10031d4..e24db31c 100644 --- a/package_test.go +++ b/package_test.go @@ -52,6 +52,8 @@ type eventRecorder struct{} func (p eventRecorder) Member(id ast.Node, obj types.Object) { } +func (p eventRecorder) UpdateUntyped(e *gox.Element, typ types.Type) { +} func newMainPackage( implicitCast ...func(pkg *gox.Package, V, T types.Type, pv *gox.Element) bool) *gox.Package { diff --git a/template.go b/template.go index 284b8cbe..621f2327 100644 --- a/template.go +++ b/template.go @@ -225,13 +225,7 @@ func DefaultConv(pkg *Package, t types.Type, pv *Element) types.Type { log.Panicln("==> DefaultConv failed: overload functions have no default type") } default: - if isBasicUntyped(typ) { - typ := types.Default(t) - if pkg.cb.rec != nil && pv != nil { - pkg.cb.rec.UpdateType(pv, typ) - } - return typ - } + return types.Default(t) } return t } diff --git a/type_var_and_const.go b/type_var_and_const.go index 5ddf6538..91322176 100644 --- a/type_var_and_const.go +++ b/type_var_and_const.go @@ -328,8 +328,9 @@ func (p *ValueDecl) endInit(cb *CodeBuilder, arity int) *ValueDecl { if err := matchType(pkg, ret, typ, "assignment"); err != nil { panic(err) } + // update untyped if cb.rec != nil && isBasicUntyped(ret.Type) { - cb.rec.UpdateType(ret, typ) + cb.rec.UpdateUntyped(ret, typ) } if values != nil { // ret.Val may be changed values[i] = ret.Val @@ -366,8 +367,9 @@ func (p *ValueDecl) endInit(cb *CodeBuilder, arity int) *ValueDecl { if values != nil { values[i] = parg.Val } + // update untyped if pkg.cb.rec != nil && isBasicUntyped(rets[i].Type) { - pkg.cb.rec.UpdateType(rets[i], retType) + pkg.cb.rec.UpdateUntyped(rets[i], retType) } if old := p.scope.Insert(types.NewVar(p.pos, pkg.Types, name, retType)); old != nil { if p.tok != token.DEFINE {