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

Don't flag self–assignments with side effects #638

Closed

Conversation

ksurent
Copy link
Contributor

@ksurent ksurent commented Oct 27, 2019

Fix SA4018 to not flag self–assignments of the form x[e] = x[e] where e may have side effects (e.g. a function call we know isn't pure or a channel read).

This also includes a change that unties the implementation of the purity fact from SA4017, making it available for reuse in SA4018 and potentially other checks in the future.

compute the fact using a more traditional definition of purity and adjust
SA4017 accordingly

the main change is that some stub functions (as defined by functions.IsStub)
can be considered pure now
return false
}
if id, ok := call.Fun.(*ast.Ident); ok {
if fn, ok := pass.TypesInfo.ObjectOf(id).(*types.Func); ok {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about a pure function taking an argument that is impure or has side effects? Recursively? Also what about methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch regarding pure functions taking impure arguments. Addressed in 1a9134f.

Can you clarify what you mean about methods? Currently we just conservatively assume that all method calls may have side effects and the purity fact for methods is always false.

@ksurent
Copy link
Contributor Author

ksurent commented Nov 22, 2019

So I was thinking about this recently and I realised that this PR confuses terminology quite a bit and does not do quite what it's meant to do.

To elaborate, the original issue says that we shouldn't flag assignments where indexing has side effects. What I think we really want is to stop flagging cases where indexing is non–deterministic.
And just to be clear, this is what I'm referring to:

// Pure and deterministic.
func foo(x int) int { return x + 42 }

// Impure but still deterministic.
func bar(x int) int {
    println(x)
    return x + 42
}

I've built everything around the purity fact, and since pure functions are a subset of deterministic, this will only cover a subset of what we want.
Detecting determinism seems much harder than purity. So perhaps this is still a useful improvement, but probably warrants a clarifying note.

Thoughts?

@dominikh
Copy link
Owner

Purity is the correct attribute to check for, for two reasons:

  • we really do care about purity. If the function has side-effects, we can't really suggest removing the assignment, not unless we also point out its side-effects and how to preserve them.
  • purity is our approximation to what you refer to as deterministic. It's the subset of Go for which we can know that identical arguments to a function result in identical outputs.

On a side-note, your definition of "deterministic" is more restricted than the general definition. Something like a PRNG (math/rand) is also deterministic, it's just that its inputs include state other than function arguments, namely the values stored in struct fields.

@dominikh
Copy link
Owner

dominikh commented Dec 2, 2019

@ksurent I propose the following solution instead: https://github.com/dominikh/go-tools/compare/impure-self-assignment?expand=1

Of note: it correctly handles more complex and nested syntax, such as foo(x)[0] = foo(x)[0] by not flagging it if foo is impure. I've also moved the handling of stubs back into the purity calculation itself. We want the same handling of stubs in this check, that is, x[stub()] = x[stub()] shouldn't get flagged.

@dominikh
Copy link
Owner

Merged as 9774f3b.

@dominikh dominikh closed this Dec 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants