Wildcard imports considered harmful

#22

The proposal is at least to put it behind a language feature flag. This is especially important in Scala (compared to Java) because of implicits. How do we jump-to-definition with something that is not even visible ?

#23

To clarify, would you be proposing blocking this syntax as well?

val x = Foo()
import x._
#24

I had not thought of it. Do you have a case where it would be a problem ? First that comes to mind is that it would not be simple for IDEs to auto-generate imports anywhere but at the top-level.

#25

One place which this is used that comes to mind is if you want to limit the scope of implicits like:

import org.json4s.dsl._

Which, IIRC, is importing the members of an object, which is equivalent to the above.

Oh, and Akka’s graph building DSL also relies on a similar mechanism.

Clarifying note on the motivation for this line of questioning: I’m deeply opposed to this proposal, but I’d also like to avoid ripping into a strawman, so I want to make sure I understand the details of what you’re proposing

1 Like
#26

If you don’t know where it was from at all, not even which library, then you downgrade (by switching to an earlier branch that compiled) and

  1. If you have an IDE, ask the IDE
  2. if not, drop : Nothing on an instance of it and recompile

Now you know where it’s from and you can go search the API to try to find where it went.

If you do know where it was from, just go search the new API docs like you’d have had to if it said error: object Thing is not a member of package boromir.

This elaborate scenario has a simple solution.

Personally, I’ve run into “here’s sample code but it doesn’t work because they elided the imports because they’re too long” as an error way more than “this worked great, but after an upgrade things went missing and you can’t find where they used to come from and that is critical to solving the problem”.

Anyway, anyone who wants to is already free to not import everything from each member of the Fellowship of the Ring. If you’re just after Sting, a frying pan, and a horn, Scala certainly doesn’t stop you from calling them out specifically.

4 Likes
#27

Seriously: I believe that the majority of Scala files I have worked in (11 years, 7 of them full-time) have involved at least one wildcard import. That’s not the kind of specialized feature that is well-suited to a language feature flag…

4 Likes
#28

When macros are in the mix, wildcard imports can’t be reliably expanded at all by tooling.

1 Like
#29

The idea is to take advantage of the shift to Dotty to introduce this breaking change. It is mainly in reaction to implied/delegate/given imports, which also introduce a breaking change. A new proposal could be to require givens to be “non-wildcardly imported” : assume there is a field myimplicit in package foo. Then,

import foo._
import given foo._

should be written instead as:

import foo.{_, myimplicit}

What do you think ?

#30

I think it’s a really good way to raise the effort of migration enough to keep people on Scala 2. At least based on what I understand from what’s been described here, it’d be a deal-breaker for me.

3 Likes
#31

To be fair, the idea that advancing a major version is now the opportunity to change everything did not originate from @rjolly. My understanding is that we should all stop worrying and love ScalaFix.

I get that wildcard imports are far too popular to be killed. But if this conversation will convince a few people to use them less, it was worth it talking about it.

It was implied earlier that implicits may not have a name, so they cannot be imported by name, and maybe that means we need to always import them via wildcards. That sounds pretty terrible to me - what if there are conflicts among some of the imported unnamed implicits. There must be a way to refer to them individually in imports. My understanding is that they do not need a name, because we can refer to them by the name of their type. In that case, we need a way to import an implicit by naming their type. Maybe by putting the type name in square brackets? Like:

**import x.y.z.{Thing, [NiceType]} **

// imports x.y.x.Thing and the implicit instance in x.y.z that has type NiceType.

1 Like
#32

By-type imports are already implemented, see https://dotty.epfl.ch/docs/reference/contextual/import-delegate.html . I thought it was overly complicated, but maybe it is the way to go. The part that bothers me is when used in normal imports (non implied/delegate/given):

import foo.{_: MyType}

It makes sense for fields and objects, but what about methods ? And types ? And classes ?

#33

If you prefer not using IDE, just do not use it. If you prefer not using wildcard, just do not use it.

I don’t see why we need to take this away from users and enforce some’s preference to everyone.

3 Likes