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

spurious unchecked warning when an abstract type is accompanied by a same-named extractor

    Details

      Description

      This pattern is used in scala.reflect._. I haven't managed to produce a standalone reproduction.

      $ ./build/quick/bin/scala -unchecked
      Welcome to Scala version 2.10.0-M1-0362-g2fe570291a-2012-02-18 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
      
      scala> import reflect.mirror._
      import reflect.mirror._
      
      scala> object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }} 
      <console>:13: warning: abstract type reflect.mirror.MethodType in type pattern reflect.mirror.MethodType is unchecked since it is eliminated by erasure
             object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }}
      
      

      Inspection of the generated code shows that the extractor is being used.

                                                                        ^
      defined module A
      
      scala> :javap -v ACompiled from "<console>"
      ...
      public int foo(scala.reflect.api.Trees$Tree);
        Code:
         Stack=3, Locals=3, Args_size=2
         0:	aload_1
         1:	invokevirtual	#21; //Method scala/reflect/api/Trees$Tree.tpe:()Lscala/reflect/api/Types$AbsType;
         4:	astore_2
         5:	aload_2
         6:	instanceof	#23; //class scala/reflect/api/Types$AbsType
         9:	ifeq	38
         12:	getstatic	#28; //Field scala/reflect/package$.MODULE$:Lscala/reflect/package$;
         15:	invokevirtual	#32; //Method scala/reflect/package$.mirror:()Lscala/reflect/api/Mirror;
         18:	checkcast	#34; //class scala/reflect/api/Types
         21:	invokeinterface	#38,  1; //InterfaceMethod scala/reflect/api/Types.MethodType:()Lscala/reflect/api/Types$MethodTypeExtractor;
         26:	aload_2
         27:	invokevirtual	#44; //Method scala/reflect/api/Types$MethodTypeExtractor.unapply:(Lscala/reflect/api/Types$AbsType;)Lscala/Option;
         30:	invokevirtual	#50; //Method scala/Option.isEmpty:()Z
         33:	ifne	38
         36:	iconst_0
         37:	ireturn
         38:	new	#52; //class scala/MatchError
         41:	dup
         42:	aload_2
         43:	invokespecial	#55; //Method scala/MatchError."<init>":(Ljava/lang/Object;)V
         46:	athrow
        LineNumberTable: 
         line 13: 0
      ...
      

        Issue Links

          Activity

          Hide
          Jason Zaugg added a comment -

          Actually, the warning might make sense.

          This gives the same warning (although I'm not certain it's a faithful minimization of the one above).

          trait A {  
            type MethodType
            
            val MethodType: MethodTypeExtractor = null
          
            abstract class MethodTypeExtractor {    
              def unapply(tpe: MethodType): Option[(Any, Any)]
            }
          }
          
          object Test {  
            val a: A = null
          
            def foo(tpe: A#MethodType) = tpe match {
              case a.MethodType(_, _) =>
            }
          }
          

          Switching to def unapply(tpe: MethodType), or to def foo(tpe: a.MethodType) silences the warning.

          Show
          Jason Zaugg added a comment - Actually, the warning might make sense. This gives the same warning (although I'm not certain it's a faithful minimization of the one above). trait A { type MethodType val MethodType: MethodTypeExtractor = null abstract class MethodTypeExtractor { def unapply(tpe: MethodType): Option[(Any, Any)] } } object Test { val a: A = null def foo(tpe: A#MethodType) = tpe match { case a.MethodType(_, _) => } } Switching to def unapply(tpe: MethodType) , or to def foo(tpe: a.MethodType) silences the warning.
          Hide
          Jason Zaugg added a comment - - edited

          Okay, I think that this is a more accurate minimization:

          trait A {  
            type Type
            type MethodType <: Type
            
            val MethodType: MethodTypeExtractor = null
          
            abstract class MethodTypeExtractor {    
              def unapply(tpe: MethodType): Option[(Any, Any)]
            }
          }
          
          object Test {  
            val a: A = null
          
            def foo(tpe: a.Type) = tpe match {
              case a.MethodType(_, _) =>
            }
          }
          

          Who is at fault: compiler or library?

          Show
          Jason Zaugg added a comment - - edited Okay, I think that this is a more accurate minimization: trait A { type Type type MethodType <: Type val MethodType: MethodTypeExtractor = null abstract class MethodTypeExtractor { def unapply(tpe: MethodType): Option[(Any, Any)] } } object Test { val a: A = null def foo(tpe: a.Type) = tpe match { case a.MethodType(_, _) => } } Who is at fault: compiler or library?
          Hide
          Adriaan Moors added a comment -

          Blame the old pattern matcher. I know, I know, it's getting old, but virtpatmat will fix this.
          See https://github.com/scala/scala/commit/5cc3dad991, SI-1697, and SI-2337.

          Show
          Adriaan Moors added a comment - Blame the old pattern matcher. I know, I know, it's getting old, but virtpatmat will fix this. See https://github.com/scala/scala/commit/5cc3dad991 , SI-1697 , and SI-2337 .
          Hide
          Jason Zaugg added a comment -

          So old, in fact, that is was among my first thoughts. Alas:

          ./build/quick/bin/scala -Yvirtpatmat -unchecked
          Welcome to Scala version 2.10.0-M1-0374-g526c92848a-2012-02-19 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
          Type in expressions to have them evaluated.
          Type :help for more information.
          
          scala> import reflect.mirror._import reflect.mirror._
          
          scala> object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }} 
          <console>:10: warning: abstract type reflect.mirror.MethodType in type pattern reflect.mirror.MethodType is unchecked since it is eliminated by erasure
                 object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }} 
                                                                            ^
          defined module A
          
          scala> :paste
          // Entering paste mode (ctrl-D to finish)
          
          trait A {  
            type Type
            type MethodType <: Type
            
            val MethodType: MethodTypeExtractor = null
          
            abstract class MethodTypeExtractor {    
              def unapply(tpe: MethodType): Option[(Any, Any)]
            }
          }
          
          object Test {  
            val a: A = null
          
            def foo(tpe: a.Type) = tpe match {
              case a.MethodType(_, _) =>
            }
          }
          
          // Exiting paste mode, now interpreting.
          
          <console>:25: warning: abstract type Test.a.MethodType in type pattern Test.a.MethodType is unchecked since it is eliminated by erasure
                     case a.MethodType(_, _) =>
                                      ^
          
          Show
          Jason Zaugg added a comment - So old, in fact, that is was among my first thoughts. Alas: ./build/quick/bin/scala -Yvirtpatmat -unchecked Welcome to Scala version 2.10.0-M1-0374-g526c92848a-2012-02-19 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29). Type in expressions to have them evaluated. Type :help for more information. scala> import reflect.mirror._import reflect.mirror._ scala> object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }} <console>:10: warning: abstract type reflect.mirror.MethodType in type pattern reflect.mirror.MethodType is unchecked since it is eliminated by erasure object A { def foo(t: Tree) = t.tpe match { case MethodType(_, _) => 0 }} ^ defined module A scala> :paste // Entering paste mode (ctrl-D to finish) trait A { type Type type MethodType <: Type val MethodType: MethodTypeExtractor = null abstract class MethodTypeExtractor { def unapply(tpe: MethodType): Option[(Any, Any)] } } object Test { val a: A = null def foo(tpe: a.Type) = tpe match { case a.MethodType(_, _) => } } // Exiting paste mode, now interpreting. <console>:25: warning: abstract type Test.a.MethodType in type pattern Test.a.MethodType is unchecked since it is eliminated by erasure case a.MethodType(_, _) => ^
          Hide
          Seth Tisue added a comment -

          related to SI-5542?

          Show
          Seth Tisue added a comment - related to SI-5542 ?
          Hide
          Adriaan Moors added a comment -

          no, this is a different problem
          one aspect was that bridges needed to become more defensive, which has been done
          the other problem, I think, is that the extractor's argument is an abstract type, which cannot be checked at all
          there will be a new feature in the pattern matcher that allows real type test when a Typeable/TypeTag/Manifest is available

          Show
          Adriaan Moors added a comment - no, this is a different problem one aspect was that bridges needed to become more defensive, which has been done the other problem, I think, is that the extractor's argument is an abstract type, which cannot be checked at all there will be a new feature in the pattern matcher that allows real type test when a Typeable/TypeTag/Manifest is available
          Hide
          Jason Zaugg added a comment -

          Yeah, I agree that the extractors should be changed to take an argument of type Any, rather than the abstract type.

          Show
          Jason Zaugg added a comment - Yeah, I agree that the extractors should be changed to take an argument of type Any, rather than the abstract type.

            People

            • Assignee:
              Adriaan Moors
              Reporter:
              Jason Zaugg
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development