How to determine whether a type parameter is a subtype of a trait?

scala

Solution

This can be achieved with TypeTags (at least 2.10M7):

scala> class Foo; trait Bar
defined class Foo
defined trait Bar

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> def isBar[A <: Foo : TypeTag] = typeOf[A].baseClasses.contains(typeOf[Bar].typeSymbol)
isBar: [A <: Foo](implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean

scala> isBar[Foo]
res43: Boolean = false

scala> isBar[Foo with Bar]
res44: Boolean = true

TypeTags provide a 1:1 translation of Scala types because they represent the types the compiler knows. Therefore they are much more powerful than plain old Manifests:

scala> val fooBar = typeTag[Foo with Bar]
fooBar: reflect.runtime.universe.TypeTag[Foo with Bar] = TypeTag[Foo with Bar]

With the method `tpe` we get full access to Scalas new Reflection:

scala> val tpe = fooBar.tpe // equivalent to typeOf[Foo with Bar]
tpe: reflect.runtime.universe.Type = Foo with Bar

scala> val tpe.<tab><tab> // lot of nice methods here
=:=                 asInstanceOf        asSeenFrom          baseClasses         baseType            contains            declaration         
declarations        erasure             exists              find                foreach             isInstanceOf        kind                
map                 member              members             narrow              normalize           substituteSymbols   substituteTypes     
takesTypeArgs       termSymbol          toString            typeConstructor     typeSymbol          widen  

Problem

Let's say I have the following types ``` class Foo trait Bar ``` Is there a way to make a method which takes in a Type parameter, T, and determine if that T is a Bar? For example, ``` def isBar[T <: Foo: Manifest] = classOf[Bar].isAssignableFrom(manifest[T].erasure) ``` Sadly, `isBar[Foo with Bar]` is `false` because erasure seems to erase mixins. Also, `manifest[Foo with Bar] <:< manifest[Bar]` is false Is this possible at all? I looked at this question: How to tell if a Scala reified type extends a certain parent class? but that answer doesn't work with mixed-in traits as they seem to be erased as evidenced above.

Original source