1

According to this question and the scala language spec, it's possible to exclude imports by using the syntax e.g. import java.{xxx => _, _}.

However, I'm finding that this doesn't work for implicits. For example:

Welcome to Scala 2.12.4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.

scala> import schema.Encoder.{ofGeneric => _, _}
import schema.Encoder.{ofGeneric=>_, _}

As per the spec, the member is not accessible:

scala> ofGeneric
<console>:15: error: not found: value ofGeneric
       ofGeneric
       ^

However, it is in implicit scope, and I can access it implicitly:

scala> :implicits
/* 10 implicit members imported from schema.Encoder */
  /* 10 defined in schema.Encoder */
  implicit val ofBoolean: Boolean]
  implicit def ofConcreteElem[K <: Symbol, A](implicit witness: shapeless.Witness.Aux[K],i
mplicit E: A]): shapeless.labelled.FieldType[K,A]]
  implicit val ofDateTime: java.time.OffsetDateTime]
  implicit val ofDouble: Double]
  implicit def ofElem[K <: Symbol, A, C[_]](implicit witness: shapeless.Witness.Aux[K],imp
licit E: shapeless.Lazy[A]],implicit C: cats.Foldable[C]): shapeless.labelled.FieldType[K,
C[A]]]
  implicit def ofGeneric[A, L <: shapeless.HList](implicit G: shapeless.LabelledGeneric.Au
x[A,L],implicit HE: shapeless.Lazy[L]]): A]
  implicit def ofHListSeq[K <: Symbol, H, T <: shapeless.HList](implicit witness: shapeles
s.Witness.Aux[K],implicit HE: shapeless.Lazy[shapeless.labelled.FieldType[K,H]]],implicit
TE: shapeless.Lazy[T]]): shapeless.labelled.FieldType[K,H] :: T]
  implicit val ofHNil: shapeless.HNil]
  implicit val ofInt: Int]
  implicit def ofString: String]

scala> implicitly[schema.Encoder[Tuple2[Int,String]]]
res3: schema.Encoder[(Int, String)] = schema.Encoder$$anonfun$ofGeneric$2@341619cc
                                                              ^^^^^^^^^

Questions:

  1. Is this a bug in the console, or a language feature?
  2. Is there any way to get around this (i.e. import all implicit members except one), without specifying each function individually?
Luciano
  • 2,388
  • 1
  • 22
  • 33

2 Answers2

1

From the spec:

The actual arguments that are eligible to be passed to an implicit parameter of type TT fall into two categories. First, eligible are all identifiers xx that can be accessed at the point of the method call ... If there are no eligible identifiers under this rule, then, second, eligible are also all implicit members of some object that belongs to the implicit scope of the implicit parameter's type, TT.

The implicit scope of a type TT consists of all companion modules of classes that are associated with the implicit parameter's type.

So, what this is saying is that it will look for implicits in the companion object once it's tried looking in the local scope.

Indeed this can be seen by calling the implicitly[...] expression above without importing anything first; it just works, because those methods are part of the companion.

According to the above quote, this should mean that if I create and/or import an implicit into scope with the same signature as those in the companion object, they will take precedence, thus removing the need to 'exclude the implicit export' as in my original question.

Luciano
  • 2,388
  • 1
  • 22
  • 33
0

Not sure about the first question, but a workaround is to define a non-implicit member with the same name in your scope.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487