`def toOption(name: String): Option[name.type]= Some(name)`を、`toOption("hoge").get`で呼び出せない



# 環境
* IntelliJ IDEA Community 2018.1
* Scala 2.12.5
    * sbt 1.1.3
    * ScalaTest 3.0.5

```sbt:build.sbt
# build.sbtの一部
scalaVersion := "2.12.5"
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.5"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"
```

# やりたいこと
以下のメソッドに対応するテストコードを、ScalaTestで書きたいです。

```scala:Sample.scala
object Sample {

  def toOption(name: String): Option[name.type] = {
    println("toOption is called.")
    Some(name)
  }

  def toOption2(name: String): Option[String] = {
    println("toOption is called.")
    Some(name)
  }
}
```

`toOption`と`toOption2`の違いは、戻り値の型です。
`toOption`の戻り値の型は、「引数の型と同じ型パラメータを持つOption型」という意味を表すため、`Option[name.type]`にしています。


テストコードは、以下の通りです。

```scala:SampleTest.scala
import org.scalatest.FreeSpec
import org.scalatest.Matchers._

class SampleTest extends FreeSpec {

  "toOption Test" in {
    println("[toOption Test]")
    Sample.toOption("hoge") shouldBe Some("hoge")
    Sample.toOption("hoge").get shouldBe "hoge" // toOption IS NOT CALLED
  }

  "toOption2 Test" in {
    println("[toOption2 Test]")
    Sample.toOption2("hoge") shouldBe Some("hoge") 
    Sample.toOption2("hoge").get shouldBe "hoge"
  }
}

```


# 問題
上記のテストコードを実行すると、コンソールには以下の内容が出力されます。

```
[toOption Test]
toOption is called.
[toOption2 Test]
toOption2 is called.
toOption2 is called.
```

`Sample.toOption("hoge").get shouldBe "hoge"`というコードでは、** `Sample.toOption`メソッドが実行されませんでした！！**



# 原因調査

@xuwei_k さんからコメントをいただきました。
ScalaTestは関係ありませんでした。

```plain:Scala_Console
Welcome to Scala 2.12.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_172).
Type in expressions for evaluation. Or try :help.

scala> def toOption(name: String): Option[name.type] = {
     |   println("toOption is called.")
     |   Some(name)
     | }
toOption: (name: String)Option[name.type]

scala> toOption("hoge").get
res0: String = hoge

scala> toOption("hoge")
toOption is called.
res1: Option[String("hoge")] = Some(hoge)
```

@xuwei_k さんのコメントから引用


## javapで逆アセンブル
javapで逆アセンブルしてみます。


```scala:Sample.scala
object Sample {
  //追加
  def toString(name: String): name.type = {
    println("toString is called.")
    name
  }
}
```

```scala:CallTest.scala
object CallTest {
  def test = {
    Sample.toOption("aaa")
    Sample.toOption("bbb").get
    Sample.toOption2("ccc").get
    Sample.toString("ddd")
  }
}
```

```shell-session:console
$ javap -verbose CallTest$.class > CallTest$.txt
``` 

```plain:CallTest$.txt
  public java.lang.String test();
    descriptor: ()Ljava/lang/String;
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #19                 // Field jp/co/scalablescala/Sample$.MODULE$:Ljp/co/scalablescala/Sample$;
         3: ldc           #21                 // String aaa
         5: invokevirtual #25                 // Method jp/co/scalablescala/Sample$.toOption:(Ljava/lang/String;)Lscala/Option;
         8: pop
         9: ldc           #27                 // String bbb
        11: pop
        12: getstatic     #19                 // Field jp/co/scalablescala/Sample$.MODULE$:Ljp/co/scalablescala/Sample$;
        15: ldc           #29                 // String ccc
        17: invokevirtual #32                 // Method jp/co/scalablescala/Sample$.toOption2:(Ljava/lang/String;)Lscala/Option;
        20: invokevirtual #38                 // Method scala/Option.get:()Ljava/lang/Object;
        23: pop
        24: ldc           #40                 // String ddd
        26: areturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      27     0  this   Ljp/co/scala/invest/CallTest$;
      LineNumberTable:
        line 8: 0
        line 9: 9
        line 10: 12
        line 11: 24
```


` Sample.toOption("bbb").get`, `Sample.toString("ddd")`のときは、`invokevirtual`（インスタンスのメソッド呼び出し）が実行されていませんでした。


# まとめ

関数の戻りの型が引数の型を参照しているとき、その関数は呼び出されない場合があります。


|  関数の定義  |  関数の呼び出し  |関数が呼び出されるか|
|:----:|:----:|:--:|
|  `def hoge(arg:String) : Option[arg.type]`  |  `hoge("fuga")`  | OK |
|  `def hoge(arg:String) : Option[arg.type]`  |  `hoge("fuga").get`  | NG|
|  `def hoge(arg:String) : Option[String]`  |  `hoge("fuga").get`  | OK|
|  `def hoge(arg:String) : arg.type`  |  `hoge("fuga")`  | NG |

Scalaコンパイラのバグですかね？