Scala Programming Language
  1. Scala Programming Language
  2. SI-6149

inferMethodAlternative (and friends) can produce lots of silent errors that call expensive string ops

    Details

      Description

      Revealed by Tiark for Scala virtualized but the mechanism for filtering-out alternatives has been doing that for some time now in standard scala (also 2.9.x).
      They have to deal with lots of overloaded methods that contain non-trivial types. In order to emit error, which only purpose is basically to say that an alternative is invalid, we call applyErrorMsg that can be expensive for those types.

      We need to make error message generation lazy but this is not trivial because the context could be different and hence the message might be inconsistent later.

        Activity

        Hide
        Hubert Plociniczak added a comment - - edited

        This is actually worse than I thought:

        object ImplicitAmbiguity {
        
          class N[T]
          class NC[T] extends N[T]
          class ND[T] extends N[T]
          class NE[T] extends N[T]
          class NF[T] extends N[T]
        
          class AA[A]
          class BB[A]
        
          class Foo
        
          implicit def conv1(i: Float) = new NC[Float]
          implicit def conv2(i: Float) = new NF[Float]
          implicit def conv3(op: AA[String]) = new N[String]
          implicit def conv4(op: AA[Float]) = new N[Float]
          implicit def conv5(op: AA[Foo]) = new N[Foo]
        
          implicit def conv6(e: BB[String]) = new N[String]
        
          def aFunc[A](a: NC[A]) = new AA[A]
        
          def aFunc[A](a: NF[A]) = new AA[Float]
        
          def aFunc[A](a: ND[A]) = new BB[A]
        
          def aFunc[A](a: NE[A]) = new BB[A]
        
          def bFunc[T](e1: N[T]) = {}
          
          // OK
          def bar02 {
            bFunc(aFunc(4F))
          }
        }
        

        -Ydebug will reveal that we do that all the time, even when the code compiles.

        [running phase namer on longerrormsg.scala]
        [running phase packageobjects on longerrormsg.scala]
        [running phase typer on longerrormsg.scala]
        warning: issue error: type mismatch;
         found   : ImplicitAmbiguity.this.AA[?A]
         required: ImplicitAmbiguity.this.N[?]
        Note that implicit conversions are not applicable because they are ambiguous:
         both method conv3 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[String])ImplicitAmbiguity.this.N[String]
         and method conv5 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[ImplicitAmbiguity.this.Foo])ImplicitAmbiguity.this.N[ImplicitAmbiguity.this.Foo]
         are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?]
        warning: issue error: type mismatch;
         found   : ImplicitAmbiguity.this.AA[?A]
         required: ImplicitAmbiguity.this.N[?]
        Note that implicit conversions are not applicable because they are ambiguous:
         both method conv3 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[String])<empty>.this.ImplicitAmbiguity.N[String]
         and method conv4 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[scala.this.Float])<empty>.this.ImplicitAmbiguity.N[scala.this.Float]
         are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?]
        warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError, scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError)
        warning: issue error: overloaded method value aFunc with alternatives:
          [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NE[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.BB[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)] <and>
          [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.ND[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.BB[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)] <and>
          [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NF[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.AA[scala.this.Float] <and>
          [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NC[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.AA[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)]
         cannot be applied to (scala.this.Float)
        warning: issue error: type mismatch;
         found   : ImplicitAmbiguity.this.AA[?A]
         required: ImplicitAmbiguity.this.N[?]
        Note that implicit conversions are not applicable because they are ambiguous:
         both method conv3 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[String])ImplicitAmbiguity.this.N[String]
         and method conv5 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[ImplicitAmbiguity.this.Foo])ImplicitAmbiguity.this.N[ImplicitAmbiguity.this.Foo]
         are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?]
        warning: issue error: type mismatch;
         found   : ImplicitAmbiguity.this.AA[?A]
         required: ImplicitAmbiguity.this.N[?]
        Note that implicit conversions are not applicable because they are ambiguous:
         both method conv3 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[String])<empty>.this.ImplicitAmbiguity.N[String]
         and method conv4 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[scala.this.Float])<empty>.this.ImplicitAmbiguity.N[scala.this.Float]
         are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?]
        warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError, scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError)
        [running phase patmat on longerrormsg.scala]
        [running phase superaccessors on longerrormsg.scala]
        [running phase extmethods on longerrormsg.scala]
        

        This could be a performance killer with all those strings created along the way.

        Show
        Hubert Plociniczak added a comment - - edited This is actually worse than I thought: object ImplicitAmbiguity { class N[T] class NC[T] extends N[T] class ND[T] extends N[T] class NE[T] extends N[T] class NF[T] extends N[T] class AA[A] class BB[A] class Foo implicit def conv1(i: Float) = new NC[Float] implicit def conv2(i: Float) = new NF[Float] implicit def conv3(op: AA[String]) = new N[String] implicit def conv4(op: AA[Float]) = new N[Float] implicit def conv5(op: AA[Foo]) = new N[Foo] implicit def conv6(e: BB[String]) = new N[String] def aFunc[A](a: NC[A]) = new AA[A] def aFunc[A](a: NF[A]) = new AA[Float] def aFunc[A](a: ND[A]) = new BB[A] def aFunc[A](a: NE[A]) = new BB[A] def bFunc[T](e1: N[T]) = {} // OK def bar02 { bFunc(aFunc(4F)) } } -Ydebug will reveal that we do that all the time, even when the code compiles. [running phase namer on longerrormsg.scala] [running phase packageobjects on longerrormsg.scala] [running phase typer on longerrormsg.scala] warning: issue error: type mismatch; found : ImplicitAmbiguity.this.AA[?A] required: ImplicitAmbiguity.this.N[?] Note that implicit conversions are not applicable because they are ambiguous: both method conv3 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[String])ImplicitAmbiguity.this.N[String] and method conv5 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[ImplicitAmbiguity.this.Foo])ImplicitAmbiguity.this.N[ImplicitAmbiguity.this.Foo] are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?] warning: issue error: type mismatch; found : ImplicitAmbiguity.this.AA[?A] required: ImplicitAmbiguity.this.N[?] Note that implicit conversions are not applicable because they are ambiguous: both method conv3 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[String])<empty>.this.ImplicitAmbiguity.N[String] and method conv4 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[scala.this.Float])<empty>.this.ImplicitAmbiguity.N[scala.this.Float] are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?] warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError, scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError) warning: issue error: overloaded method value aFunc with alternatives: [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NE[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.BB[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)] <and> [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.ND[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.BB[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)] <and> [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NF[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.AA[scala.this.Float] <and> [A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)](<param> a: ImplicitAmbiguity.this.NC[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)])ImplicitAmbiguity.this.AA[A(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)(in method aFunc)] cannot be applied to (scala.this.Float) warning: issue error: type mismatch; found : ImplicitAmbiguity.this.AA[?A] required: ImplicitAmbiguity.this.N[?] Note that implicit conversions are not applicable because they are ambiguous: both method conv3 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[String])ImplicitAmbiguity.this.N[String] and method conv5 in module class ImplicitAmbiguity of type (<param> op: ImplicitAmbiguity.this.AA[ImplicitAmbiguity.this.Foo])ImplicitAmbiguity.this.N[ImplicitAmbiguity.this.Foo] are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?] warning: issue error: type mismatch; found : ImplicitAmbiguity.this.AA[?A] required: ImplicitAmbiguity.this.N[?] Note that implicit conversions are not applicable because they are ambiguous: both method conv3 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[String])<empty>.this.ImplicitAmbiguity.N[String] and method conv4 in module class ImplicitAmbiguity of type (<param> op: <empty>.this.ImplicitAmbiguity.AA[scala.this.Float])<empty>.this.ImplicitAmbiguity.N[scala.this.Float] are possible conversion functions from ImplicitAmbiguity.this.AA[?A] to ImplicitAmbiguity.this.N[?] warning: update buffer: Set(scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError, scala.tools.nsc.typechecker.ContextErrors$AmbiguousTypeError) [running phase patmat on longerrormsg.scala] [running phase superaccessors on longerrormsg.scala] [running phase extmethods on longerrormsg.scala] This could be a performance killer with all those strings created along the way.
        Hide
        Tiark Rompf added a comment -
        Show
        Tiark Rompf added a comment - Here's my temporary fix to Scala-Virtualized: https://github.com/namin/scala/commit/32c2a70db7da413c17987a0bd9545d1481e1e392
        Hide
        Adriaan Moors added a comment -

        Un-assigning to foster work stealing, as announced in https://groups.google.com/forum/?fromgroups=#!topic/scala-internals/o8WG4plpNkw

        Show
        Adriaan Moors added a comment - Un-assigning to foster work stealing, as announced in https://groups.google.com/forum/?fromgroups=#!topic/scala-internals/o8WG4plpNkw
        Hide
        Grzegorz Kossakowski added a comment -

        Unassigning and rescheduling to M7 as previous deadline was missed.

        Show
        Grzegorz Kossakowski added a comment - Unassigning and rescheduling to M7 as previous deadline was missed.
        Hide
        Adriaan Moors added a comment -

        Since 2.11.0-RC1 is one week away, pushing all non-blockers without PR to 2.11.1-RC1. Please undo the change if I missed work in progress.

        Show
        Adriaan Moors added a comment - Since 2.11.0-RC1 is one week away, pushing all non-blockers without PR to 2.11.1-RC1. Please undo the change if I missed work in progress.

          People

          • Assignee:
            Jason Zaugg
            Reporter:
            Hubert Plociniczak
          • Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:

              Development