2015-10-16 93 views
4

我注意到類型檢查器分階段工作。有時候,scalac只會返回一些錯誤,這使得你幾乎認爲它已經存在,但是一旦你修復了它們所有的 - 繁榮 - 下一個階段,你突然間會發現很多錯誤,而這些錯誤之前並不存在。類型檢查器階段

類型檢查器的不同階段是什麼?

有沒有辦法知道類型檢查器在哪個階段放棄了我的代碼(除了識別錯誤)?

+0

我相信, Odersky從這個[talk](https://www.youtube.com/watch?v=WxyyJyB_Ssc)的幻燈片中可以看到所有階段。 –

+0

我一定會注意到這一點,但請注意,我(僅)對編譯器停止報告錯誤的階段感興趣。 – OlivierBlanvillain

+0

這可能是一個重複的http://stackoverflow.com/questions/4527902/what-is-the-order-of-the-scala-compiler-phases – Felix

回答

1

編譯器選項爲-Yissue-debug。當發出錯誤時,它在2.10中輸出堆棧跟蹤。

重構報告期間支持它的代碼在2.11中被刪除,但該選項仍然有效。 (我在某個時候恢復了它,因爲事實上,它是查看發生錯誤的最快方法;但顯然PR在藤上死了並且消失了,可能是push -f的受害者。)

在2.12中,可以提供一個自定義的記者,完成同樣的事情。他們聲稱,他們將加強記者API訪問上下文,所以你也許可以直接查詢當前階段,檢查樹木,等等。

這裏有你所描述的情況爲例:

class C { def f: Int ; def g: Int = "" ; def h = "\000" } 

有三個錯誤,但只有一次一個報告,因爲它們是在不同的編譯階段發出的。

爲了澄清這個問題,各個階段除了「打字員」,可以創建和類型檢測,樹木,還可以強制樹被輸入後也很好typedness。 (也有其他類型的錯誤,例如「不能寫入輸出文件中。」)

對於C,解析器發出錯誤(-Xfuture下),用於棄用八進制語法中,導電型測量儀報告的類型不匹配g,並且抓包重新檢查階段檢查聲明但未定義(空)的成員f。您通常會每次修復一個錯誤。如果解析器錯誤是作爲警告發出的,那麼警告將被抑制,直到錯誤得到解決,所以這將是彈出的最後一個而不是第一個。

這是一個記者試圖做的不僅僅是輸出巨大的堆棧跟蹤。

package myrep 

import scala.tools.nsc.Settings 
import scala.tools.nsc.reporters.ConsoleReporter 

import scala.reflect.internal.util._ 

class DebugReporter(ss: Settings) extends ConsoleReporter(ss) { 
    override def warning(pos: Position, msg: String) = debug { 
    super.warning(pos, msg) 
    } 
    override def error(pos: Position, msg: String) = debug { 
    super.error(pos, msg) 
    } 
    // let it ride 
    override def hasErrors = false 

    private def debug(body: => Unit): Unit = { 
    val pkgs = Set("nsc.ast.parser", "nsc.typechecker", "nsc.transform") 
    def compilerPackages(e: StackTraceElement): Boolean = pkgs exists (e.getClassName contains _) 
    def classname(e: StackTraceElement): String = (e.getClassName split """\.""").last 
    if (ss.Yissuedebug) echo { 
     ((new Throwable).getStackTrace filter compilerPackages map classname).distinct mkString ("Issued from: ", ",", "\n") 
    } 
    body 
    } 
} 

它關於沒有錯誤,以便編譯器不會提前中止。

它會在 「工具類路徑」 上調用這種方式,與記者類:

scalacm -toolcp repdir -Xreporter myrep.DebugReporter -Yissue-debug -deprecation errs.scala 

其中

$ scalacm -version 
Scala compiler version 2.12.0-M2 -- Copyright 2002-2013, LAMP/EPFL 

輸出示例:

Issued from: Scanners$UnitScanner,Scanners$Scanner,Parsers$Parser,Parsers$Parser$$anonfun$templateStat$1,Parsers$Parser$$anonfun$topStat$1,Parsers$SourceFileParser,Parsers$UnitParser,SyntaxAnalyzer,SyntaxAnalyzer$ParserPhase 
errs.scala:4: warning: Octal escape literals are deprecated, use \u0000 instead. 
class C { def f: Int ; def g: Int = "" ; def h = "\000" } 
               ^
Issued from: Contexts$ImmediateReporter,Contexts$ContextReporter,Contexts$Context,ContextErrors$ErrorUtils$,ContextErrors$TyperContextErrors$TyperErrorGen$,Typers$Typer,Analyzer$typerFactory$$anon$3 
errs.scala:4: error: type mismatch; 
found : String("") 
required: Int 
class C { def f: Int ; def g: Int = "" ; def h = "\000" } 
            ^
Issued from: RefChecks$RefCheckTransformer,Transform$Phase 
errs.scala:4: error: class C needs to be abstract, since method f is not defined 
class C { def f: Int ; def g: Int = "" ; def h = "\000" } 
    ^
one warning found 
two errors found 
+0

我意識到沒有人在意,但這是你添加回來的地方。仍然在PR隊列中。你爲什麼不添加更多的上下文? https://github.com/som-snytt/scala/blob/issue/2991-2.12/src/compiler/scala/tools/nsc/typechecker/Contexts.scala#L577 –

3

由於@Felix指出,this answer列出編譯階段:

$ scalac -version 
Scala compiler version 2.11.6 -- Copyright 2002-2013, LAMP/EPFL 
$ scalac -Xshow-phases 
    phase name id description 
    ---------- -- ----------- 
     parser 1 parse source into ASTs, perform simple desugaring 
     namer 2 resolve names, attach symbols to named trees 
packageobjects 3 load package objects 
     typer 4 the meat and potatoes: type the trees 
     patmat 5 translate match expressions 
superaccessors 6 add super accessors in traits and nested classes 
    extmethods 7 add extension methods for inline classes 
     pickler 8 serialize symbol tables 
    refchecks 9 reference/override checking, translate nested objects 
     uncurry 10 uncurry, translate function values to anonymous classes 
    tailcalls 11 replace tail calls by jumps 
    specialize 12 @specialized-driven class and method specialization 
explicitouter 13 this refs to outer pointers 
     erasure 14 erase types, add interfaces for traits 
    posterasure 15 clean up erased inline classes 
     lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs 
    lambdalift 17 move nested functions to top level 
    constructors 18 move field definitions into constructors 
     flatten 19 eliminate inner classes 
     mixin 20 mixin composition 
     cleanup 21 platform-specific cleanups, generate reflective calls 
    delambdafy 22 remove lambdas 
     icode 23 generate portable intermediate code 
      jvm 24 generate JVM bytecode 
     terminal 25 the last phase during a compilation run 

有沒有辦法知道在哪個階段類型檢查放棄了對我的代碼(不承認錯誤等)?

如果添加-verbose標誌scalac,將打印各階段的名稱,多長時間了這一階段完成後。然後你可以推斷哪一個階段失敗

我不認爲scalac暴露不同階段的打字,只有編譯階段。 typer被列爲單個編譯階段。