Skip to content

Commit

Permalink
Merge pull request #1548 from darth-tytus/typeErrorDiagnostic
Browse files Browse the repository at this point in the history
Better errors for type mismatches #1532
  • Loading branch information
mmcgr committed Jul 26, 2020
2 parents 2d9d05a + f44dae0 commit 75477b2
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 59 deletions.
17 changes: 9 additions & 8 deletions src/ErrorReport.h
Expand Up @@ -68,7 +68,7 @@ class DiagnosticMessage {

class Diagnostic {
public:
enum Type { ERROR, WARNING };
enum class Type { ERROR, WARNING };

Diagnostic(Type type, DiagnosticMessage primaryMessage, std::vector<DiagnosticMessage> additionalMessages)
: type(type), primaryMessage(std::move(primaryMessage)),
Expand All @@ -90,7 +90,7 @@ class Diagnostic {
}

void print(std::ostream& out) const {
out << (type == ERROR ? "Error: " : "Warning: ");
out << (type == Type::ERROR ? "Error: " : "Warning: ");
out << primaryMessage;
for (const DiagnosticMessage& additionalMessage : additionalMessages) {
out << additionalMessage;
Expand Down Expand Up @@ -119,10 +119,10 @@ class Diagnostic {
}
}

if (type == ERROR && other.getType() == WARNING) {
if (type == Type::ERROR && other.getType() == Type::WARNING) {
return true;
}
if (other.getType() == ERROR && type == WARNING) {
if (other.getType() == Type::ERROR && type == Type::WARNING) {
return false;
}

Expand Down Expand Up @@ -150,12 +150,12 @@ class ErrorReport {

unsigned getNumErrors() const {
return std::count_if(diagnostics.begin(), diagnostics.end(),
[](Diagnostic d) -> bool { return d.getType() == Diagnostic::ERROR; });
[](Diagnostic d) -> bool { return d.getType() == Diagnostic::Type::ERROR; });
}

unsigned getNumWarnings() const {
return std::count_if(diagnostics.begin(), diagnostics.end(),
[](Diagnostic d) -> bool { return d.getType() == Diagnostic::WARNING; });
[](Diagnostic d) -> bool { return d.getType() == Diagnostic::Type::WARNING; });
}

unsigned getNumIssues() const {
Expand All @@ -164,14 +164,15 @@ class ErrorReport {

/** Adds an error with the given message and location */
void addError(const std::string& message, SrcLocation location) {
diagnostics.insert(Diagnostic(Diagnostic::ERROR, DiagnosticMessage(message, std::move(location))));
diagnostics.insert(
Diagnostic(Diagnostic::Type::ERROR, DiagnosticMessage(message, std::move(location))));
}

/** Adds a warning with the given message and location */
void addWarning(const std::string& message, SrcLocation location) {
if (!nowarn) {
diagnostics.insert(
Diagnostic(Diagnostic::WARNING, DiagnosticMessage(message, std::move(location))));
Diagnostic(Diagnostic::Type::WARNING, DiagnosticMessage(message, std::move(location))));
}
}

Expand Down
11 changes: 6 additions & 5 deletions src/ParserDriver.cpp
Expand Up @@ -100,7 +100,7 @@ void ParserDriver::addPragma(std::unique_ptr<AstPragma> p) {
void ParserDriver::addFunctorDeclaration(std::unique_ptr<AstFunctorDeclaration> f) {
const std::string& name = f->getName();
if (const AstFunctorDeclaration* prev = getFunctorDeclaration(*translationUnit->getProgram(), name)) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition of functor " + toString(name), f->getSrcLoc()),
{DiagnosticMessage("Previous definition", prev->getSrcLoc())});
translationUnit->getErrorReport().addDiagnostic(err);
Expand All @@ -112,7 +112,7 @@ void ParserDriver::addFunctorDeclaration(std::unique_ptr<AstFunctorDeclaration>
void ParserDriver::addRelation(std::unique_ptr<AstRelation> r) {
const auto& name = r->getQualifiedName();
if (AstRelation* prev = getRelation(*translationUnit->getProgram(), name)) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition of relation " + toString(name), r->getSrcLoc()),
{DiagnosticMessage("Previous definition", prev->getSrcLoc())});
translationUnit->getErrorReport().addDiagnostic(err);
Expand All @@ -125,7 +125,7 @@ void ParserDriver::addIO(std::unique_ptr<AstIO> d) {
if (d->getType() == AstIoType::printsize) {
for (const auto& cur : translationUnit->getProgram()->getIOs()) {
if (cur->getQualifiedName() == d->getQualifiedName() && cur->getType() == AstIoType::printsize) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition of printsize directives for relation " +
toString(d->getQualifiedName()),
d->getSrcLoc()),
Expand All @@ -141,7 +141,7 @@ void ParserDriver::addIO(std::unique_ptr<AstIO> d) {
void ParserDriver::addType(std::unique_ptr<AstType> type) {
const auto& name = type->getQualifiedName();
if (const AstType* prev = getType(*translationUnit->getProgram(), name)) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition of type " + toString(name), type->getSrcLoc()),
{DiagnosticMessage("Previous definition", prev->getSrcLoc())});
translationUnit->getErrorReport().addDiagnostic(err);
Expand Down Expand Up @@ -217,7 +217,8 @@ void ParserDriver::error(const SrcLocation& loc, const std::string& msg) {
translationUnit->getErrorReport().addError(msg, loc);
}
void ParserDriver::error(const std::string& msg) {
translationUnit->getErrorReport().addDiagnostic(Diagnostic(Diagnostic::ERROR, DiagnosticMessage(msg)));
translationUnit->getErrorReport().addDiagnostic(
Diagnostic(Diagnostic::Type::ERROR, DiagnosticMessage(msg)));
}

} // end of namespace souffle
17 changes: 13 additions & 4 deletions src/ast/transform/AstSemanticChecker.cpp
Expand Up @@ -231,7 +231,7 @@ AstSemanticCheckerImpl::AstSemanticCheckerImpl(AstTranslationUnit& tu) : tu(tu)
std::string negOrAgg = hasNegation ? "negation" : "aggregation";
messages.push_back(
DiagnosticMessage("has cyclic " + negOrAgg, foundLiteral->getSrcLoc()));
report.addDiagnostic(Diagnostic(Diagnostic::ERROR,
report.addDiagnostic(Diagnostic(Diagnostic::Type::ERROR,
DiagnosticMessage("Unable to stratify relation(s) {" + relationsListStr + "}"),
messages));
break;
Expand Down Expand Up @@ -1187,6 +1187,7 @@ void AstSemanticCheckerImpl::checkNamespaces() {
bool AstExecutionPlanChecker::transform(AstTranslationUnit& translationUnit) {
auto* relationSchedule = translationUnit.getAnalysis<RelationSchedule>();
auto* recursiveClauses = translationUnit.getAnalysis<RecursiveClauses>();
auto&& report = translationUnit.getErrorReport();

for (const RelationScheduleStep& step : relationSchedule->schedule()) {
const std::set<const AstRelation*>& scc = step.computed();
Expand All @@ -1212,7 +1213,7 @@ bool AstExecutionPlanChecker::transform(AstTranslationUnit& translationUnit) {
if (version <= maxVersion) {
for (const auto& cur : clause->getExecutionPlan()->getOrders()) {
if (cur.first >= version) {
translationUnit.getErrorReport().addDiagnostic(Diagnostic(Diagnostic::ERROR,
report.addDiagnostic(Diagnostic(Diagnostic::Type::ERROR,
DiagnosticMessage(
"execution plan for version " + std::to_string(cur.first),
cur.second->getSrcLoc()),
Expand Down Expand Up @@ -1258,8 +1259,16 @@ void TypeChecker::visitAtom(const AstAtom& atom) {
return isA<RecordType>(type) && !isA<SubsetType>(type);
});
if (!validAttribute && !Global::config().has("legacy")) {
report.addError("Atoms argument type is not a subtype of its declared type",
arguments[i]->getSrcLoc());
auto primaryDiagnostic =
DiagnosticMessage("Atom's argument type is not a subtype of its declared type",
arguments[i]->getSrcLoc());

auto declaredTypeInfo =
DiagnosticMessage(tfm::format("The argument's declared type is %s", typeName),
attributes[i]->getSrcLoc());

report.addDiagnostic(Diagnostic(Diagnostic::Type::ERROR, std::move(primaryDiagnostic),
{std::move(declaredTypeInfo)}));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/ast/transform/ComponentInstantiationTransformer.cpp
Expand Up @@ -62,7 +62,7 @@ struct ComponentContent {
return (element->getQualifiedName() == type->getQualifiedName());
});
if (foundItem != types.end()) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage(
"Redefinition of type " + toString(type->getQualifiedName()), type->getSrcLoc()),
{DiagnosticMessage("Previous definition", (*foundItem)->getSrcLoc())});
Expand All @@ -78,7 +78,7 @@ struct ComponentContent {
return (element->getQualifiedName() == rel->getQualifiedName());
});
if (foundItem != relations.end()) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition of relation " + toString(rel->getQualifiedName()),
rel->getSrcLoc()),
{DiagnosticMessage("Previous definition", (*foundItem)->getSrcLoc())});
Expand All @@ -100,7 +100,7 @@ struct ComponentContent {
if (foundItem != ios.end()) {
auto type = (*foundItem)->getType();
if (type == newIO->getType() && newIO->getType() != AstIoType::output) {
Diagnostic err(Diagnostic::ERROR,
Diagnostic err(Diagnostic::Type::ERROR,
DiagnosticMessage("Redefinition I/O operation " + toString(newIO->getQualifiedName()),
newIO->getSrcLoc()),
{DiagnosticMessage("Previous definition", (*foundItem)->getSrcLoc())});
Expand Down
30 changes: 24 additions & 6 deletions tests/semantic/extended_subtypes3/extended_subtypes3.err
@@ -1,19 +1,37 @@
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 20
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 20
SymbolChain(a, a, a) :- SymbolChain(a, _, _).
---------------^------------------------------
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 20
The argument's declared type is symbolB in file extended_subtypes3.dl at line 18
.decl SymbolChain(a: symbolA, b: symbolB, c: symbolC)
---------------------------------^--------------------
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 20
SymbolChain(a, a, a) :- SymbolChain(a, _, _).
------------------^---------------------------
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 21
The argument's declared type is symbolC in file extended_subtypes3.dl at line 18
.decl SymbolChain(a: symbolA, b: symbolB, c: symbolC)
---------------------------------------------^--------
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 21
SymbolChain(b, b, b) :- SymbolChain(_, b, _).
------------------^---------------------------
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 33
The argument's declared type is symbolC in file extended_subtypes3.dl at line 18
.decl SymbolChain(a: symbolA, b: symbolB, c: symbolC)
---------------------------------------------^--------
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 33
RecordSubtypes(x, [1, x], x) :- RecordSubtypes(x, _, _). // error in [1, x] and x
--------------------------^-------------------------------------------------------
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 34
The argument's declared type is S2List in file extended_subtypes3.dl at line 31
.decl RecordSubtypes(a: List, b: S1List, c: S2List)
--------------------------------------------^-------
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 34
RecordSubtypes(y, y, y) :- RecordSubtypes(y, _, _). // Should be error in second place and third place.
------------------^-------------------------------------------------------------------------------------
Error: Atoms argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 34
The argument's declared type is S1List in file extended_subtypes3.dl at line 31
.decl RecordSubtypes(a: List, b: S1List, c: S2List)
---------------------------------^------------------
Error: Atom's argument type is not a subtype of its declared type in file extended_subtypes3.dl at line 34
RecordSubtypes(y, y, y) :- RecordSubtypes(y, _, _). // Should be error in second place and third place.
---------------------^----------------------------------------------------------------------------------
The argument's declared type is S2List in file extended_subtypes3.dl at line 31
.decl RecordSubtypes(a: List, b: S1List, c: S2List)
--------------------------------------------^-------
6 errors generated, evaluation aborted
35 changes: 28 additions & 7 deletions tests/semantic/rule_typecompat/rule_typecompat.err
Expand Up @@ -13,9 +13,12 @@ Warning: No rules/facts defined for relation D in file rule_typecompat.dl at lin
Warning: No rules/facts defined for relation E in file rule_typecompat.dl at line 10
.decl E (r:R, s:S)
------^------------
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 15
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 15
A(x) :- B(x).
--^-----------
The argument's declared type is T in file rule_typecompat.dl at line 6
.decl A (t:T)
-----------^--
Error: Unable to deduce type for variable x in file rule_typecompat.dl at line 18
A(x) :- F(x,x).
--^-------------
Expand All @@ -40,9 +43,12 @@ A(x) :- G(x,x).
Warning: Variable y only occurs once in file rule_typecompat.dl at line 25
A(x) :- G(x,y).
------------^---
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 28
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 28
G(x,x) :- A(x).
----^-----------
The argument's declared type is R in file rule_typecompat.dl at line 12
.decl G (t:T, r:R)
----------------^--
Error: Ungrounded variable y in file rule_typecompat.dl at line 30
G(x,y) :- A(x).
----^-----------
Expand All @@ -64,9 +70,12 @@ A(x) :- A(x), B(y), C(z).
Warning: Variable z only occurs once in file rule_typecompat.dl at line 36
A(x) :- A(x), B(y), C(z).
----------------------^---
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 39
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 39
F(x,y) :- F(x,z), G(z,y).
----^---------------------
The argument's declared type is T in file rule_typecompat.dl at line 11
.decl F (r:R, t:T)
----------------^--
Error: Ungrounded variable y in file rule_typecompat.dl at line 41
F(x,y) :- F(x,z), G(z,x).
----^---------------------
Expand Down Expand Up @@ -112,21 +121,33 @@ F(x,y) :- F(x,v), F(w,y), A(w), D(v).
Warning: Variable w only occurs once in file rule_typecompat.dl at line 52
F(x,y) :- F(x,v), F(w,y), !H(v), !D(v).
--------------------^-------------------
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 52
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 52
F(x,y) :- F(x,v), F(w,y), !H(v), !D(v).
------------------------------------^---
The argument's declared type is R in file rule_typecompat.dl at line 9
.decl D (r:R)
-----------^--
Warning: Variable v only occurs once in file rule_typecompat.dl at line 53
F(x,y) :- F(x,v), F(w,y), !H(w), !D(w).
--------------^-------------------------
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 53
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 53
F(x,y) :- F(x,v), F(w,y), !H(w), !D(w).
-----------------------------^----------
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 54
The argument's declared type is T in file rule_typecompat.dl at line 5
.decl H (t:T)
-----------^--
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 54
F(x,y) :- F(x,v), F(w,y), !H(w), !D(v).
-----------------------------^----------
Error: Atoms argument type is not a subtype of its declared type in file rule_typecompat.dl at line 54
The argument's declared type is T in file rule_typecompat.dl at line 5
.decl H (t:T)
-----------^--
Error: Atom's argument type is not a subtype of its declared type in file rule_typecompat.dl at line 54
F(x,y) :- F(x,v), F(w,y), !H(w), !D(v).
------------------------------------^---
The argument's declared type is R in file rule_typecompat.dl at line 9
.decl D (r:R)
-----------^--
Error: Unable to deduce type for variable x in file rule_typecompat.dl at line 57
F(x,y) :- F(x,y), x > y.
--^-----------------------
Expand Down
5 changes: 4 additions & 1 deletion tests/semantic/type_as2/type_as2.err
@@ -1,6 +1,9 @@
Error: Atoms argument type is not a subtype of its declared type in file type_as2.dl at line 22
Error: Atom's argument type is not a subtype of its declared type in file type_as2.dl at line 22
B(as(x, symbol)) :- A(x).
--^-----------------------
The argument's declared type is symbol1 in file type_as2.dl at line 21
.decl B(x: symbol1)
-----------^--------
Error: Unable to deduce type of the argument (cast) in file type_as2.dl at line 23
B(as(x, float)) :- A(x).
--^----------------------
Expand Down
15 changes: 12 additions & 3 deletions tests/semantic/type_system12/type_system12.err
@@ -1,10 +1,19 @@
Error: Atoms argument type is not a subtype of its declared type in file type_system12.dl at line 38
Error: Atom's argument type is not a subtype of its declared type in file type_system12.dl at line 38
C(x) :- B(x). // Error
--^-----------------------------------------
Error: Atoms argument type is not a subtype of its declared type in file type_system12.dl at line 39
The argument's declared type is S1 in file type_system12.dl at line 37
.decl C(x : S1)
------------^---
Error: Atom's argument type is not a subtype of its declared type in file type_system12.dl at line 39
C(x) :- !A(x), B(x). // Error
--^-----------------------------------------
Error: Atoms argument type is not a subtype of its declared type in file type_system12.dl at line 39
The argument's declared type is S1 in file type_system12.dl at line 37
.decl C(x : S1)
------------^---
Error: Atom's argument type is not a subtype of its declared type in file type_system12.dl at line 39
C(x) :- !A(x), B(x). // Error
-----------^--------------------------------
The argument's declared type is S2 in file type_system12.dl at line 23
.decl A(x : S2)
------------^---
3 errors generated, evaluation aborted
5 changes: 4 additions & 1 deletion tests/semantic/type_system14/type_system14.err
@@ -1,4 +1,7 @@
Error: Atoms argument type is not a subtype of its declared type in file type_system14.dl at line 24
Error: Atom's argument type is not a subtype of its declared type in file type_system14.dl at line 24
RG(val) :- RD(val), RE(cat("",val)).
---^---------------------------------
The argument's declared type is B in file type_system14.dl at line 21
.decl RG(x:B)
-----------^--
1 errors generated, evaluation aborted

0 comments on commit 75477b2

Please sign in to comment.