Skip to content

Reject failed inits #4434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions compiler/src/dotty/tools/repl/Rendering.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package dotty.tools
package repl

import java.io.{ StringWriter, PrintWriter }
import java.lang.{ ClassLoader, ExceptionInInitializerError }
import java.io.{PrintWriter, StringWriter}
import java.lang.{ClassLoader, ExceptionInInitializerError}
import java.lang.reflect.InvocationTargetException

import scala.util.Try
import scala.runtime.ScalaRunTime

import dotc.core.Contexts.Context
import dotc.core.Denotations.Denotation
import dotc.core.Flags
import dotc.core.Symbols.Symbol
import dotc.core.StdNames.str

import scala.util.Try

/** This rendering object uses `ClassLoader`s to accomplish crossing the 4th
* wall (i.e. fetching back values from the compiled class files put into a
* specific class loader capable of loading from memory) and rendering them.
Expand Down Expand Up @@ -72,21 +74,20 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
d.symbol.showUser

/** Render value definition result */
def renderVal(d: Denotation)(implicit ctx: Context): Option[String] = {
def renderVal(d: Denotation)(implicit ctx: Context): Try[Option[String]] = {
val dcl = d.symbol.showUser

try {
Try {
val resultValue =
if (d.symbol.is(Flags.Lazy)) Some("<lazy>")
else valueOf(d.symbol)

resultValue.map(value => s"$dcl = $value")
}
catch { case ex: InvocationTargetException => Some(renderError(ex)) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should propagate any exception that is not an InvocationTargetException

}

/** Render the stack trace of the underlying exception */
private def renderError(ex: InvocationTargetException): String = {
def renderError(ex: InvocationTargetException): String = {
val cause = ex.getCause match {
case ex: ExceptionInInitializerError => ex.getCause
case ex => ex
Expand Down
54 changes: 39 additions & 15 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dotty.tools.repl

import java.io.PrintStream
import java.lang.reflect.InvocationTargetException

import dotty.tools.dotc.ast.Trees._
import dotty.tools.dotc.ast.{tpd, untpd}
Expand All @@ -22,9 +23,11 @@ import dotty.tools.dotc.util.{SourceFile, SourcePosition}
import dotty.tools.dotc.{CompilationUnit, Driver}
import dotty.tools.io._
import org.jline.reader._
import java.lang.reflect.InvocationTargetException

import scala.annotation.tailrec
import scala.collection.JavaConverters._
import scala.util.{Failure, Success}

/** The state of the REPL contains necessary bindings instead of having to have
* mutation
Expand Down Expand Up @@ -224,13 +227,14 @@ class ReplDriver(settings: Array[String],

val warnings = newState.context.reporter.removeBufferedMessages(newState.context)
displayErrors(warnings)(newState) // display warnings
displayDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports)

displayDefinitions(unit.tpdTree, newestWrapper)(newStateWithImports).getOrElse(state)
}
)
}

/** Display definitions from `tree` */
private def displayDefinitions(tree: tpd.Tree, newestWrapper: Name)(implicit state: State): State = {
private def displayDefinitions(tree: tpd.Tree, newestWrapper: Name)(implicit state: State): Option[State] = {
implicit val ctx = state.context

def resAndUnit(denot: Denotation) = {
Expand Down Expand Up @@ -263,15 +267,40 @@ class ReplDriver(settings: Array[String],
val typeAliases =
info.bounds.hi.typeMembers.filter(_.symbol.info.isTypeAlias)

(
typeAliases.map("// defined alias " + _.symbol.showUser) ++
defs.map(rendering.renderMethod) ++
vals.map(rendering.renderVal).flatten
).foreach(str => out.println(SyntaxHighlighting.highlight(str)))
var renderedVals: List[Option[String]] = Nil
var error: InvocationTargetException = null
import scala.util.control.Breaks.{break, breakable}
breakable {
for (v <- vals) {
val render = rendering.renderVal(v)
render match {
case Success(rv) =>
renderedVals = renderedVals :+ rv
case Failure(th) => th match {
case ex: InvocationTargetException =>
error = ex
break()
case other =>
throw other
}
}
}
}

state.copy(valIndex = state.valIndex - vals.count(resAndUnit))
if (error != null) {
out.println(SyntaxHighlighting.highlight(rendering.renderError(error)))
rendering = new Rendering(classLoader)
None
} else {
(
typeAliases.map("// defined alias " + _.symbol.showUser) ++
defs.map(rendering.renderMethod) ++
renderedVals.flatten
).foreach(str => out.println(SyntaxHighlighting.highlight(str)))
Some(state.copy(valIndex = state.valIndex - vals.count(resAndUnit)))
}
}
else state
else Some(state)

def isSyntheticCompanion(sym: Symbol) =
sym.is(Module) && sym.is(Synthetic)
Expand All @@ -294,18 +323,13 @@ class ReplDriver(settings: Array[String],


ctx.atPhase(ctx.typerPhase.next) { implicit ctx =>

// Display members of wrapped module:
tree.symbol.info.memberClasses
.find(_.symbol.name == newestWrapper.moduleClassName)
.map { wrapperModule =>
.flatMap { wrapperModule =>
displayTypeDefs(wrapperModule.symbol)
displayMembers(wrapperModule.symbol)
}
.getOrElse {
// user defined a trait/class/object, so no module needed
state
}
}
}

Expand Down