elixir icon indicating copy to clipboard operation
elixir copied to clipboard

Remove ambiguity in nullary remote calls with unknown targets

Open josevalim opened this issue 6 years ago • 11 comments

  • [x] Deprecate map.foo() in favor of map.foo
  • [x] Deprecate mod.foo in favor of mod.foo()
  • [ ] Change the AST so remote calls (A.b, a.b, etc) without parens has nil third element. Once we do so, remove :no_parens metadata usage throughout the codebase (perhaps behind the --future flag)

PS: originally this issue was about deprecating all nullary remote calls without parens, but it has been restricted since then. See this comment for more info.

josevalim avatar Nov 08 '19 17:11 josevalim

What about typespecs of arity 0?

eksperimental avatar Nov 10 '19 13:11 eksperimental

@eksperimental we probably won't touch typespecs for two reasons:

  1. of all of the examples above, it is the most common, which means potentially hundreds of warnings in a project

  2. it can't be fully automated, which doesn't help with 1

josevalim avatar Nov 11 '19 09:11 josevalim

Is this open for contribution? Because I would love to work on that :)

esse avatar Nov 20 '19 10:11 esse

Hi @esse, not yet. Note it is tagged for v1.11 and we are still working on v1.10.

josevalim avatar Nov 20 '19 11:11 josevalim

Folks, I will go ahead and revert the changes to the pipe operator. I have been running them for the last 40 days and I have to be honest that every time I saw the warning a part of me died a bit. :)

There is nothing ambiguous on |> Foo.bar, so it makes no sense to push users to use parens. That's opposite to an unqualified bar without parens, which was ambiguous and it required revisiting the context.

Therefore, we will only apply these rules where ambiguity exists: map.foo() and mod.foo. We will likely start emitting a warning for map.foo() first and a warnings for mod.foo later.

EDIT: I have updated the original description to track only the changes we will effectively do.

josevalim avatar Mar 12 '20 11:03 josevalim

On v1.11 we will add this as a compile-time warning whenever we can infer it. So I will postpone this to v1.12 or maybe even v1.13.

josevalim avatar Jun 30 '20 09:06 josevalim

Hey. Just wanted to loop back on this issues since it's been up since 2019 and was last slated to be addressed in v1.13. We're at v1.15.5 now and no warning is emitted for code like this:

fun = fn -> IO.puts "Hey there" end
[%{ack_fn: fun}] |> Stream.each(& &1.ack_fn()) |> ... |> Enum.to_list()

That's a simplified version of what we had in our product's codebase until recently. Because of the missing . in &1.ack_fn(), the ack function wasn't getting called as it was supposed to.

alco avatar Aug 31 '23 09:08 alco

PRs are welcome! :)

josevalim avatar Aug 31 '23 09:08 josevalim

I would like to take a look at this, but I think I'm not familiar enough with the context? Would it be possible to add a bit more of context on some code samples we should warn and others that where we shouldn't?

For example, for the case above it's not clear to me what would be the criteria for warning, as the type should be unknown and &1 could be a module, making it a valid call

viniciusmuller avatar Sep 07 '23 12:09 viniciusmuller

I'm thinking it could be a warning saying something to the tune of "Unable to determine the type of &1. If it is a module, use apply(&1, :ack_fn, []). If it is a map, use &1.ack_fn.()"

alco avatar Sep 17 '23 15:09 alco

Sorry, I dropped the ball on these comments, but the deprecation is now on main.

josevalim avatar Oct 30 '23 20:10 josevalim