- 
  Notifications
 You must be signed in to change notification settings 
- Fork 1.1k
 
 Lint or deprecate auto-tupling (like Scala 2's -Xlint:adapted-args)
 
 #19255
 
 -
Equivalent of Scala 2. E.g. Some(1,2) should warn about adapted args.
Beta Was this translation helpful? Give feedback.
All reactions
- 
 ❤️ 3
Replies: 8 comments 8 replies
-
This would fit in well with the effort being made in Scala 3.4 to begin phasing out legacy language features.
One past discussion in this area: https://contributors.scala-lang.org/t/lets-drop-auto-tupling/1799
Another: #4311
The Scala 2 ticket is scala/bug#3583 , where I suggested that we deprecate instead of merely offering a lint. If Scala 3 deprecates, I believe we would follow suit and deprecate in Scala 2 as well under -Xsource:3.
Beta Was this translation helpful? Give feedback.
All reactions
-
Note https://contributors.scala-lang.org/t/lets-drop-auto-tupling/1799/9
[It] would be a shame to lose what is effectively our only tool for safe mixed-typed variadics. It seems like if autotupling is going to mostly go away, it’d be nice to get some way to get it back via a request at the definition site.
The trio of generics, autotupling, and typeclasses allow you to actually write safe arity-generic methods (within any relevant tuple size limits).
It would be nice to make autotupling an opt-in behavior for some intentional functions, unless this is already possible in Scala 3 otherwise. In the thread I'm calling the opt-in as
def foo[A: ParamList](params: A): Unit = ???
Beta Was this translation helpful? Give feedback.
All reactions
-
If it was a warning, it could be opted in to with @nowarn, I think?
Beta Was this translation helpful? Give feedback.
All reactions
-
If it was a warning, it could be opted in to with
@nowarn, I think?
As long as it can be done at the definition and not the call-sites, as that'd be a lot of noise. Mayyybe with Wconf.
Beta Was this translation helpful? Give feedback.
All reactions
-
@nicolasstucki Did this come up at all when you were doing your inventory recently?
Beta Was this translation helpful? Give feedback.
All reactions
-
No. I will add it to the list in https://github.com/orgs/lampepfl/projects/2/views/11
Beta Was this translation helpful? Give feedback.
All reactions
- 
 ❤️ 1
-
It's more tricky than just dropping auto-tupling. We'll have to start with this:
val buf: ListBuffer[Int] = ??? val buf += (1, 2)
This needs to be declared illegal first. The general rule will be that infix operators no longer take vararg arguments.
Why? Because auto-tupling is necessary to make this work in the current rules:
val xs: List[(Int, Int)] = ??? (1, 2) :: xs xs :+ (1, 2)
If we drop auto-tupling, this would no longer work, which would be upsetting. So we have to start with the infix varargs. buf += (1, 2) needs to be illegal. Right now it's a deprecation warning:
sc ../new/test.scala -deprecation -- Deprecation Warning: ../new/test.scala:15:12 -------------------------------- 15 |val _ = buf += (1, 2) | ^^^^^^ |method += in trait Growable is deprecated since 2.13.0: Use `++=` aka `addAll` instead of varargs `+=`; infix operations with an operand of multiple args will be deprecated
What we need to do:
- Warn on the compiler side that (1) infix operator definitions cannot take vararg parameters, (2) infix operator calls cannot take vararg arguments. These should give deprecation warnings in the next version.
- Make these things illegal in a version after that, which would mean that a tuple passed to such an infix operator is treated as a tuple.
- Drop auto-tupling.
It's a long road. We better start quickly. Who can do the first step (deprecation)?
Beta Was this translation helpful? Give feedback.
All reactions
-
I also want to clearly state that we should not waste our time linting this, like we did in Scala 2. Doing a lint here is a half-baked solution that creates language dialects.
EDIT: Sorry, we do already have a lint in place. It's a language import: import language.noAutoTupling. Here's the doc comment:
/** Where imported, auto-tupling is disabled. * * '''Why control the feature?''' Auto-tupling can lead to confusing and * brittle code in presence of overloads. In particular, surprising overloads * can be selected, and adding new overloads can change which overload is selected * in suprising ways. * * '''Why allow it?''' Not allowing auto-tupling is difficult to reconcile with * operators accepting tuples. */ @compileTimeOnly("`noAutoTupling` can only be used at compile time in import statements") object noAutoTupling
So, yes, to make progress, and make the import redundant, we have to follow the steps I outlined above.
Beta Was this translation helpful? Give feedback.
All reactions
-
The discussion about "will they or won't they?" goes back to 2018 when the API was deprecated: "Scala 3.0 will probably drop support for infix operators with multiple parameters." (szeiger) So it's already been a long road trip.
Scala 2's best effort is to lint both, -Xlint:multiarg-infix. The "warts" are close siblings.
The advantage of a lint is that you get to hear feedback about how it messes with someone's DSL.
which would be upsetting
... for some definition of "liberating".
Beta Was this translation helpful? Give feedback.
All reactions
-
OK, thanks to @odersky for pointing out import language.noAutoTupling which is effectively the same lint as in Scala 2. Does anyone know how to import it for a whole project? I don't recall having to do that in a Scala project before.
Beta Was this translation helpful? Give feedback.
All reactions
-
➜ ~ scala -language:noAutoTupling
Welcome to Scala 3.3.1 (21, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
scala> Some(42,27)
-- Error: --------------------------------------------------------------------------------------------------------------
1 |Some(42,27)
 | ^^
 | too many arguments for method apply in object Some: (value: A): Some[A]
1 error found
Another trick for the feature implicits is just to stick your own implicit definition somewhere, such as a package or a custom predef for -Yimports.
Beta Was this translation helpful? Give feedback.
All reactions
- 
 🎉 1
-
Except that it has no feature trait and:
scala> { given scala.language.noAutoTupling.type = scala.language.noAutoTupling; Some(42,27) }
-- Error: --------------------------------------------------------------------------------------------------------------
1 |{ given scala.language.noAutoTupling.type = scala.language.noAutoTupling; Some(42,27) }
 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 | `noAutoTupling` can only be used at compile time in import statements
1 error found
export also doesn't work...
Beta Was this translation helpful? Give feedback.
All reactions
- 
 👍 1
-
Awesome, thank you. Looks like we already have effectively the Scala 2 lint for project-wide use.
Beta Was this translation helpful? Give feedback.
All reactions
-
At scala/scala#10857 (comment) I noticed the lint doesn't warn for infix tupling:
➜ ~ scala -Xlint:adapted-args
Welcome to Scala 2.13.15 (OpenJDK 64-Bit Server VM, Java 23).
Type in expressions for evaluation. Or try :help.
scala> def f[A](x: A) = x
def f[A](x: A): A
scala> f(1,2,3)
 ^
 warning: adapted the argument list to the expected 3-tuple: add additional parens instead
 signature: f[A](x: A): A
 given arguments: 1, 2, 3
 after adaptation: f((1, 2, 3): (Int, Int, Int)) [quickfixable]
val res0: (Int, Int, Int) = (1,2,3)
scala> object X { def f[A](x: A) = x.getClass }
object X
scala> X f (1,2,3)
val res1: Class[_ <: (Int, Int, Int)] = class scala.Tuple3
scala>
I was reviewing the behavior because I wondered why I had a nowarn on a tuple:
importInfos(ctx.unit) ::= (info, keyword, ctx.owner) : @nowarn
So in that PR, I demote -Xlint:multiarg-infix to -Wmultiarg-infix.
Not only am I reconciled to the current behavior, I hope it does not change. I don't use "multiarg infix", but somebody does.
I would propose that the desired feature is not auto-tupling but auto-untupling: if applying infix tuple doesn't work, only then consider multiarg infix. (The opposite of current priority.) That is in the spirit of parameter untupling: "don't hassle me with arity boilerplate".
Beta Was this translation helpful? Give feedback.
All reactions
-
Just wanted to point out that autotupling is currently essential for libraries like @armanbilge's Calico - I guess it'd still be fine if autotupling were to be made illegal, but it'd surely become less convenient. Mayybe the DSL can be reworked to still work without autotupling too...
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks for the ping. It looks like #19255 (reply in thread) captures the Calico usecase.
Beta Was this translation helpful? Give feedback.