diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso index 372eb5bd8b..a5617b5b16 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso @@ -59,8 +59,9 @@ type Type_Error Arguments: - expected: The expected type at the error location. - actual: The actual type at the error location. - - name: The name of the argument whose type is mismatched. - Error expected actual name + - comment: Description of the value that was being checked, + e.g. function argument, result or an arbitrary expression. + Error expected actual comment ## PRIVATE Convert the Type_Error error to a human-readable format. @@ -78,7 +79,7 @@ type Type_Error _ -> ". Try to apply " + (missing_args.join ", ") + " arguments" _ -> tpe.to_text - "Type error: expected `"+self.name+"` to be "+self.expected.to_display_text+", but got "+type_of_actual+"." + "Type error: expected "+self.comment+" to be "+self.expected.to_display_text+", but got "+type_of_actual+"." @Builtin_Type type Compile_Error diff --git a/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/PassPersistance.java b/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/PassPersistance.java index bd939c45c5..aa45e20925 100644 --- a/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/PassPersistance.java +++ b/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/PassPersistance.java @@ -30,7 +30,7 @@ import scala.Option; @Persistable(clazz = GatherDiagnostics.DiagnosticsMeta.class, id = 1114) @Persistable(clazz = DocumentationComments.Doc.class, id = 1115) @Persistable(clazz = AliasAnalysis$Info$Occurrence.class, id = 1116) -@Persistable(clazz = TypeSignatures.Signature.class, id = 1117) +@Persistable(clazz = TypeSignatures.Signature.class, id = 2117) @Persistable(clazz = ModuleAnnotations.Annotations.class, id = 1118) @Persistable(clazz = AliasAnalysis$Info$Scope$Root.class, id = 1120) @Persistable(clazz = DataflowAnalysis$DependencyInfo$Type$Static.class, id = 1121) diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala index b797458a4a..7d7ed10b49 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala @@ -488,7 +488,7 @@ final class SuggestionBuilder[A: IndexedSource]( typeSignature: Option[TypeSignatures.Metadata] ): Vector[TypeArg] = typeSignature match { - case Some(TypeSignatures.Signature(typeExpr)) => + case Some(TypeSignatures.Signature(typeExpr, _)) => buildTypeSignature(typeExpr) case _ => Vector() diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala index e9ea22902e..4e470d1e1c 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala @@ -393,7 +393,7 @@ case object DataflowAnalysis extends IRPass { */ def analyseType(typ: Type, info: DependencyInfo): Type = { typ match { - case asc @ Type.Ascription(typed, signature, _, _, _) => + case asc @ Type.Ascription(typed, signature, _, _, _, _) => val ascrDep = asStatic(asc) val typedDep = asStatic(typed) val sigDep = asStatic(signature) diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala index ee2fce97e8..f29e8f4155 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala @@ -166,7 +166,7 @@ case object ComplexType extends IRPass { ): List[Definition] = { var unusedSig: Option[Type.Ascription] = None val sig = lastSignature match { - case Some(Type.Ascription(typed, _, _, _, _)) => + case Some(Type.Ascription(typed, _, _, _, _, _)) => typed match { case literal: Name.Literal => if (name.name == literal.name) { diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala index 1b8a6b6e06..9d78457ca4 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala @@ -115,7 +115,7 @@ case object SuspendedArguments extends IRPass { method.body match { case lam @ Function.Lambda(args, body, _, _, _, _) => method.getMetadata(TypeSignatures) match { - case Some(Signature(signature)) => + case Some(Signature(signature, _)) => val newArgs = computeSuspensions(args.drop(1), signature) if (newArgs.head.suspended) { errors.Conversion( @@ -163,7 +163,7 @@ case object SuspendedArguments extends IRPass { body match { case lam @ Function.Lambda(args, lamBody, _, _, _, _) => explicit.getMetadata(TypeSignatures) match { - case Some(Signature(signature)) => + case Some(Signature(signature, _)) => val newArgs = computeSuspensions( args.drop(1), signature @@ -214,7 +214,7 @@ case object SuspendedArguments extends IRPass { expression.transformExpressions { case bind @ Expression.Binding(_, expr, _, _, _) => val newExpr = bind.getMetadata(TypeSignatures) match { - case Some(Signature(signature)) => + case Some(Signature(signature, _)) => expr match { case lam @ Function.Lambda(args, body, _, _, _, _) => lam.copy( @@ -229,7 +229,7 @@ case object SuspendedArguments extends IRPass { bind.copy(expression = newExpr) case lam @ Function.Lambda(args, body, _, _, _, _) => lam.getMetadata(TypeSignatures) match { - case Some(Signature(signature)) => + case Some(Signature(signature, _)) => lam.copy( arguments = computeSuspensions(args, signature), body = resolveExpression(body) diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala index 499364a8aa..45c40a4587 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala @@ -186,7 +186,7 @@ case object TypeFunctions extends IRPass { name.name match { case Type.Ascription.name => - Type.Ascription(leftArg, rightArg, location) + Type.Ascription(leftArg, rightArg, None, location) case Type.Context.name => Type.Context(leftArg, rightArg, location) case Type.Error.name => diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala index 8161dff91c..8272b7c198 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala @@ -111,7 +111,8 @@ case object TypeNames extends IRPass { new MetadataPair( TypeSignatures, TypeSignatures.Signature( - resolveSignature(typeParams, bindingsMap, s.signature) + resolveSignature(typeParams, bindingsMap, s.signature), + s.comment ) ) ) diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala index 1d10387eee..eca3016942 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala @@ -97,7 +97,7 @@ case object TypeSignatures extends IRPass { case _ => } val res = lastSignature match { - case Some(asc @ Type.Ascription(typed, sig, _, _, _)) => + case Some(asc @ Type.Ascription(typed, sig, comment, _, _, _)) => val methodRef = meth.methodReference val newMethodWithDoc = asc .getMetadata(DocumentationComments) @@ -121,7 +121,7 @@ case object TypeSignatures extends IRPass { if (ref isSameReferenceAs methodRef) { Some( newMethodWithAnnotations.updateMetadata( - new MetadataPair(this, Signature(sig)) + new MetadataPair(this, Signature(sig, comment)) ) ) } else { @@ -246,7 +246,9 @@ case object TypeSignatures extends IRPass { private def resolveAscription(sig: Type.Ascription): Expression = { val newTyped = sig.typed.mapExpressions(resolveExpression) val newSig = sig.signature.mapExpressions(resolveExpression) - newTyped.updateMetadata(new MetadataPair(this, Signature(newSig))) + newTyped.updateMetadata( + new MetadataPair(this, Signature(newSig, sig.comment)) + ) } /** Resolves type signatures in a block. @@ -271,7 +273,7 @@ case object TypeSignatures extends IRPass { case binding: Expression.Binding => val newBinding = binding.mapExpressions(resolveExpression) val res = lastSignature match { - case Some(asc @ Type.Ascription(typed, sig, _, _, _)) => + case Some(asc @ Type.Ascription(typed, sig, comment, _, _, _)) => val name = binding.name val newBindingWithDoc = asc .getMetadata(DocumentationComments) @@ -287,7 +289,7 @@ case object TypeSignatures extends IRPass { if (typedName.name == name.name) { Some( newBindingWithDoc.updateMetadata( - new MetadataPair(this, Signature(sig)) + new MetadataPair(this, Signature(sig, comment)) ) ) } else { @@ -321,8 +323,10 @@ case object TypeSignatures extends IRPass { /** A representation of a type signature. * * @param signature the expression for the type signature + * @param comment an optional comment from which the potential error message will be derived */ - case class Signature(signature: Expression) extends IRPass.IRMetadata { + case class Signature(signature: Expression, comment: Option[String] = None) + extends IRPass.IRMetadata { override val metadataName: String = "TypeSignatures.Signature" /** @inheritdoc */ @@ -345,6 +349,6 @@ case object TypeSignatures extends IRPass { /** @inheritdoc */ override def duplicate(): Option[IRPass.IRMetadata] = - Some(this.copy(signature = signature.duplicate())) + Some(this.copy(signature = signature.duplicate(), comment = comment)) } } diff --git a/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java b/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java index 0f78bc4055..3f96a90b55 100644 --- a/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java +++ b/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java @@ -96,7 +96,7 @@ final class TreeToIr { methodReference = translateExpression(sig.getVariable()); } var signature = translateType(sig.getType()); - var ascription = new Type.Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); + var ascription = new Type.Ascription(methodReference, signature, Option.empty(), getIdentifiedLocation(sig), meta(), diag()); yield ascription; } default -> translateExpression(exprTree); @@ -250,7 +250,8 @@ final class TreeToIr { yield join(error, appendTo); } - var ascribedBody = addTypeAscription(body, returnSignature, loc); + String functionName = fn.getName().codeRepr(); + var ascribedBody = addTypeAscription(functionName, body, returnSignature, loc); var binding = new Method.Binding( methodRef, args, @@ -317,7 +318,7 @@ final class TreeToIr { case Tree.TypeSignature sig -> { var methodReference = translateMethodReference(sig.getVariable(), true); var signature = translateType(sig.getType()); - var ascription = new Type.Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); + var ascription = new Type.Ascription(methodReference, signature, Option.empty(), getIdentifiedLocation(sig), meta(), diag()); yield join(ascription, appendTo); } @@ -507,6 +508,7 @@ final class TreeToIr { var loc = getIdentifiedLocation(fun); var body = translateExpression(treeBody); + String functionName = name.name(); if (args.isEmpty()) { if (body instanceof Expression.Block block) { // suspended block has a name and no arguments @@ -524,14 +526,14 @@ final class TreeToIr { body = translateSyntaxError(fun, Syntax.UnexpectedExpression$.MODULE$); } - var ascribedBody = addTypeAscription(body, returnType, loc); + var ascribedBody = addTypeAscription(functionName, body, returnType, loc); return new Expression.Binding(name, ascribedBody, loc, meta(), diag()); } else { if (body == null) { return translateSyntaxError(fun, Syntax.UnexpectedDeclarationInType$.MODULE$); } - var ascribedBody = addTypeAscription(body, returnType, loc); + var ascribedBody = addTypeAscription(functionName, body, returnType, loc); return new Function.Binding(name, args, ascribedBody, loc, true, meta(), diag()); } } @@ -551,17 +553,18 @@ final class TreeToIr { *

* If the type is {@code null}, the body is returned unchanged. */ - private Expression addTypeAscription(Expression body, Expression type, Option loc) { + private Expression addTypeAscription(String functionName, Expression body, Expression type, Option loc) { if (type == null) { return body; } - return new Type.Ascription(body, type, loc, meta(), diag()); + String comment = "the result of `" + functionName + "`"; + return new Type.Ascription(body, type, Option.apply(comment), loc, meta(), diag()); } private Type.Ascription translateTypeSignature(Tree sig, Tree type, Expression typeName) { var fn = translateType(type); - return new Type.Ascription(typeName, fn, getIdentifiedLocation(sig), meta(), diag()); + return new Type.Ascription(typeName, fn, Option.empty(), getIdentifiedLocation(sig), meta(), diag()); } diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala index 6b79b44a77..28c94690e4 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala @@ -122,6 +122,7 @@ object Type { * * @param typed the expression being ascribed a type * @param signature the signature being ascribed to `typed` + * @param comment a comment that may be used to add context to the type error * @param location the source location that the node corresponds to * @param passData the pass metadata associated with this node * @param diagnostics compiler diagnostics for this node @@ -129,6 +130,7 @@ object Type { sealed case class Ascription( typed: Expression, signature: Expression, + comment: Option[String], override val location: Option[IdentifiedLocation], override val passData: MetadataStorage = new MetadataStorage(), override val diagnostics: DiagnosticStorage = DiagnosticStorage() @@ -141,6 +143,7 @@ object Type { * * @param typed the expression being ascribed a type * @param signature the signature being ascribed to `typed` + * @param comment a comment that may be used to add context to the type error * @param location the source location that the node corresponds to * @param passData the pass metadata associated with this node * @param diagnostics compiler diagnostics for this node @@ -150,12 +153,14 @@ object Type { def copy( typed: Expression = typed, signature: Expression = signature, + comment: Option[String] = comment, location: Option[IdentifiedLocation] = location, passData: MetadataStorage = passData, diagnostics: DiagnosticStorage = diagnostics, id: UUID @Identifier = id ): Ascription = { - val res = Ascription(typed, signature, location, passData, diagnostics) + val res = + Ascription(typed, signature, comment, location, passData, diagnostics) res.id = id res } @@ -205,6 +210,7 @@ object Type { s"""Type.Ascription( |typed = $typed, |signature = $signature, + |comment = $comment, |location = $location, |passData = ${this.showPassData}, |diagnostics = $diagnostics, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/argument/ReadArgumentCheckNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/argument/ReadArgumentCheckNode.java index 86e203cb18..17dcbf79eb 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/argument/ReadArgumentCheckNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/argument/ReadArgumentCheckNode.java @@ -19,7 +19,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.enso.compiler.core.ir.Name; import org.enso.interpreter.EnsoLanguage; import org.enso.interpreter.node.BaseNode.TailStatus; import org.enso.interpreter.node.EnsoRootNode; @@ -49,11 +48,11 @@ import org.enso.interpreter.runtime.library.dispatch.TypesLibrary; import org.graalvm.collections.Pair; public abstract class ReadArgumentCheckNode extends Node { - private final String name; + private final String comment; @CompilerDirectives.CompilationFinal private String expectedTypeMessage; - ReadArgumentCheckNode(String name) { - this.name = name; + ReadArgumentCheckNode(String comment) { + this.comment = comment; } /** */ @@ -62,7 +61,7 @@ public abstract class ReadArgumentCheckNode extends Node { } /** - * Executes check or conversion of the value.abstract + * Executes check or conversion of the value. * * @param frame frame requesting the conversion * @param value the value to convert @@ -89,12 +88,12 @@ public abstract class ReadArgumentCheckNode extends Node { expectedTypeMessage = expectedTypeMessage(); } var ctx = EnsoContext.get(this); - var msg = name == null ? "expression" : name; - var err = ctx.getBuiltins().error().makeTypeError(expectedTypeMessage, v, msg); + var msg = comment == null ? "expression" : comment; + var err = ctx.getBuiltins().error().makeTypeErrorOfComment(expectedTypeMessage, v, msg); throw new PanicException(err, this); } - public static ReadArgumentCheckNode allOf(Name argumentName, ReadArgumentCheckNode... checks) { + public static ReadArgumentCheckNode allOf(String argumentName, ReadArgumentCheckNode... checks) { var list = Arrays.asList(checks); var flatten = list.stream() @@ -105,27 +104,25 @@ public abstract class ReadArgumentCheckNode extends Node { return switch (arr.length) { case 0 -> null; case 1 -> arr[0]; - default -> new AllOfNode(argumentName.name(), arr); + default -> new AllOfNode(argumentName, arr); }; } - public static ReadArgumentCheckNode oneOf(Name argumentName, List checks) { + public static ReadArgumentCheckNode oneOf(String comment, List checks) { var arr = toArray(checks); return switch (arr.length) { case 0 -> null; case 1 -> arr[0]; - default -> new OneOfNode(argumentName.name(), arr); + default -> new OneOfNode(comment, arr); }; } - public static ReadArgumentCheckNode build(Name argumentName, Type expectedType) { - var n = argumentName == null ? null : argumentName.name(); - return ReadArgumentCheckNodeFactory.TypeCheckNodeGen.create(n, expectedType); + public static ReadArgumentCheckNode build(String comment, Type expectedType) { + return ReadArgumentCheckNodeFactory.TypeCheckNodeGen.create(comment, expectedType); } - public static ReadArgumentCheckNode meta(Name argumentName, Object metaObject) { - var n = argumentName == null ? null : argumentName.name(); - return ReadArgumentCheckNodeFactory.MetaCheckNodeGen.create(n, metaObject); + public static ReadArgumentCheckNode meta(String comment, Object metaObject) { + return ReadArgumentCheckNodeFactory.MetaCheckNodeGen.create(comment, metaObject); } public static boolean isWrappedThunk(Function fn) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/TypeError.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/TypeError.java index e49ff6999a..54c84a6ac1 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/TypeError.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/error/TypeError.java @@ -13,6 +13,6 @@ public class TypeError extends UniquelyConstructibleBuiltin { @Override protected List getConstructorParamNames() { - return List.of("expected", "actual", "name"); + return List.of("expected", "actual", "comment"); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java index fb2798e001..783dff4ee7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java @@ -176,11 +176,24 @@ public final class Error { * * @param expected the expected type * @param actual the actual type - * @param name the name of the variable that is a type error + * @param name name of the argument that was being checked * @return a runtime representation of the error. */ + @CompilerDirectives.TruffleBoundary public Atom makeTypeError(Object expected, Object actual, String name) { - return typeError.newInstance(expected, actual, Text.create(name)); + return typeError.newInstance(expected, actual, Text.create("`" + name + "`")); + } + + /** + * Creates an instance of the runtime representation of a {@code Type_Error}. + * + * @param expected the expected type + * @param actual the actual type + * @param comment description of the value that was being checked + * @return a runtime representation of the error. + */ + public Atom makeTypeErrorOfComment(Object expected, Object actual, String comment) { + return typeError.newInstance(expected, actual, Text.create(comment)); } /** diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala index 0b2bbb4577..aa2bd354a9 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala @@ -713,24 +713,24 @@ class IrToTruffle( // ========================================================================== private def extractAscribedType( - name: Name, + comment: String, t: Expression ): ReadArgumentCheckNode = t match { case u: `type`.Set.Union => ReadArgumentCheckNode.oneOf( - name, - u.operands.map(extractAscribedType(name, _)).asJava + comment, + u.operands.map(extractAscribedType(comment, _)).asJava ) case i: `type`.Set.Intersection => ReadArgumentCheckNode.allOf( - name, - extractAscribedType(name, i.left), - extractAscribedType(name, i.right) + comment, + extractAscribedType(comment, i.left), + extractAscribedType(comment, i.right) ) - case p: Application.Prefix => extractAscribedType(name, p.function) + case p: Application.Prefix => extractAscribedType(comment, p.function) case _: Tpe.Function => ReadArgumentCheckNode.build( - name, + comment, context.getTopScope().getBuiltins().function() ) case t => { @@ -740,7 +740,7 @@ class IrToTruffle( .Resolution(BindingsMap.ResolvedType(mod, tpe)) ) => ReadArgumentCheckNode.build( - name, + comment, asScope( mod .unsafeAsModule() @@ -753,7 +753,7 @@ class IrToTruffle( .Resolution(BindingsMap.ResolvedPolyglotSymbol(mod, symbol)) ) => ReadArgumentCheckNode.meta( - name, + comment, asScope( mod .unsafeAsModule() @@ -768,7 +768,8 @@ class IrToTruffle( private def checkAsTypes( arg: DefinitionArgument ): ReadArgumentCheckNode = { - arg.ascribedType.map(extractAscribedType(arg.name, _)).getOrElse(null) + val comment = "`" + arg.name.name + "`" + arg.ascribedType.map(extractAscribedType(comment, _)).getOrElse(null) } /** Checks if the expression has a @Builtin_Method annotation @@ -1074,9 +1075,11 @@ class IrToTruffle( ir match { case _: Expression.Binding => case _ => - val types = ir.getMetadata(TypeSignatures) + val types: Option[TypeSignatures.Signature] = + ir.getMetadata(TypeSignatures) types.foreach { tpe => - val checkNode = extractAscribedType(null, tpe.signature); + val checkNode = + extractAscribedType(tpe.comment.orNull, tpe.signature); if (checkNode != null) { runtimeExpression = ReadArgumentCheckNode.wrap(runtimeExpression, checkNode) diff --git a/engine/runtime/src/test/java/org/enso/interpreter/test/SignaturePolyglotTest.java b/engine/runtime/src/test/java/org/enso/interpreter/test/SignaturePolyglotTest.java index e56e46d9d5..9e8ba06ab2 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/test/SignaturePolyglotTest.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/test/SignaturePolyglotTest.java @@ -66,7 +66,8 @@ public class SignaturePolyglotTest extends TestBase { var ret = fn.execute(new StringBuilder("Hi")); fail("Should fail, but got: " + ret); } catch (PolyglotException e) { - assertTypeError("`x`", "java.time.format.DateTimeFormatter", "StringBuilder", e.getMessage()); + assertTypeError( + "`x`", "java.time.format.DateTimeFormatter", "java.lang.StringBuilder", e.getMessage()); } } diff --git a/engine/runtime/src/test/java/org/enso/interpreter/test/SignatureTest.java b/engine/runtime/src/test/java/org/enso/interpreter/test/SignatureTest.java index 808b072f72..9cf7c20070 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/test/SignatureTest.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/test/SignatureTest.java @@ -506,7 +506,7 @@ public class SignatureTest extends TestBase { var v = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "Bin.Zero One"); fail("Expecting an error, not " + v); } catch (PolyglotException ex) { - assertTypeError("`v`", "Zero", "Zero", ex.getMessage()); + assertTypeError("`v`", "Zero", "One", ex.getMessage()); } } @@ -639,7 +639,7 @@ public class SignatureTest extends TestBase { var v = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "Bin.Vec 'Hi'"); fail("Expecting an error, not " + v); } catch (PolyglotException ex) { - assertTypeError("`v`", "Integer | Range | Vector", "Integer", ex.getMessage()); + assertTypeError("`v`", "Integer | Range | Vector", "Text", ex.getMessage()); } var ok2 = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "Bin.Either Zero"); assertEquals("binary.Bin", ok2.getMetaObject().getMetaQualifiedName()); @@ -872,7 +872,8 @@ public class SignatureTest extends TestBase { var res = plusChecked.execute("a", "b"); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains( + "expected the result of `plusChecked` to be Integer, but got Text", e.getMessage()); } } @@ -923,7 +924,8 @@ public class SignatureTest extends TestBase { var res = plusChecked.execute(2, 3); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains( + "expected the result of `constant` to be Integer, but got Text", e.getMessage()); } } @@ -944,13 +946,13 @@ public class SignatureTest extends TestBase { .buildLiteral(); var module = ctx.eval(src); - var plusChecked = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "foo"); - assertEquals(8, plusChecked.execute(2).asInt()); + var foo = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "foo"); + assertEquals(8, foo.execute(2).asInt()); try { - var res = plusChecked.execute("."); + var res = foo.execute("."); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains("expected the result of `x` to be Integer, but got Text", e.getMessage()); } } @@ -978,7 +980,7 @@ public class SignatureTest extends TestBase { var res = plusChecked.execute("."); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains("expected the result of `x` to be Integer, but got Text", e.getMessage()); } } @@ -1008,7 +1010,7 @@ public class SignatureTest extends TestBase { var res = foo.execute(2); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains("expected the result of `foo` to be Integer, but got Text", e.getMessage()); } var res = foo.execute(3); @@ -1043,8 +1045,7 @@ public class SignatureTest extends TestBase { var res = factorial.execute(20); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - // TODO we may want to change `expression` to 'the return type' or something - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains("expected the result of `go` to be Integer, but got Text", e.getMessage()); } } @@ -1080,7 +1081,7 @@ public class SignatureTest extends TestBase { var res = foo.execute(n, 1); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertContains("expected the result of `go` to be Integer, but got Text", e.getMessage()); } } @@ -1113,20 +1114,16 @@ public class SignatureTest extends TestBase { var res = foo_bad.execute(n); fail("Expecting an exception, not: " + res); } catch (PolyglotException e) { - assertContains("expected `expression` to be Integer, but got Text", e.getMessage()); + assertEquals( + "Type error: expected the result of `foo_bad` to be Integer, but got Text.", + e.getMessage()); } } static void assertTypeError(String expArg, String expType, String realType, String msg) { - if (!msg.contains(expArg)) { - fail("Expecting value " + expArg + " in " + msg); - } - if (!msg.contains(expType)) { - fail("Expecting value " + expType + " in " + msg); - } - if (!msg.contains(realType)) { - fail("Expecting value " + realType + " in " + msg); - } + assertEquals( + "Type error: expected " + expArg + " to be " + expType + ", but got " + realType + ".", + msg); } private static void assertContains(String exp, String msg) { diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala index b18dc73ce1..b405e7cd56 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/TextTest.scala @@ -117,7 +117,7 @@ class TextTest extends InterpreterTest { |main = | IO.println (List.Cons Nothing Nothing).to_display_text | IO.println (Syntax_Error.Error "foo").to_display_text - | IO.println (Type_Error.Error Nothing List.Nil "myvar").to_display_text + | IO.println (Type_Error.Error Nothing List.Nil "`myvar`").to_display_text | IO.println (Compile_Error.Error "error :(").to_display_text | IO.println (Inexhaustive_Pattern_Match.Error 32).to_display_text | IO.println (Arithmetic_Error.Error "cannot frobnicate quaternions").to_display_text diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso index 205a654c70..9ba09260e4 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso @@ -17,13 +17,13 @@ type Arithmetic_Error @Builtin_Type type Type_Error - Error expected actual name + Error expected actual comment type_of_actual self = tpe = Meta.type_of self.actual if tpe.is_error then self.actual.to_display_text else tpe.to_display_text - to_display_text self = "Type error: expected `"+self.name+"` to be "+self.expected.to_display_text+", but got "+self.type_of_actual+"." + to_display_text self = "Type error: expected "+self.comment+" to be "+self.expected.to_display_text+", but got "+self.type_of_actual+"." @Builtin_Type type Not_Invokable