@@ -750,17 +750,15 @@ func (c *compiler) CallNode(node *ast.CallNode) {
750750 }
751751 for i , arg := range node .Arguments {
752752 c .compile (arg )
753- if k := kind (arg .Type ()); k == reflect .Ptr || k == reflect .Interface {
754- var in reflect.Type
755- if fn .IsVariadic () && i >= fnNumIn - 1 {
756- in = fn .In (fn .NumIn () - 1 ).Elem ()
757- } else {
758- in = fn .In (i + fnInOffset )
759- }
760- if k = kind (in ); k != reflect .Ptr && k != reflect .Interface {
761- c .emit (OpDeref )
762- }
753+
754+ var in reflect.Type
755+ if fn .IsVariadic () && i >= fnNumIn - 1 {
756+ in = fn .In (fn .NumIn () - 1 ).Elem ()
757+ } else {
758+ in = fn .In (i + fnInOffset )
763759 }
760+
761+ c .derefParam (in , arg )
764762 }
765763 } else {
766764 for _ , arg := range node .Arguments {
@@ -1059,8 +1057,19 @@ func (c *compiler) BuiltinNode(node *ast.BuiltinNode) {
10591057
10601058 if id , ok := builtin .Index [node .Name ]; ok {
10611059 f := builtin .Builtins [id ]
1062- for _ , arg := range node .Arguments {
1060+ for i , arg := range node .Arguments {
10631061 c .compile (arg )
1062+ argType := arg .Type ()
1063+ if argType .Kind () == reflect .Ptr || arg .Nature ().IsUnknown () {
1064+ if f .Deref == nil {
1065+ // By default, builtins expect arguments to be dereferenced.
1066+ c .emit (OpDeref )
1067+ } else {
1068+ if f .Deref (i , argType ) {
1069+ c .emit (OpDeref )
1070+ }
1071+ }
1072+ }
10641073 }
10651074
10661075 if f .Fast != nil {
@@ -1218,6 +1227,18 @@ func (c *compiler) derefInNeeded(node ast.Node) {
12181227 }
12191228}
12201229
1230+ func (c * compiler ) derefParam (in reflect.Type , param ast.Node ) {
1231+ if param .Nature ().Nil {
1232+ return
1233+ }
1234+ if param .Type ().AssignableTo (in ) {
1235+ return
1236+ }
1237+ if in .Kind () != reflect .Ptr && param .Type ().Kind () == reflect .Ptr {
1238+ c .emit (OpDeref )
1239+ }
1240+ }
1241+
12211242func (c * compiler ) optimize () {
12221243 for i , op := range c .bytecode {
12231244 switch op {
0 commit comments