SIP Meeting Minutes - March 12 2020

Language

Minutes

The meeting took place with the following agenda:

  1. Review given instances and context parameters
  2. Review given imports
  3. Extension methods
  4. Export clauses
  5. Review metaprogramming
  6. Review match types

Date and Location

The meeting took place on the 12th March 2020 throughout the day at EPFL in Lausanne, Switzerland, and Zoom.

The meeting wasn’t broadcast.

Minutes were taken by Dale Wijnand.

Committee Attendees

Sitting in

Not present

Miles notified the committee that he wouldn’t be available. Josh, Heather, and Iulian were all unable to participate because of coronavirus-related travel restrictions and disruptions.

Proceedings

Review given instances and context parameters

  • Martin: syntax wise, happy with what we have now
  • Martin likes ?=> instead of using
  • Gui: but using is better for literal (expression level), and then for consistency should be for the type too
  • Seb: could use ?=> at the literal side too, no?
  • Martin: we tried, but using felt more natural; there was pushback

Seb: the features are in good shape

  • Gui: a summary from the implicit threads, kind of things people talked about
  • Gui: on the contributors threads on implicits there’ve been a lot of quesitons like “why do we have to the these set of changes? why are these the correct set of changes?”
  • Gui: in the docs we don’t justify the changes, we don’t have design decisions
  • Martin: that’s because the docs target users
  • Gui: but for the SIP process we should
  • Gui: also users ask “why can’t we just ‘fix’ the existing stuff?”
  • Gui: why instead of a big redesign let’s just, for example, fix mulit-parameter implicit classes?
  • Martin: we need a fresh start that fixes the 6 different aspects systematically
  • Martin: some of the existing problems/bugs are just not fixable
  • Gui: people are uneasy with not knowing how things desugar
  • Martin: I still think this is within the bandwidth of what Scala’s always done
  • Gui: another concern is for anonymous things, the compiler has to come up with a name, should we specify that scheme?
  • Seb: it’s too fragile, for instance if you rename a type, the name changes, or a type parameter name, or whether it’s fully qualified or partially imported
  • Martin: and the names are optimised to be short, and not optimised not to clash
  • Seb: we should highlight that well in the docs: library authors, name your instances (and your method extension given instances)

Review given imports

  • Gui: one inconsistency is that doing a named import of a given is without the given keyword: import A.foo
  • Gui: and IDEs will want to import the most specific thing, so the synthetic name of anonymous instances, particularly extension names
  • Gui/Seb: we could add extension to the import syntax
  • Dale: the previous discussion about libraries always wanting to name their given instances and extensions, most things will have good names
  • Dale: so if IDEs add imports with synthetic names in apps, doesn’t seem to really matter

Extension methods

  • Gui: one difference between infix extension methods and grouped extension methods is that grouped they live in a given instance
  • Martin: people like the extension keyword, when we have it as only given people were confused by what these things were
  • Gui: one big difference with the status quo (Scala 2) of extension methods is you can’t have two sets of type parameters, on the class and on the def, and people aren’t pleased with that
  • Martin: eventually that will go when we have curried type parameters, which isn’t a 3.0 thing
  • Gui: could we add private support to extension methods?
  • Martin: Actually I just tried it, we do allow private

Export clauses

  • Martin: addressing the problem that Scala don’t assist encouraging composition (over inheritance)
  • Martin: side reasons are package object inhertance and exporting enum cases
  • Martin: the feedback is some want it to do more, some want it to do less
  • Martin: I feel good about how it is now, I wouldn’t change any detail on it
  • Adriaan: it would be good to add a type ascription when exporting (export A.T: Foo to only export Foo’s methods)
  • Martin: that wouldn’t be big, we could add that
  • Gui: we could add refinements to the export, to select exactly the method (export A.T: { def foo(x: Int): Int })
  • Martin: or users could just do it with a val val x: Any { def a(x: Int): Int }
  • Adriaan: I’m symapthetic to only allowing to export from static paths, we can always extend it to non static paths
  • Seb: the question is does the restriction buy us anything
  • Martin: importantly the forwarders are final, you can’t overriden them
  • Gui: In TASTy should adding a method be TASTy compatible?
  • Seb: if we consider them implementation details, then no, you defined your API once, adding a method to the exported thing shouldn’t propagate to where you previously exported it
  • Gui: export also “interacts” with visibility
  • Martin: so you can do private export foo._, but in order to you need access to foo at the definition point of the export
  • Gui: but now it’s export foo._ which includes all the package private things in foo
  • Dale: there’s a precedent there with current (term and type) forwarders, but with this you can do lots at once, which aggravates the problem

Review meta programming

(Note: most of the time was spent going over the various feature changes, through the docs.)

Run through https://dotty.epfl.ch/docs/reference/metaprogramming/inline.html

  • Gui: why inline msg: String? Seeing as the semantics match just use msg: => String, just as the syntax, with the current codegen implementation.
  • Gui: inline interacts with overriding
  • Nic: if in a subclass (say Range) you override a method (say foreach) with inline it only inlines if the type is cast
  • Seb: I need both, inline if statically the type is Range, and use the optimised override if it’s a Seq that’s a Range at runtime
  • (After the meeting, this led to scala/scala3#8543 and scala/scala3#8564.)
  • Lukas: inline is perfect for macros, but it shouldn’t exist for performance. The runtime is where performance should be fixed (and it’s in a better position to do it)
  • Lukas: inlining isn’t on by default (in Scala 2) because it interacts with binary compatibility in non-obvious ways, and inline in Dotty does the same

Run through https://dotty.epfl.ch/docs/reference/metaprogramming/macros.html

Run through https://dotty.epfl.ch/docs/reference/metaprogramming/staging.html, which adds a bit on top of the macro framework above, but can be compiled (and executed) at runtime

Run through https://dotty.epfl.ch/docs/reference/metaprogramming/reflection.html

  • Gui: concerned how many compiler implementation details TASTy reflect exposes
  • Gui: should try to reduce it to the minimum of what users care about, for example, opaque types, and maintain backwards compatibility
  • Seb: I think we need to change things and, ultimately, things will have to change, so we can’t ship this with API stability guarantees

Review match types

Review https://github.com/dotty-staging/dotty/blob/fix-6709/docs/docs/reference/new-types/match-types.md (part of https://github.com/scala/scala3/pull/8024)

type LeafElem[X] = X match {
  case String => Char
  case Array[t] => LeafElem[t]
  case Iterable[t] => LeafElem[t]
  case AnyVal => X
}
  • Olivier: The order of match type definitions is significant
  • Olivier: The disjointness is between X and String, not between String and Array
  • Olivier: See https://github.com/scala/scala3/issues/8493 as an example of disjointness requirement (can’t use traits)
  • Martin: Currently the use-cases can be implemented like Generic
  • Olivier: Put at a very high level, the intent is to remove some of the computation that happens in implicits and do it (better) in match types
  • Olivier: another problem is that when you type-check a type you can stackoverflow, which has bad UX, particularly given we have recursive types

Next

The next meeting will be tomorrow, 13 March.