Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: __SOURCE__ constant like __FILE__, __LINE__, __FUNCTION__ C++ macro #37620

Open
kokizzu opened this issue Mar 3, 2020 · 10 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FeatureRequest NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@kokizzu
Copy link

kokizzu commented Mar 3, 2020

those macros are very useful for debugging and caching:

__SOURCE__ = __FILE__:__LINE__ __FUNCTION__
/foo/bar.go:123 foo.Bar.HomeHandler(Context)

usage example

func (b *Bar) HomeHandler(ctx *Context) {
    res := DoQuery(__SOURCE__, sql, parameters)
    ...
}
func DoQuery(source, sql string, args ...interface{}) *sql.Rows {
    // cache using __SOURCE__ and args
    sql = ` -- ` + __SOURCE__ + `
    ` + sql
    ...
}

on code above, if there's sql error, we can know who's the caller directly if there's SQL error (without needing to access runtime.Stack/FuncForPC (which i currently use), this is a bit similar to C# [System.Runtime.CompilerServices.CallerMemberName], [System.Runtime.CompilerServices.CallerFilePath], [System.Runtime.CompilerServices.CallerLineNumber] but works on compile time instead of runtime.

@ianlancetaylor
Copy link
Contributor

You can get all of this information by calling runtime.Caller.

We could choose to implement runtime.Caller directly in the compiler if that seems to be useful.

@kokizzu
Copy link
Author

kokizzu commented Mar 3, 2020

i think if the string generated at compile time (then sent to the other function) would be more efficient than inspecting stack trace at runtime.

@ianlancetaylor
Copy link
Contributor

I'm saying that if this seems important then we could implement runtime.Caller in the compiler such that the string is determined at compile time.

It's not obvious to me that we need two different ways to get the same information.

@dmitshur dmitshur added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. FeatureRequest labels Mar 3, 2020
@dmitshur dmitshur added this to the Backlog milestone Mar 3, 2020
@dmitshur dmitshur changed the title feature request: __SOURCE__ constant like __FILE__, __LINE__, __FUNCTION__ C++ macro cmd/compile: __SOURCE__ constant like __FILE__, __LINE__, __FUNCTION__ C++ macro Mar 3, 2020
@kokizzu
Copy link
Author

kokizzu commented Mar 3, 2020

but i'm really not sure if we could get info about the caller at compile time '__')

@ianlancetaylor
Copy link
Contributor

The compiler can trivially compute the file and line results of runtime.Caller(0) at compile time.

It takes a little more work to trace the PC result passed into runtime.FuncForPC, but that too is doable.

@kokizzu
Copy link
Author

kokizzu commented Mar 4, 2020

I mean, if there's function A and B that calls function C, wouldn't that be require runtime instead of compile time?

func A() { C() }
func B() { C() }
func C() { can be A or B }

also if using __SOURCE__ it's more controllable, since we could do something like this:

func A() { B(__SOURCE__) }
func X() { B(__SOURCE__) }
func B(src) { C(src) }
func C(src) { use the src } // which can be A or X

@ianlancetaylor
Copy link
Contributor

func A() {
    _, source, _, _ := runtime.Caller(0)
    B(source)
}

@eddyli1989
Copy link

eddyli1989 commented Aug 4, 2021

runtime.Caller is expensive
in Performance-sensitive case
__FILE__ __LINE__ is a better way

@leighmcculloch
Copy link
Contributor

There's an element of this that isn't only about performance. This would be helpful for quick insert print style debugging. I know we have delve and other tools, but sometimes print style debugging ftw.

The fact that runtime.Caller returns multiple values makes this a little inconvenient because it can't be inlined into the fmt.Printf, but a scope fixes that.

func A() {
	{
		_, file, line, _ := runtime.Caller(0)
		fmt.Printf("%s:%d i was here", file, line)
	}
	// ...
	{
		_, file, line, _ := runtime.Caller(0)
		fmt.Printf("%s:%d i was here", file, line)
	}
	// ...
}

__FILE__ and __LINE__ constants would be more convenient.

func A() {
	fmt.Printf("%s:%d i was here", __FILE__, __LINE__)
	// ...
	fmt.Printf("%s:%d i was here", __FILE__, __LINE__)
	// ...
}

I'm not sure this is compelling enough, but I know I'd definitely use it if it existed.

@AlekSi
Copy link
Contributor

AlekSi commented Jul 11, 2024

See also #12876 and #27329

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FeatureRequest NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
Status: Triage Backlog
Development

No branches or pull requests

7 participants