Interesting. Do you have a reference to where that happens?

If i understand you correctly, however, it doesn't appear to solve the case 
where the called function fn lives in a different package, and takes an 
argument which is a private type. That is:

-- a/a.go --
package a

type myString string

func Fn(str myString) { }

-- b/b.go --
package b

import "a"

func rewrite() {
    go a.Fn("some string")
}

In this example knowing the desired type from the function signature does 
not help, I would think?

On Friday, November 8, 2019 at 6:58:02 PM UTC+1, Ian Lance Taylor wrote:
>
> On Fri, Nov 8, 2019 at 9:08 AM André Eriksson <ean...@gmail.com 
> <javascript:>> wrote: 
> > 
> > That works in simple cases, but does not work when the expression is an 
> untyped constant, like 1 or nil. In the case of 1 the variable will get a 
> concrete type of int, while fn may accept a float32, or even a private type 
> that cannot be named in the current package. 
>
> You might want to look at the rewriting that cmd/cgo does, as it 
> handles this exact kind of case.  Basically, for untyped constants, 
> you know the desired type, because it's in the function signature.  So 
> use that. 
>
> It does get kind of complicated, though. 
>
> Ian 
>
>
> > On Friday, November 8, 2019 at 5:51:10 PM UTC+1, Michael Jones wrote: 
> >> 
> >> If expr was evaluable in the original code then why not rewrite in 
> place after assigning temporaries? 
> >> 
> >> go fn(e1,e2) 
> >> 
> >> { 
> >> t1,t2 := e1,e2 
> >> go func() { 
> >>   defer instrument() 
> >>   fn(t1,t2) 
> >> } 
> >> 
> >> 
> >> On Fri, Nov 8, 2019 at 8:38 AM André Eriksson <ean...@gmail.com> 
> wrote: 
> >>> 
> >>> I am working on a type of Go preprocessor that rewrites source code to 
> add additional instrumentation to certain types of statements. 
> >>> 
> >>> One such statement is the go statement. I would like to instrument the 
> newly created goroutine, injecting some instrumentation code at the start 
> and finish of the goroutine. 
> >>> 
> >>> In the simple case, the rewrite is straightforward: 
> >>> 
> >>> go fn() 
> >>> 
> >>> becomes 
> >>> 
> >>> go func() { 
> >>> defer instrument()() 
> >>> fn() 
> >>> }() 
> >>> 
> >>> However this approach does not work when fn takes parameters. 
> >>> If we were to rewrite go fn(expr) into the equivalent form above: 
> >>> 
> >>> go func() { 
> >>> defer instrument()() 
> >>> fn(expr) 
> >>> }() 
> >>> 
> >>> 
> >>> the semantics change, since in the rewrite expr gets evaluated inside 
> the newly created goroutine, which can change the behavior and introduce 
> data races. 
> >>> 
> >>> My attempts to address this have not been particularly fruitful. 
> >>> 
> >>> One cannot pass in expr as an argument to the closure, because the 
> type of the expression may not have a valid name in the current package 
> (for example if expr evaluates to a private type in some other package). 
> >>> 
> >>> Similarly, if expr is a constant expression (like 1 or nil) the type 
> may depend on the corresponding parameter in fn’s signature. 
> >>> 
> >>> The only semantics-preserving rewrite I can think of revolves around 
> using package reflect, and rewriting like so: 
> >>> 
> >>> go func(fn reflect.Value, vals …reflect.Value) { 
> >>> defer instrument() 
> >>> fn.Call(vals) 
> >>> }(reflect.ValueOf(fn), reflect.ValueOf(expr)) 
> >>> 
> >>> As far as I understand, this should be semantics-preserving, although 
> with a slight performance cost. (Though I imagine the cost of a 
> reflection-based call is dwarfed by the cost of spawning a goroutine.) 
> >>> 
> >>> Unfortunately this also comes with a major downside: the rewritten 
> code does not typecheck identically to the original code. Ideally I would 
> like the rewritten form to cause identical typechecking failures to the old 
> code, so that these errors are caught at compile time without requiring a 
> separate typechecking pass for the original code. 
> >>> 
> >>> Am I correct in the above reasoning? Can anyone think of a way to do 
> this sort of rewrite in a semantics-preserving and typechecking-preserving 
> way? 
> >>> 
> >>> -- 
> >>> You received this message because you are subscribed to the Google 
> Groups "golang-nuts" group. 
> >>> To unsubscribe from this group and stop receiving emails from it, send 
> an email to golan...@googlegroups.com. 
> >>> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/a92641f3-2eda-4d4a-ab02-d2b40e3bde75%40googlegroups.com.
>  
>
> >> 
> >> 
> >> 
> >> -- 
> >> Michael T. Jones 
> >> michae...@gmail.com 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups "golang-nuts" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an email to golan...@googlegroups.com <javascript:>. 
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/ec41a345-163f-4a8a-a24f-b868def081a0%40googlegroups.com.
>  
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/0ff39043-4699-4f0b-a1c0-6c4ebc5eb208%40googlegroups.com.

Reply via email to