inferencer: significantly improve the op-assignment diagnostic.

Before this commit, it displayed incorrect output if an error
appeared on 2nd run and beyond, and displayed messages for trying
to do "num32 -= num64" that made very little sense.
This commit is contained in:
whitequark 2016-11-21 13:08:03 +00:00
parent 3485c83429
commit 35f4449ef2
2 changed files with 25 additions and 20 deletions

View File

@ -1043,22 +1043,10 @@ class Inferencer(algorithm.Visitor):
if coerced:
return_type, target_type, value_type = coerced
try:
node.target.type.unify(target_type)
except types.UnificationError as e:
printer = types.TypePrinter()
note = diagnostic.Diagnostic("note",
"expression of type {typec}",
{"typec": printer.name(node.value.type)},
node.value.loc)
diag = diagnostic.Diagnostic("error",
"expression of type {typea} has to be coerced to {typeb}, "
"which makes assignment invalid",
{"typea": printer.name(node.target.type),
"typeb": printer.name(target_type)},
node.op.loc, [node.target.loc], [note])
self.engine.process(diag)
return
if isinstance(node.value, asttyped.CoerceT):
orig_value_type = node.value.value.type
else:
orig_value_type = node.value.type
try:
node.target.type.unify(return_type)
@ -1066,17 +1054,34 @@ class Inferencer(algorithm.Visitor):
printer = types.TypePrinter()
note = diagnostic.Diagnostic("note",
"expression of type {typec}",
{"typec": printer.name(node.value.type)},
{"typec": printer.name(orig_value_type)},
node.value.loc)
diag = diagnostic.Diagnostic("error",
"the result of this operation has type {typeb}, "
"which makes assignment to a slot of type {typea} invalid",
"which cannot be assigned to a left-hand side of type {typea}",
{"typea": printer.name(node.target.type),
"typeb": printer.name(return_type)},
node.op.loc, [node.target.loc], [note])
self.engine.process(diag)
return
try:
node.target.type.unify(target_type)
except types.UnificationError as e:
printer = types.TypePrinter()
note = diagnostic.Diagnostic("note",
"expression of type {typec}",
{"typec": printer.name(orig_value_type)},
node.value.loc)
diag = diagnostic.Diagnostic("error",
"this operation requires the left-hand side of type {typea} "
"to be coerced to {typeb}, which cannot be done",
{"typea": printer.name(node.target.type),
"typeb": printer.name(target_type)},
node.op.loc, [node.target.loc], [note])
self.engine.process(diag)
return
node.value = self._coerce_one(value_type, node.value, other_node=node.target)
def visit_ForT(self, node):

View File

@ -28,10 +28,10 @@
# CHECK-L: ${LINE:+1}: error: cannot coerce list(elt='a) to a numeric type
[] - 1.0
# CHECK-L: ${LINE:+2}: error: expression of type numpy.int? has to be coerced to float, which makes assignment invalid
# CHECK-L: ${LINE:+2}: error: the result of this operation has type float, which cannot be assigned to a left-hand side of type numpy.int?
# CHECK-L: ${LINE:+1}: note: expression of type float
a = 1; a += 1.0
# CHECK-L: ${LINE:+2}: error: the result of this operation has type (numpy.int?, float), which makes assignment to a slot of type (numpy.int?,) invalid
# CHECK-L: ${LINE:+2}: error: the result of this operation has type (numpy.int?, float), which cannot be assigned to a left-hand side of type (numpy.int?,)
# CHECK-L: ${LINE:+1}: note: expression of type (float,)
b = (1,); b += (1.0,)