Skip to content

Commit

Permalink
Ambiguous imports warnings/errors are serializable
Browse files Browse the repository at this point in the history
`AmbgiuousImport` error and `DuplicatedImport` warning must not have
`Source` as one of its fields or compiler will crash during a
serialization attempt.
Changed the implementation to provide it as a parameter to the `message`
method instead.
  • Loading branch information
hubertp committed Oct 17, 2023
1 parent b039f92 commit 33de332
Show file tree
Hide file tree
Showing 21 changed files with 160 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,14 +199,15 @@ final class EnsureCompiledJob(
module: Module,
diagnostic: Diagnostic
): Api.ExecutionResult.Diagnostic = {
val source = module.getSource
Api.ExecutionResult.Diagnostic(
kind,
Option(diagnostic.formattedMessage),
Option(diagnostic.formattedMessage(source)),
Option(module.getPath).map(new File(_)),
diagnostic.location
.map(loc =>
LocationResolver
.locationToRange(loc.location, module.getSource.getCharacters)
.locationToRange(loc.location, source.getCharacters)
),
diagnostic.location
.flatMap(LocationResolver.getExpressionId(module.getIr, _))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package org.enso.compiler.core.ir

import com.oracle.truffle.api.source.Source

/** A representation of various kinds of diagnostic in the IR. */
trait Diagnostic extends Serializable {

/** @return a human-readable description of this error condition.
/** @param source Location of the diagnostic.
* @return a human-readable description of this error condition.
*/
def message: String
def message(source: Source): String

/** @return a human-readable description of this error condition, formatted for immediate reporting. */
def formattedMessage: String = message
/** @param source Location of the diagnostic.
* @return a human-readable description of this error condition, formatted for immediate reporting.
*/
def formattedMessage(source: Source): String = message(source)

/** The location at which the diagnostic occurs. */
val location: Option[IdentifiedLocation]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.enso.compiler.core.ir

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, ToStringHelper}

Expand Down Expand Up @@ -75,7 +76,7 @@ sealed case class Empty(
override def children: List[IR] = List()

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
"Empty IR: Please report this as a compiler bug."

/** @inheritdoc */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ object Warning {
case class DuplicatedImport(
override val location: Option[IdentifiedLocation],
originalImport: ir.module.scope.Import,
symbolName: String,
source: Source
symbolName: String
) extends Warning {
override def message: String = {
override def message(source: Source): String = {
val originalImportRepr =
originalImport.location match {
case Some(location) =>
Expand All @@ -35,7 +34,7 @@ object Warning {
*/
case class WrongTco(override val location: Option[IdentifiedLocation])
extends Warning {
override def message: String =
override def message(source: Source): String =
"A @Tail_Call annotation was placed in a non-tail-call position."

override def diagnosticKeys(): Array[Any] = Array()
Expand All @@ -49,7 +48,7 @@ object Warning {
case class WrongBuiltinMethod(
override val location: Option[IdentifiedLocation]
) extends Warning {
override def message: String =
override def message(source: Source): String =
"A @Builtin_Method annotation allows only the name of the builtin node in the body."

override def diagnosticKeys(): Array[Any] = Array()
Expand All @@ -68,7 +67,7 @@ object Warning {
) extends Warning {
override val location: Option[IdentifiedLocation] = ir.location

override def message: String =
override def message(source: Source): String =
s"${funName.name}: Self parameter should be declared as the first parameter. Instead its position is: ${paramPosition + 1}."

override def diagnosticKeys(): Array[Any] =
Expand All @@ -87,7 +86,7 @@ object Warning {
) extends Warning {
override val location: Option[IdentifiedLocation] = ir.location

override def message: String =
override def message(source: Source): String =
s"The expression ${ir.showCode()} could not be parallelised: $reason."

override def diagnosticKeys(): Array[Any] = Array(ir.showCode(), reason)
Expand All @@ -98,7 +97,7 @@ object Warning {

/** @return a human-readable description of this error condition.
*/
override def message: String =
override def message(source: Source): String =
s"A non-unit type ${ir.name} is used on value level (in ${context})." +
" This is probably an error."

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.enso.compiler.core.ir
package expression

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper}
import org.enso.compiler.core.ir.Expression
import org.enso.compiler.core.{ir, IR}
Expand Down Expand Up @@ -107,7 +108,7 @@ object Error {
override def children: List[IR] = List(ir)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
"InvalidIR: Please report this as a compiler bug."

override def diagnosticKeys(): Array[Any] = Array()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir
package expression
package errors

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, Identifier}

Expand Down Expand Up @@ -85,7 +86,7 @@ sealed case class Conversion(
s"(Error: ${storedIr.showCode(indent)})"

/** @inheritdoc */
override def message: String = reason.explain
override def message(source: Source): String = reason.explain

override def diagnosticKeys(): Array[Any] = Array(reason.explain)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ sealed case class ImportExport(
override def children: List[IR] = List(ir)

/** @inheritdoc */
override def message: String = reason.message
override def message(source: Source): String = reason.message(source)

override def diagnosticKeys(): Array[Any] = Array(reason)

Expand All @@ -111,9 +111,10 @@ object ImportExport {
*/
sealed trait Reason {

/** @return A human-readable description of the error.
/** @param source Location of the original import/export IR.
* @return A human-readable description of the error.
*/
def message: String
def message(source: Source): String
}

/** Used when the `project` keyword is used in an impossible position.
Expand All @@ -123,7 +124,7 @@ object ImportExport {
*/
case class ProjectKeywordUsedButNotInProject(statementType: String)
extends Reason {
override def message: String =
override def message(source: Source): String =
s"The `project` keyword was used in an $statementType statement," +
" but the module does not belong to a project."
}
Expand All @@ -135,7 +136,8 @@ object ImportExport {
*/
case class PackageCouldNotBeLoaded(name: String, reason: String)
extends Reason {
override def message: String = s"Package containing the module $name" +
override def message(source: Source): String =
s"Package containing the module $name" +
s" could not be loaded: $reason"
}

Expand All @@ -144,51 +146,52 @@ object ImportExport {
* @param name the module name.
*/
case class ModuleDoesNotExist(name: String) extends Reason {
override def message: String = s"The module $name does not exist."
override def message(source: Source): String =
s"The module $name does not exist."
}

case class TypeDoesNotExist(
typeName: String,
moduleName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"The type $typeName does not exist in module $moduleName"
}

case class SymbolDoesNotExist(
symbolName: String,
moduleOrTypeName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"The symbol $symbolName (module, type, or constructor) does not exist in $moduleOrTypeName."
}

case class NoSuchConstructor(
typeName: String,
constructorName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"No such constructor ${constructorName} in type $typeName"
}

case class ExportSymbolsFromPrivateModule(
moduleName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"Cannot export any symbol from module '$moduleName': The module is private"
}

case class ExportPrivateModule(
moduleName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"Cannot export private module '$moduleName'"
}

case class ImportPrivateModule(
moduleName: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"Cannot import private module '$moduleName'"
}

Expand All @@ -198,7 +201,7 @@ object ImportExport {
moduleVisibility: String,
submoduleVisibility: String
) extends Reason {
override def message: String =
override def message(source: Source): String =
s"Cannot export submodule '$submoduleName' of module '$moduleName': " +
s"the submodule is $submoduleVisibility, but the module is $moduleVisibility"
}
Expand All @@ -210,16 +213,14 @@ object ImportExport {
* @param originalSymbolPath the original symbol path.
* @param symbolName the symbol name that is ambiguous.
* @param symbolPath the symbol path that is different than [[originalSymbolPath]].
* @param source Location of the original import.
*/
case class AmbiguousImport(
originalImport: module.scope.Import,
originalSymbolPath: String,
symbolName: String,
symbolPath: String,
source: Source
symbolPath: String
) extends Reason {
override def message: String = {
override def message(source: Source): String = {
val originalImportRepr =
originalImport.location match {
case Some(location) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir
package expression
package errors

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, Identifier}

Expand Down Expand Up @@ -69,7 +70,7 @@ sealed case class Pattern(
id = if (keepIdentifiers) id else randomId
)

override def message: String = reason.explain
override def message(source: Source): String = reason.explain

override def diagnosticKeys(): Array[Any] = Array(reason)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir
package expression
package errors

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, Identifier}

Expand Down Expand Up @@ -87,7 +88,7 @@ object Redefined {
this

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
"Methods must have only one definition of the `this` argument, and " +
"it must be the first."

Expand Down Expand Up @@ -186,7 +187,7 @@ object Redefined {
copy(location = location)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
s"Method overloads are not supported: ${targetType.map(_.name + ".").getOrElse("")}from " +
s"${sourceType.showCode()} is defined multiple times in this module."

Expand Down Expand Up @@ -305,7 +306,7 @@ object Redefined {
copy(location = location)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
s"Method overloads are not supported: ${atomName.map(_.name + ".").getOrElse("")}" +
s"${methodName.name} is defined multiple times in this module."

Expand Down Expand Up @@ -431,7 +432,7 @@ object Redefined {
copy(location = location)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
s"Method definitions with the same name as atoms are not supported. " +
s"Method ${methodName.name} clashes with the atom ${atomName.name} in this module."

Expand Down Expand Up @@ -534,7 +535,7 @@ object Redefined {
copy(location = location)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
s"Redefining atoms is not supported: ${typeName.name} is " +
s"defined multiple times in this module."

Expand Down Expand Up @@ -650,7 +651,7 @@ object Redefined {
override def children: List[IR] = List(invalidBinding)

/** @inheritdoc */
override def message: String =
override def message(source: Source): String =
s"Variable ${invalidBinding.name.name} is being redefined."

override def diagnosticKeys(): Array[Any] = Array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir
package expression
package errors

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, Identifier}

Expand Down Expand Up @@ -83,10 +84,10 @@ sealed case class Resolution(
override def showCode(indent: Int): String = originalName.showCode(indent)

/** @inheritdoc */
override def message: String = reason.explain(originalName)
override def message(source: Source): String = reason.explain(originalName)

/** @inheritdoc */
override def formattedMessage: String = s"${message}."
override def formattedMessage(source: Source): String = s"${message(source)}."

override def diagnosticKeys(): Array[Any] = Array(reason)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.compiler.core.ir
package expression
package errors

import com.oracle.truffle.api.source.Source
import org.enso.compiler.core.IR
import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper}

Expand Down Expand Up @@ -89,10 +90,10 @@ sealed case class Syntax(
override def children: List[IR] = List()

/** @inheritdoc */
override def message: String = reason.explanation
override def message(source: Source): String = reason.explanation

/** @inheritdoc */
override def formattedMessage: String = s"${message}."
override def formattedMessage(source: Source): String = s"${message(source)}."

override def diagnosticKeys(): Array[Any] = Array(reason)

Expand Down
Loading

0 comments on commit 33de332

Please sign in to comment.