aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Parpart <christian@ethereum.org>2018-07-02 23:00:09 +0800
committerchriseth <chris@ethereum.org>2018-07-11 04:14:19 +0800
commit1505e28b56c3a90abdb606ed1389394d7918d7eb (patch)
treedc7e6da3a8ce720de73313065cceb6ec9f34cc9b
parentd84976dc871a1fdfab233650b989af69e325bf2b (diff)
downloaddexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar.gz
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar.bz2
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar.lz
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar.xz
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.tar.zst
dexon-solidity-1505e28b56c3a90abdb606ed1389394d7918d7eb.zip
semantics: Suggest auto-deduced type when user declares variable with `var` keyword.
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp9
-rw-r--r--libsolidity/analysis/SyntaxChecker.h2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp76
-rw-r--r--test/libsolidity/syntaxTests/types/var_type_suggest.sol23
4 files changed, 91 insertions, 19 deletions
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 63f8fac3..4311e77d 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -254,15 +254,6 @@ bool SyntaxChecker::visit(FunctionTypeName const& _node)
return true;
}
-bool SyntaxChecker::visit(VariableDeclaration const& _declaration)
-{
- if (!_declaration.typeName())
- {
- m_errorReporter.syntaxError(_declaration.location(), "Use of the \"var\" keyword is disallowed.");
- }
- return true;
-}
-
bool SyntaxChecker::visit(StructDefinition const& _struct)
{
if (_struct.members().empty())
diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h
index 1579df57..8ee3df37 100644
--- a/libsolidity/analysis/SyntaxChecker.h
+++ b/libsolidity/analysis/SyntaxChecker.h
@@ -69,8 +69,6 @@ private:
virtual bool visit(FunctionDefinition const& _function) override;
virtual bool visit(FunctionTypeName const& _node) override;
- virtual bool visit(VariableDeclaration const& _declaration) override;
-
virtual bool visit(StructDefinition const& _struct) override;
ErrorReporter& m_errorReporter;
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 78536664..9de7829c 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -23,6 +23,7 @@
#include <libsolidity/analysis/TypeChecker.h>
#include <memory>
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <libsolidity/ast/AST.h>
#include <libsolidity/inlineasm/AsmAnalysis.h>
@@ -1051,6 +1052,49 @@ void TypeChecker::endVisit(EmitStatement const& _emit)
m_insideEmitStatement = false;
}
+/**
+ * Creates a tuple declaration syntax from a vector of variable declarations.
+ *
+ * @param decls a tuple of variables
+ *
+ * @returns a Solidity language confirming string of a tuple variable declaration.
+ */
+static string createTupleDecl(vector<VariableDeclaration const*> const & decls)
+{
+ vector<string> components;
+ for (VariableDeclaration const* decl : decls)
+ if (decl)
+ components.emplace_back(decl->annotation().type->toString(false) + " " + decl->name());
+ else
+ components.emplace_back();
+
+ if (decls.size() == 1)
+ return components.front();
+ else
+ return "(" + boost::algorithm::join(components, ", ") + ")";
+}
+
+static bool typeCanBeExpressed(vector<VariableDeclaration const*> const & decls)
+{
+ for (VariableDeclaration const* decl : decls)
+ {
+ // skip empty tuples (they can be expressed of course)
+ if (!decl)
+ continue;
+
+ if (auto functionType = dynamic_cast<FunctionType const*>(decl->annotation().type.get()))
+ {
+ if (
+ functionType->kind() != FunctionType::Kind::Internal &&
+ functionType->kind() != FunctionType::Kind::External
+ )
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
{
bool const v050 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
@@ -1161,6 +1205,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
else
assignments[assignments.size() - i - 1] = variables[variables.size() - i - 1].get();
+ bool autoTypeDeductionNeeded = false;
+
for (size_t i = 0; i < assignments.size(); ++i)
{
if (!assignments[i])
@@ -1171,6 +1217,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
solAssert(!!valueComponentType, "");
if (!var.annotation().type)
{
+ autoTypeDeductionNeeded = true;
+
// Infer type from value.
solAssert(!var.typeName(), "");
var.annotation().type = valueComponentType->mobileType();
@@ -1214,14 +1262,6 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
}
else
solAssert(dynamic_cast<FixedPointType const*>(var.annotation().type.get()), "Unknown type.");
-
- m_errorReporter.warning(
- _statement.location(),
- "The type of this variable was inferred as " +
- typeName +
- extension +
- ". This is probably not desired. Use an explicit type to silence this warning."
- );
}
var.accept(*this);
@@ -1258,6 +1298,26 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
}
}
}
+
+ if (autoTypeDeductionNeeded)
+ {
+ if (!typeCanBeExpressed(assignments))
+ {
+ m_errorReporter.syntaxError(_statement.location(),
+ "Use of the \"var\" keyword is disallowed. "
+ "Type cannot be expressed in syntax.");
+ }
+ else
+ {
+ // report with trivial snipped `uint i = ...`
+ string const typeName = createTupleDecl(assignments);
+
+ m_errorReporter.syntaxError(_statement.location(),
+ "Use of the \"var\" keyword is disallowed. "
+ "Use explicit declaration `" + typeName + " = ...´ instead.");
+ }
+ }
+
return false;
}
diff --git a/test/libsolidity/syntaxTests/types/var_type_suggest.sol b/test/libsolidity/syntaxTests/types/var_type_suggest.sol
new file mode 100644
index 00000000..176fab96
--- /dev/null
+++ b/test/libsolidity/syntaxTests/types/var_type_suggest.sol
@@ -0,0 +1,23 @@
+contract C {
+ function h() internal pure returns (uint, uint, uint) {
+ return (1, 2, 4);
+ }
+ function g(uint x) internal pure returns (uint) {
+ return x;
+ }
+ function f() internal pure {
+ var i = 31415;
+ var t = "string";
+ var g2 = g;
+ var myblockhash = block.blockhash;
+ var (a, b) = (2, "troi");
+ var (x,, z) = h();
+ }
+}
+// ----
+// SyntaxError: (224-237): Use of the "var" keyword is disallowed. Use explicit declaration `uint16 i = ...´ instead.
+// SyntaxError: (247-263): Use of the "var" keyword is disallowed. Use explicit declaration `string memory t = ...´ instead.
+// SyntaxError: (273-283): Use of the "var" keyword is disallowed. Use explicit declaration `function (uint256) pure returns (uint256) g2 = ...´ instead.
+// SyntaxError: (293-326): Use of the "var" keyword is disallowed. Type cannot be expressed in syntax.
+// SyntaxError: (336-360): Use of the "var" keyword is disallowed. Use explicit declaration `(uint8 a, string memory b) = ...´ instead.
+// SyntaxError: (370-387): Use of the "var" keyword is disallowed. Use explicit declaration `(uint256 x, , uint256 z) = ...´ instead.