mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge a47aa09bb4
into bdd2f02c83
This commit is contained in:
commit
d15d8f3648
@ -188,6 +188,8 @@ set(sources
|
|||||||
experimental/analysis/Analysis.h
|
experimental/analysis/Analysis.h
|
||||||
experimental/analysis/DebugWarner.cpp
|
experimental/analysis/DebugWarner.cpp
|
||||||
experimental/analysis/DebugWarner.h
|
experimental/analysis/DebugWarner.h
|
||||||
|
experimental/analysis/TypeClassMemberRegistration.cpp
|
||||||
|
experimental/analysis/TypeClassMemberRegistration.h
|
||||||
experimental/analysis/TypeClassRegistration.cpp
|
experimental/analysis/TypeClassRegistration.cpp
|
||||||
experimental/analysis/TypeClassRegistration.h
|
experimental/analysis/TypeClassRegistration.h
|
||||||
experimental/analysis/TypeInference.cpp
|
experimental/analysis/TypeInference.cpp
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||||
#include <libsolidity/experimental/analysis/DebugWarner.h>
|
#include <libsolidity/experimental/analysis/DebugWarner.h>
|
||||||
#include <libsolidity/experimental/analysis/SyntaxRestrictor.h>
|
#include <libsolidity/experimental/analysis/SyntaxRestrictor.h>
|
||||||
|
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeInference.h>
|
#include <libsolidity/experimental/analysis/TypeInference.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||||
@ -28,6 +29,7 @@ using namespace solidity::frontend::experimental;
|
|||||||
// TODO: creating all of them for all nodes up front may be wasteful, we should improve the mechanism.
|
// TODO: creating all of them for all nodes up front may be wasteful, we should improve the mechanism.
|
||||||
struct Analysis::AnnotationContainer
|
struct Analysis::AnnotationContainer
|
||||||
{
|
{
|
||||||
|
TypeClassMemberRegistration::Annotation typeClassMemberRegistrationAnnotation;
|
||||||
TypeClassRegistration::Annotation typeClassRegistrationAnnotation;
|
TypeClassRegistration::Annotation typeClassRegistrationAnnotation;
|
||||||
TypeRegistration::Annotation typeRegistrationAnnotation;
|
TypeRegistration::Annotation typeRegistrationAnnotation;
|
||||||
TypeInference::Annotation typeInferenceAnnotation;
|
TypeInference::Annotation typeInferenceAnnotation;
|
||||||
@ -35,11 +37,37 @@ struct Analysis::AnnotationContainer
|
|||||||
|
|
||||||
struct Analysis::GlobalAnnotationContainer
|
struct Analysis::GlobalAnnotationContainer
|
||||||
{
|
{
|
||||||
|
TypeClassMemberRegistration::GlobalAnnotation typeClassMemberRegistrationAnnotation;
|
||||||
TypeClassRegistration::GlobalAnnotation typeClassRegistrationAnnotation;
|
TypeClassRegistration::GlobalAnnotation typeClassRegistrationAnnotation;
|
||||||
TypeRegistration::GlobalAnnotation typeRegistrationAnnotation;
|
TypeRegistration::GlobalAnnotation typeRegistrationAnnotation;
|
||||||
TypeInference::GlobalAnnotation typeInferenceAnnotation;
|
TypeInference::GlobalAnnotation typeInferenceAnnotation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
TypeClassMemberRegistration::Annotation& solidity::frontend::experimental::detail::AnnotationFetcher<TypeClassMemberRegistration>::get(ASTNode const& _node)
|
||||||
|
{
|
||||||
|
return analysis.annotationContainer(_node).typeClassMemberRegistrationAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
TypeClassMemberRegistration::GlobalAnnotation const& solidity::frontend::experimental::detail::ConstAnnotationFetcher<TypeClassMemberRegistration>::get() const
|
||||||
|
{
|
||||||
|
return analysis.annotationContainer().typeClassMemberRegistrationAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
TypeClassMemberRegistration::GlobalAnnotation& solidity::frontend::experimental::detail::AnnotationFetcher<TypeClassMemberRegistration>::get()
|
||||||
|
{
|
||||||
|
return analysis.annotationContainer().typeClassMemberRegistrationAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
TypeClassMemberRegistration::Annotation const& solidity::frontend::experimental::detail::ConstAnnotationFetcher<TypeClassMemberRegistration>::get(ASTNode const& _node) const
|
||||||
|
{
|
||||||
|
return analysis.annotationContainer(_node).typeClassMemberRegistrationAnnotation;
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
TypeClassRegistration::Annotation& solidity::frontend::experimental::detail::AnnotationFetcher<TypeClassRegistration>::get(ASTNode const& _node)
|
TypeClassRegistration::Annotation& solidity::frontend::experimental::detail::AnnotationFetcher<TypeClassRegistration>::get(ASTNode const& _node)
|
||||||
{
|
{
|
||||||
@ -153,6 +181,7 @@ bool Analysis::check(std::vector<std::shared_ptr<SourceUnit const>> const& _sour
|
|||||||
SyntaxRestrictor,
|
SyntaxRestrictor,
|
||||||
TypeClassRegistration,
|
TypeClassRegistration,
|
||||||
TypeRegistration,
|
TypeRegistration,
|
||||||
|
TypeClassMemberRegistration,
|
||||||
TypeInference,
|
TypeInference,
|
||||||
DebugWarner
|
DebugWarner
|
||||||
>;
|
>;
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
|
||||||
|
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||||
|
|
||||||
|
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||||
|
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||||
|
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||||
|
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
|
||||||
|
|
||||||
|
#include <liblangutil/ErrorReporter.h>
|
||||||
|
#include <liblangutil/Exceptions.h>
|
||||||
|
|
||||||
|
using namespace solidity::frontend::experimental;
|
||||||
|
using namespace solidity::langutil;
|
||||||
|
|
||||||
|
TypeClassMemberRegistration::TypeClassMemberRegistration(Analysis& _analysis):
|
||||||
|
m_analysis(_analysis),
|
||||||
|
m_errorReporter(_analysis.errorReporter()),
|
||||||
|
m_typeSystem(_analysis.typeSystem())
|
||||||
|
{
|
||||||
|
TypeSystemHelpers helper{m_typeSystem};
|
||||||
|
|
||||||
|
auto registeredTypeClass = [&](BuiltinClass _builtinClass) -> TypeClass {
|
||||||
|
return m_analysis.annotation<TypeClassRegistration>().builtinClasses.at(_builtinClass);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto defineConversion = [&](BuiltinClass _builtinClass, PrimitiveType _fromType, std::string _functionName) {
|
||||||
|
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
||||||
|
std::move(_functionName),
|
||||||
|
helper.functionType(
|
||||||
|
m_typeSystem.type(_fromType, {}),
|
||||||
|
m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable
|
||||||
|
),
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto defineBinaryMonoidalOperator = [&](BuiltinClass _builtinClass, Token _token, std::string _functionName) {
|
||||||
|
Type typeVar = m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable;
|
||||||
|
annotation().operators.emplace(_token, std::make_tuple(registeredTypeClass(_builtinClass), _functionName));
|
||||||
|
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
||||||
|
std::move(_functionName),
|
||||||
|
helper.functionType(
|
||||||
|
helper.tupleType({typeVar, typeVar}),
|
||||||
|
typeVar
|
||||||
|
)
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
|
||||||
|
auto defineBinaryCompareOperator = [&](BuiltinClass _builtinClass, Token _token, std::string _functionName) {
|
||||||
|
Type typeVar = m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable;
|
||||||
|
annotation().operators.emplace(_token, std::make_tuple(registeredTypeClass(_builtinClass), _functionName));
|
||||||
|
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
||||||
|
std::move(_functionName),
|
||||||
|
helper.functionType(
|
||||||
|
helper.tupleType({typeVar, typeVar}),
|
||||||
|
m_typeSystem.type(PrimitiveType::Bool, {})
|
||||||
|
)
|
||||||
|
}};
|
||||||
|
};
|
||||||
|
|
||||||
|
defineConversion(BuiltinClass::Integer, PrimitiveType::Integer, "fromInteger");
|
||||||
|
|
||||||
|
defineBinaryMonoidalOperator(BuiltinClass::Mul, Token::Mul, "mul");
|
||||||
|
defineBinaryMonoidalOperator(BuiltinClass::Add, Token::Add, "add");
|
||||||
|
|
||||||
|
defineBinaryCompareOperator(BuiltinClass::Equal, Token::Equal, "eq");
|
||||||
|
defineBinaryCompareOperator(BuiltinClass::Less, Token::LessThan, "lt");
|
||||||
|
defineBinaryCompareOperator(BuiltinClass::LessOrEqual, Token::LessThanOrEqual, "leq");
|
||||||
|
defineBinaryCompareOperator(BuiltinClass::Greater, Token::GreaterThan, "gt");
|
||||||
|
defineBinaryCompareOperator(BuiltinClass::GreaterOrEqual, Token::GreaterThanOrEqual, "geq");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TypeClassMemberRegistration::analyze(SourceUnit const& _sourceUnit)
|
||||||
|
{
|
||||||
|
_sourceUnit.accept(*this);
|
||||||
|
return !m_errorReporter.hasErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TypeClassMemberRegistration::endVisit(TypeClassDefinition const& _typeClassDefinition)
|
||||||
|
{
|
||||||
|
solAssert(m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.has_value());
|
||||||
|
TypeClass typeClass = m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.value();
|
||||||
|
|
||||||
|
_typeClassDefinition.typeVariable().accept(*this);
|
||||||
|
|
||||||
|
std::map<std::string, Type> functionTypes;
|
||||||
|
for (auto subNode: _typeClassDefinition.subNodes())
|
||||||
|
{
|
||||||
|
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(subNode.get());
|
||||||
|
solAssert(functionDefinition);
|
||||||
|
|
||||||
|
std::optional<Type> functionType = TypeSystemHelpers{m_typeSystem}.functionType(
|
||||||
|
m_typeSystem.freshTypeVariable({}),
|
||||||
|
m_typeSystem.freshTypeVariable({})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!functionTypes.emplace(functionDefinition->name(), functionType.value()).second)
|
||||||
|
m_errorReporter.fatalTypeError(
|
||||||
|
3195_error,
|
||||||
|
// TODO: Secondary location with previous definition
|
||||||
|
functionDefinition->location(),
|
||||||
|
"Function in type class declared multiple times."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
annotation().typeClassFunctions[typeClass] = std::move(functionTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeClassMemberRegistration::Annotation& TypeClassMemberRegistration::annotation(ASTNode const& _node)
|
||||||
|
{
|
||||||
|
return m_analysis.annotation<TypeClassMemberRegistration>(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeClassMemberRegistration::Annotation const& TypeClassMemberRegistration::annotation(ASTNode const& _node) const
|
||||||
|
{
|
||||||
|
return m_analysis.annotation<TypeClassMemberRegistration>(_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeClassMemberRegistration::GlobalAnnotation& TypeClassMemberRegistration::annotation()
|
||||||
|
{
|
||||||
|
return m_analysis.annotation<TypeClassMemberRegistration>();
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
|
#include <libsolidity/experimental/ast/TypeSystem.h>
|
||||||
|
|
||||||
|
namespace solidity::langutil
|
||||||
|
{
|
||||||
|
class ErrorReporter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace solidity::frontend::experimental
|
||||||
|
{
|
||||||
|
|
||||||
|
class Analysis;
|
||||||
|
class TypeSystem;
|
||||||
|
|
||||||
|
class TypeClassMemberRegistration: public ASTConstVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Annotation
|
||||||
|
{
|
||||||
|
};
|
||||||
|
struct GlobalAnnotation
|
||||||
|
{
|
||||||
|
std::map<TypeClass, std::map<std::string, Type>> typeClassFunctions;
|
||||||
|
std::map<Token, std::tuple<TypeClass, std::string>> operators;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeClassMemberRegistration(Analysis& _analysis);
|
||||||
|
|
||||||
|
bool analyze(SourceUnit const& _sourceUnit);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void endVisit(TypeClassDefinition const& _typeClassDefinition) override;
|
||||||
|
|
||||||
|
Annotation& annotation(ASTNode const& _node);
|
||||||
|
Annotation const& annotation(ASTNode const& _node) const;
|
||||||
|
GlobalAnnotation& annotation();
|
||||||
|
|
||||||
|
Analysis& m_analysis;
|
||||||
|
langutil::ErrorReporter& m_errorReporter;
|
||||||
|
TypeSystem& m_typeSystem;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -32,6 +32,30 @@ TypeClassRegistration::TypeClassRegistration(Analysis& _analysis):
|
|||||||
m_errorReporter(_analysis.errorReporter()),
|
m_errorReporter(_analysis.errorReporter()),
|
||||||
m_typeSystem(_analysis.typeSystem())
|
m_typeSystem(_analysis.typeSystem())
|
||||||
{
|
{
|
||||||
|
auto declareBuiltinClass = [&](std::string _name, BuiltinClass _class) -> TypeClass {
|
||||||
|
Type type = m_typeSystem.freshTypeVariable({});
|
||||||
|
auto result = m_typeSystem.declareTypeClass(
|
||||||
|
type,
|
||||||
|
_name,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
if (auto error = std::get_if<std::string>(&result))
|
||||||
|
solAssert(!error, *error);
|
||||||
|
TypeClass declaredClass = std::get<TypeClass>(result);
|
||||||
|
// TODO: validation?
|
||||||
|
GlobalAnnotation& annotation = m_analysis.annotation<TypeClassRegistration>();
|
||||||
|
solAssert(annotation.builtinClassesByName.emplace(_name, _class).second);
|
||||||
|
return annotation.builtinClasses.emplace(_class, declaredClass).first->second;
|
||||||
|
};
|
||||||
|
|
||||||
|
declareBuiltinClass("integer", BuiltinClass::Integer);
|
||||||
|
declareBuiltinClass("*", BuiltinClass::Mul);
|
||||||
|
declareBuiltinClass("+", BuiltinClass::Add);
|
||||||
|
declareBuiltinClass("==", BuiltinClass::Equal);
|
||||||
|
declareBuiltinClass("<", BuiltinClass::Less);
|
||||||
|
declareBuiltinClass("<=", BuiltinClass::LessOrEqual);
|
||||||
|
declareBuiltinClass(">", BuiltinClass::Greater);
|
||||||
|
declareBuiltinClass(">=", BuiltinClass::GreaterOrEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeClassRegistration::analyze(SourceUnit const& _sourceUnit)
|
bool TypeClassRegistration::analyze(SourceUnit const& _sourceUnit)
|
||||||
|
@ -41,6 +41,8 @@ public:
|
|||||||
};
|
};
|
||||||
struct GlobalAnnotation
|
struct GlobalAnnotation
|
||||||
{
|
{
|
||||||
|
std::map<BuiltinClass, TypeClass> builtinClasses;
|
||||||
|
std::map<std::string, BuiltinClass> builtinClassesByName;
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeClassRegistration(Analysis& _analysis);
|
TypeClassRegistration(Analysis& _analysis);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <libsolidity/experimental/analysis/TypeInference.h>
|
#include <libsolidity/experimental/analysis/TypeInference.h>
|
||||||
|
|
||||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||||
|
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||||
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
|
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
|
||||||
@ -51,80 +52,6 @@ TypeInference::TypeInference(Analysis& _analysis):
|
|||||||
m_unitType(m_typeSystem.type(PrimitiveType::Unit, {})),
|
m_unitType(m_typeSystem.type(PrimitiveType::Unit, {})),
|
||||||
m_boolType(m_typeSystem.type(PrimitiveType::Bool, {}))
|
m_boolType(m_typeSystem.type(PrimitiveType::Bool, {}))
|
||||||
{
|
{
|
||||||
TypeSystemHelpers helper{m_typeSystem};
|
|
||||||
|
|
||||||
auto declareBuiltinClass = [&](std::string _name, BuiltinClass _class) -> TypeClass {
|
|
||||||
Type type = m_typeSystem.freshTypeVariable({});
|
|
||||||
auto result = m_typeSystem.declareTypeClass(
|
|
||||||
type,
|
|
||||||
_name,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
if (auto error = std::get_if<std::string>(&result))
|
|
||||||
solAssert(!error, *error);
|
|
||||||
TypeClass declaredClass = std::get<TypeClass>(result);
|
|
||||||
// TODO: validation?
|
|
||||||
solAssert(annotation().builtinClassesByName.emplace(_name, _class).second);
|
|
||||||
return annotation().builtinClasses.emplace(_class, declaredClass).first->second;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto registeredTypeClass = [&](BuiltinClass _builtinClass) -> TypeClass {
|
|
||||||
return annotation().builtinClasses.at(_builtinClass);
|
|
||||||
};
|
|
||||||
|
|
||||||
auto defineConversion = [&](BuiltinClass _builtinClass, PrimitiveType _fromType, std::string _functionName) {
|
|
||||||
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
|
||||||
std::move(_functionName),
|
|
||||||
helper.functionType(
|
|
||||||
m_typeSystem.type(_fromType, {}),
|
|
||||||
m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable
|
|
||||||
),
|
|
||||||
}};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto defineBinaryMonoidalOperator = [&](BuiltinClass _builtinClass, Token _token, std::string _functionName) {
|
|
||||||
Type typeVar = m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable;
|
|
||||||
annotation().operators.emplace(_token, std::make_tuple(registeredTypeClass(_builtinClass), _functionName));
|
|
||||||
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
|
||||||
std::move(_functionName),
|
|
||||||
helper.functionType(
|
|
||||||
helper.tupleType({typeVar, typeVar}),
|
|
||||||
typeVar
|
|
||||||
)
|
|
||||||
}};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto defineBinaryCompareOperator = [&](BuiltinClass _builtinClass, Token _token, std::string _functionName) {
|
|
||||||
Type typeVar = m_typeSystem.typeClassInfo(registeredTypeClass(_builtinClass)).typeVariable;
|
|
||||||
annotation().operators.emplace(_token, std::make_tuple(registeredTypeClass(_builtinClass), _functionName));
|
|
||||||
annotation().typeClassFunctions[registeredTypeClass(_builtinClass)] = {{
|
|
||||||
std::move(_functionName),
|
|
||||||
helper.functionType(
|
|
||||||
helper.tupleType({typeVar, typeVar}),
|
|
||||||
m_typeSystem.type(PrimitiveType::Bool, {})
|
|
||||||
)
|
|
||||||
}};
|
|
||||||
};
|
|
||||||
|
|
||||||
declareBuiltinClass("integer", BuiltinClass::Integer);
|
|
||||||
declareBuiltinClass("*", BuiltinClass::Mul);
|
|
||||||
declareBuiltinClass("+", BuiltinClass::Add);
|
|
||||||
declareBuiltinClass("==", BuiltinClass::Equal);
|
|
||||||
declareBuiltinClass("<", BuiltinClass::Less);
|
|
||||||
declareBuiltinClass("<=", BuiltinClass::LessOrEqual);
|
|
||||||
declareBuiltinClass(">", BuiltinClass::Greater);
|
|
||||||
declareBuiltinClass(">=", BuiltinClass::GreaterOrEqual);
|
|
||||||
|
|
||||||
defineConversion(BuiltinClass::Integer, PrimitiveType::Integer, "fromInteger");
|
|
||||||
|
|
||||||
defineBinaryMonoidalOperator(BuiltinClass::Mul, Token::Mul, "mul");
|
|
||||||
defineBinaryMonoidalOperator(BuiltinClass::Add, Token::Add, "add");
|
|
||||||
|
|
||||||
defineBinaryCompareOperator(BuiltinClass::Equal, Token::Equal, "eq");
|
|
||||||
defineBinaryCompareOperator(BuiltinClass::Less, Token::LessThan, "lt");
|
|
||||||
defineBinaryCompareOperator(BuiltinClass::LessOrEqual, Token::LessThanOrEqual, "leq");
|
|
||||||
defineBinaryCompareOperator(BuiltinClass::Greater, Token::GreaterThan, "gt");
|
|
||||||
defineBinaryCompareOperator(BuiltinClass::GreaterOrEqual, Token::GreaterThanOrEqual, "geq");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeInference::analyze(SourceUnit const& _sourceUnit)
|
bool TypeInference::analyze(SourceUnit const& _sourceUnit)
|
||||||
@ -136,19 +63,17 @@ bool TypeInference::analyze(SourceUnit const& _sourceUnit)
|
|||||||
bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
|
bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
|
||||||
{
|
{
|
||||||
solAssert(m_expressionContext == ExpressionContext::Term);
|
solAssert(m_expressionContext == ExpressionContext::Term);
|
||||||
auto& functionAnnotation = annotation(_functionDefinition);
|
|
||||||
if (functionAnnotation.type)
|
// For type class members the type annotation is filled by visit(TypeClassDefinition)
|
||||||
return false;
|
if (!annotation(_functionDefinition).type.has_value())
|
||||||
|
annotation(_functionDefinition).type = TypeSystemHelpers{m_typeSystem}.functionType(
|
||||||
|
m_typeSystem.freshTypeVariable({}),
|
||||||
|
m_typeSystem.freshTypeVariable({})
|
||||||
|
);
|
||||||
|
|
||||||
ScopedSaveAndRestore signatureRestore(m_currentFunctionType, std::nullopt);
|
ScopedSaveAndRestore signatureRestore(m_currentFunctionType, std::nullopt);
|
||||||
|
m_currentFunctionType = annotation(_functionDefinition).type;
|
||||||
Type argumentsType = m_typeSystem.freshTypeVariable({});
|
auto [argumentsType, returnType] = TypeSystemHelpers{m_typeSystem}.destFunctionType(m_currentFunctionType.value());
|
||||||
Type returnType = m_typeSystem.freshTypeVariable({});
|
|
||||||
Type functionType = TypeSystemHelpers{m_typeSystem}.functionType(argumentsType, returnType);
|
|
||||||
|
|
||||||
m_currentFunctionType = functionType;
|
|
||||||
functionAnnotation.type = functionType;
|
|
||||||
|
|
||||||
|
|
||||||
_functionDefinition.parameterList().accept(*this);
|
_functionDefinition.parameterList().accept(*this);
|
||||||
unify(argumentsType, typeAnnotation(_functionDefinition.parameterList()), _functionDefinition.parameterList().location());
|
unify(argumentsType, typeAnnotation(_functionDefinition.parameterList()), _functionDefinition.parameterList().location());
|
||||||
@ -204,22 +129,27 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
|
|||||||
_typeClassDefinition.typeVariable().accept(*this);
|
_typeClassDefinition.typeVariable().accept(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, Type> functionTypes;
|
|
||||||
|
|
||||||
solAssert(m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.has_value());
|
solAssert(m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.has_value());
|
||||||
TypeClass typeClass = m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.value();
|
TypeClass typeClass = m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.value();
|
||||||
|
|
||||||
Type typeVar = m_typeSystem.typeClassInfo(typeClass).typeVariable;
|
Type typeVar = m_typeSystem.typeClassInfo(typeClass).typeVariable;
|
||||||
auto& typeMembersAnnotation = annotation().members[typeConstructor(&_typeClassDefinition)];
|
auto& typeMembersAnnotation = annotation().members[typeConstructor(&_typeClassDefinition)];
|
||||||
|
|
||||||
|
std::map<std::string, Type> const& functionTypes = m_analysis.annotation<TypeClassMemberRegistration>().typeClassFunctions.at(typeClass);
|
||||||
|
|
||||||
for (auto subNode: _typeClassDefinition.subNodes())
|
for (auto subNode: _typeClassDefinition.subNodes())
|
||||||
{
|
{
|
||||||
subNode->accept(*this);
|
|
||||||
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(subNode.get());
|
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(subNode.get());
|
||||||
solAssert(functionDefinition);
|
solAssert(functionDefinition);
|
||||||
// TODO: need polymorphicInstance?
|
|
||||||
auto functionType = polymorphicInstance(typeAnnotation(*functionDefinition));
|
// For type class members the type is assigned by TypeClassMemberRegistration.
|
||||||
if (!functionTypes.emplace(functionDefinition->name(), functionType).second)
|
// Fill in the `type` annotation to avoid `visit(FunctionDefinition)` giving it a fresh one.
|
||||||
m_errorReporter.fatalTypeError(3195_error, functionDefinition->location(), "Function in type class declared multiple times.");
|
Type functionType = functionTypes.at(functionDefinition->name());
|
||||||
|
solAssert(!annotation(*functionDefinition).type.has_value());
|
||||||
|
annotation(*functionDefinition).type = functionType;
|
||||||
|
|
||||||
|
subNode->accept(*this);
|
||||||
|
|
||||||
auto typeVars = TypeEnvironmentHelpers{*m_env}.typeVars(functionType);
|
auto typeVars = TypeEnvironmentHelpers{*m_env}.typeVars(functionType);
|
||||||
if (typeVars.size() != 1)
|
if (typeVars.size() != 1)
|
||||||
m_errorReporter.fatalTypeError(8379_error, functionDefinition->location(), "Function in type class may only depend on the type class variable.");
|
m_errorReporter.fatalTypeError(8379_error, functionDefinition->location(), "Function in type class may only depend on the type class variable.");
|
||||||
@ -227,8 +157,6 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
|
|||||||
typeMembersAnnotation[functionDefinition->name()] = TypeMember{functionType};
|
typeMembersAnnotation[functionDefinition->name()] = TypeMember{functionType};
|
||||||
}
|
}
|
||||||
|
|
||||||
annotation().typeClassFunctions[typeClass] = std::move(functionTypes);
|
|
||||||
|
|
||||||
for (auto [functionName, functionType]: functionTypes)
|
for (auto [functionName, functionType]: functionTypes)
|
||||||
{
|
{
|
||||||
TypeEnvironmentHelpers helper{*m_env};
|
TypeEnvironmentHelpers helper{*m_env};
|
||||||
@ -295,15 +223,16 @@ bool TypeInference::visit(BinaryOperation const& _binaryOperation)
|
|||||||
{
|
{
|
||||||
auto& operationAnnotation = annotation(_binaryOperation);
|
auto& operationAnnotation = annotation(_binaryOperation);
|
||||||
solAssert(!operationAnnotation.type);
|
solAssert(!operationAnnotation.type);
|
||||||
|
auto const& memberRegistrationAnnotation = m_analysis.annotation<TypeClassMemberRegistration>();
|
||||||
TypeSystemHelpers helper{m_typeSystem};
|
TypeSystemHelpers helper{m_typeSystem};
|
||||||
switch (m_expressionContext)
|
switch (m_expressionContext)
|
||||||
{
|
{
|
||||||
case ExpressionContext::Term:
|
case ExpressionContext::Term:
|
||||||
if (auto* operatorInfo = util::valueOrNullptr(annotation().operators, _binaryOperation.getOperator()))
|
if (auto* operatorInfo = util::valueOrNullptr(memberRegistrationAnnotation.operators, _binaryOperation.getOperator()))
|
||||||
{
|
{
|
||||||
auto [typeClass, functionName] = *operatorInfo;
|
auto [typeClass, functionName] = *operatorInfo;
|
||||||
// TODO: error robustness?
|
// TODO: error robustness?
|
||||||
Type functionType = m_env->fresh(annotation().typeClassFunctions.at(typeClass).at(functionName));
|
Type functionType = m_env->fresh(memberRegistrationAnnotation.typeClassFunctions.at(typeClass).at(functionName));
|
||||||
|
|
||||||
_binaryOperation.leftExpression().accept(*this);
|
_binaryOperation.leftExpression().accept(*this);
|
||||||
_binaryOperation.rightExpression().accept(*this);
|
_binaryOperation.rightExpression().accept(*this);
|
||||||
@ -630,6 +559,7 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
|
|||||||
{
|
{
|
||||||
// visiting the type class will re-visit this instantiation
|
// visiting the type class will re-visit this instantiation
|
||||||
typeClassDefinition->accept(*this);
|
typeClassDefinition->accept(*this);
|
||||||
|
|
||||||
// TODO: more error handling? Should be covered by the visit above.
|
// TODO: more error handling? Should be covered by the visit above.
|
||||||
solAssert(m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.has_value());
|
solAssert(m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.has_value());
|
||||||
return m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.value();
|
return m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.value();
|
||||||
@ -641,8 +571,10 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](Token _token) -> std::optional<TypeClass> {
|
[&](Token _token) -> std::optional<TypeClass> {
|
||||||
|
auto const& classRegistrationAnnotation = m_analysis.annotation<TypeClassRegistration>();
|
||||||
|
|
||||||
if (auto builtinClass = builtinClassFromToken(_token))
|
if (auto builtinClass = builtinClassFromToken(_token))
|
||||||
if (auto typeClass = util::valueOrNullptr(annotation().builtinClasses, *builtinClass))
|
if (auto typeClass = util::valueOrNullptr(classRegistrationAnnotation.builtinClasses, *builtinClass))
|
||||||
return *typeClass;
|
return *typeClass;
|
||||||
m_errorReporter.typeError(2658_error, _typeClassInstantiation.location(), "Invalid type class name.");
|
m_errorReporter.typeError(2658_error, _typeClassInstantiation.location(), "Invalid type class name.");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@ -695,7 +627,8 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
|
|||||||
if (auto error = m_typeSystem.instantiateClass(type, arity))
|
if (auto error = m_typeSystem.instantiateClass(type, arity))
|
||||||
m_errorReporter.typeError(5094_error, _typeClassInstantiation.location(), *error);
|
m_errorReporter.typeError(5094_error, _typeClassInstantiation.location(), *error);
|
||||||
|
|
||||||
auto const& classFunctions = annotation().typeClassFunctions.at(*typeClass);
|
auto const& memberRegistrationAnnotation = m_analysis.annotation<TypeClassMemberRegistration>();
|
||||||
|
auto const& classFunctions = memberRegistrationAnnotation.typeClassFunctions.at(*typeClass);
|
||||||
|
|
||||||
TypeEnvironment newEnv = m_env->clone();
|
TypeEnvironment newEnv = m_env->clone();
|
||||||
if (!newEnv.unify(m_typeSystem.typeClassVariable(*typeClass), type).empty())
|
if (!newEnv.unify(m_typeSystem.typeClassVariable(*typeClass), type).empty())
|
||||||
@ -1045,7 +978,9 @@ bool TypeInference::visit(Literal const& _literal)
|
|||||||
m_errorReporter.typeError(2345_error, _literal.location(), "Only integers are supported.");
|
m_errorReporter.typeError(2345_error, _literal.location(), "Only integers are supported.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
literalAnnotation.type = m_typeSystem.freshTypeVariable(Sort{{annotation().builtinClasses.at(BuiltinClass::Integer)}});
|
|
||||||
|
TypeClass integerClass = m_analysis.annotation<TypeClassRegistration>().builtinClasses.at(BuiltinClass::Integer);
|
||||||
|
literalAnnotation.type = m_typeSystem.freshTypeVariable(Sort{{integerClass}});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,10 +994,10 @@ TypeRegistration::TypeClassInstantiations const& typeClassInstantiations(Analysi
|
|||||||
if (typeClassDeclaration)
|
if (typeClassDeclaration)
|
||||||
return _analysis.annotation<TypeRegistration>(*typeClassDeclaration).instantiations;
|
return _analysis.annotation<TypeRegistration>(*typeClassDeclaration).instantiations;
|
||||||
// TODO: better mechanism than fetching by name.
|
// TODO: better mechanism than fetching by name.
|
||||||
auto const& annotation = _analysis.annotation<TypeRegistration>();
|
auto const& typeRegistrationAnnotation = _analysis.annotation<TypeRegistration>();
|
||||||
auto const& inferenceAnnotation = _analysis.annotation<TypeInference>();
|
auto const& classRegistrationAnnotation = _analysis.annotation<TypeClassRegistration>();
|
||||||
return annotation.builtinClassInstantiations.at(
|
return typeRegistrationAnnotation.builtinClassInstantiations.at(
|
||||||
inferenceAnnotation.builtinClassesByName.at(
|
classRegistrationAnnotation.builtinClassesByName.at(
|
||||||
_analysis.typeSystem().typeClassName(_class)
|
_analysis.typeSystem().typeClassName(_class)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -45,10 +45,6 @@ public:
|
|||||||
};
|
};
|
||||||
struct GlobalAnnotation
|
struct GlobalAnnotation
|
||||||
{
|
{
|
||||||
std::map<BuiltinClass, TypeClass> builtinClasses;
|
|
||||||
std::map<std::string, BuiltinClass> builtinClassesByName;
|
|
||||||
std::map<TypeClass, std::map<std::string, Type>> typeClassFunctions;
|
|
||||||
std::map<Token, std::tuple<TypeClass, std::string>> operators;
|
|
||||||
std::map<TypeConstructor, std::map<std::string, TypeMember>> members;
|
std::map<TypeConstructor, std::map<std::string, TypeMember>> members;
|
||||||
};
|
};
|
||||||
bool visit(Block const&) override { return true; }
|
bool visit(Block const&) override { return true; }
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||||
|
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeInference.h>
|
#include <libsolidity/experimental/analysis/TypeInference.h>
|
||||||
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binaryOperation)
|
|||||||
Type rightType = type(_binaryOperation.rightExpression());
|
Type rightType = type(_binaryOperation.rightExpression());
|
||||||
Type resultType = type(_binaryOperation);
|
Type resultType = type(_binaryOperation);
|
||||||
Type functionType = helper.functionType(helper.tupleType({leftType, rightType}), resultType);
|
Type functionType = helper.functionType(helper.tupleType({leftType, rightType}), resultType);
|
||||||
auto [typeClass, memberName] = m_context.analysis.annotation<TypeInference>().operators.at(_binaryOperation.getOperator());
|
auto [typeClass, memberName] = m_context.analysis.annotation<TypeClassMemberRegistration>().operators.at(_binaryOperation.getOperator());
|
||||||
auto const& functionDefinition = resolveTypeClassFunction(typeClass, memberName, functionType);
|
auto const& functionDefinition = resolveTypeClassFunction(typeClass, memberName, functionType);
|
||||||
// TODO: deduplicate with FunctionCall
|
// TODO: deduplicate with FunctionCall
|
||||||
// TODO: get around resolveRecursive by passing the environment further down?
|
// TODO: get around resolveRecursive by passing the environment further down?
|
||||||
@ -219,7 +220,7 @@ TypeRegistration::TypeClassInstantiations const& typeClassInstantiations(IRGener
|
|||||||
return _context.analysis.annotation<TypeRegistration>(*typeClassDeclaration).instantiations;
|
return _context.analysis.annotation<TypeRegistration>(*typeClassDeclaration).instantiations;
|
||||||
// TODO: better mechanism than fetching by name.
|
// TODO: better mechanism than fetching by name.
|
||||||
auto& instantiations = _context.analysis.annotation<TypeRegistration>().builtinClassInstantiations;
|
auto& instantiations = _context.analysis.annotation<TypeRegistration>().builtinClassInstantiations;
|
||||||
auto& builtinClassesByName = _context.analysis.annotation<TypeInference>().builtinClassesByName;
|
auto& builtinClassesByName = _context.analysis.annotation<TypeClassRegistration>().builtinClassesByName;
|
||||||
return instantiations.at(builtinClassesByName.at(_context.analysis.typeSystem().typeClassName(_class)));
|
return instantiations.at(builtinClassesByName.at(_context.analysis.typeSystem().typeClassName(_class)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +230,7 @@ FunctionDefinition const& IRGeneratorForStatements::resolveTypeClassFunction(Typ
|
|||||||
TypeSystemHelpers helper{m_context.analysis.typeSystem()};
|
TypeSystemHelpers helper{m_context.analysis.typeSystem()};
|
||||||
|
|
||||||
TypeEnvironment env = m_context.env->clone();
|
TypeEnvironment env = m_context.env->clone();
|
||||||
Type genericFunctionType = env.fresh(m_context.analysis.annotation<TypeInference>().typeClassFunctions.at(_class).at(_name));
|
Type genericFunctionType = env.fresh(m_context.analysis.annotation<TypeClassMemberRegistration>().typeClassFunctions.at(_class).at(_name));
|
||||||
auto typeVars = TypeEnvironmentHelpers{env}.typeVars(genericFunctionType);
|
auto typeVars = TypeEnvironmentHelpers{env}.typeVars(genericFunctionType);
|
||||||
solAssert(typeVars.size() == 1);
|
solAssert(typeVars.size() == 1);
|
||||||
solAssert(env.unify(genericFunctionType, _type).empty());
|
solAssert(env.unify(genericFunctionType, _type).empty());
|
||||||
|
49
test/libsolidity/syntaxTests/experimental/algebraicTypes.sol
Normal file
49
test/libsolidity/syntaxTests/experimental/algebraicTypes.sol
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
type word = __builtin("word");
|
||||||
|
type bool = __builtin("bool");
|
||||||
|
type unit = __builtin("unit");
|
||||||
|
|
||||||
|
type wordOrBool = word | bool;
|
||||||
|
type wordAndBool = (word, bool);
|
||||||
|
|
||||||
|
function g() -> () {}
|
||||||
|
|
||||||
|
function f() -> () {
|
||||||
|
let ptr1: unit -> unit = g;
|
||||||
|
let ptr2: () -> () = g;
|
||||||
|
|
||||||
|
// FIXME: Does not unify:
|
||||||
|
//let ptr3: () -> () | () -> () = g;
|
||||||
|
//let ptr4: unit -> unit | () -> () = g;
|
||||||
|
//let ptr5: word | () -> () = g;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Info 4164: (31-61): Inferred type: word
|
||||||
|
// Info 4164: (62-92): Inferred type: bool
|
||||||
|
// Info 4164: (93-123): Inferred type: ()
|
||||||
|
// Info 4164: (125-155): Inferred type: wordOrBool
|
||||||
|
// Info 4164: (143-154): Inferred type: sum(word, bool)
|
||||||
|
// Info 4164: (143-147): Inferred type: word
|
||||||
|
// Info 4164: (150-154): Inferred type: bool
|
||||||
|
// Info 4164: (156-188): Inferred type: wordAndBool
|
||||||
|
// Info 4164: (175-187): Inferred type: (word, bool)
|
||||||
|
// Info 4164: (176-180): Inferred type: word
|
||||||
|
// Info 4164: (182-186): Inferred type: bool
|
||||||
|
// Info 4164: (190-211): Inferred type: () -> ()
|
||||||
|
// Info 4164: (200-202): Inferred type: ()
|
||||||
|
// Info 4164: (206-208): Inferred type: ()
|
||||||
|
// Info 4164: (213-449): Inferred type: () -> ()
|
||||||
|
// Info 4164: (223-225): Inferred type: ()
|
||||||
|
// Info 4164: (229-231): Inferred type: ()
|
||||||
|
// Info 4164: (242-260): Inferred type: () -> ()
|
||||||
|
// Info 4164: (248-260): Inferred type: () -> ()
|
||||||
|
// Info 4164: (248-252): Inferred type: ()
|
||||||
|
// Info 4164: (256-260): Inferred type: ()
|
||||||
|
// Info 4164: (263-264): Inferred type: () -> ()
|
||||||
|
// Info 4164: (274-288): Inferred type: () -> ()
|
||||||
|
// Info 4164: (280-288): Inferred type: () -> ()
|
||||||
|
// Info 4164: (280-282): Inferred type: ()
|
||||||
|
// Info 4164: (286-288): Inferred type: ()
|
||||||
|
// Info 4164: (291-292): Inferred type: () -> ()
|
@ -0,0 +1,52 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
type word = __builtin("word");
|
||||||
|
|
||||||
|
type T = word;
|
||||||
|
|
||||||
|
class Self: C {
|
||||||
|
function f(self: Self) -> word;
|
||||||
|
}
|
||||||
|
|
||||||
|
instantiation T: C {
|
||||||
|
function f(self: T) -> word {}
|
||||||
|
}
|
||||||
|
|
||||||
|
instantiation T: D {
|
||||||
|
function f(self: T) -> word {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Self: D {
|
||||||
|
function f(self: Self) -> word;
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Info 4164: (31-61): Inferred type: word
|
||||||
|
// Info 4164: (63-77): Inferred type: T:(type, C, D)
|
||||||
|
// Info 4164: (72-76): Inferred type: word
|
||||||
|
// Info 4164: (79-132): Inferred type: C
|
||||||
|
// Info 4164: (85-89): Inferred type: 'bb:(type, C)
|
||||||
|
// Info 4164: (99-130): Inferred type: 'bb:(type, C) -> word
|
||||||
|
// Info 4164: (109-121): Inferred type: 'bb:(type, C)
|
||||||
|
// Info 4164: (110-120): Inferred type: 'bb:(type, C)
|
||||||
|
// Info 4164: (116-120): Inferred type: 'bb:(type, C)
|
||||||
|
// Info 4164: (125-129): Inferred type: word
|
||||||
|
// Info 4164: (134-191): Inferred type: void
|
||||||
|
// Info 4164: (159-189): Inferred type: T -> word
|
||||||
|
// Info 4164: (169-178): Inferred type: T
|
||||||
|
// Info 4164: (170-177): Inferred type: T
|
||||||
|
// Info 4164: (176-177): Inferred type: T
|
||||||
|
// Info 4164: (182-186): Inferred type: word
|
||||||
|
// Info 4164: (193-250): Inferred type: void
|
||||||
|
// Info 4164: (218-248): Inferred type: T -> word
|
||||||
|
// Info 4164: (228-237): Inferred type: T
|
||||||
|
// Info 4164: (229-236): Inferred type: T
|
||||||
|
// Info 4164: (235-236): Inferred type: T
|
||||||
|
// Info 4164: (241-245): Inferred type: word
|
||||||
|
// Info 4164: (252-305): Inferred type: D
|
||||||
|
// Info 4164: (258-262): Inferred type: 'bi:(type, D)
|
||||||
|
// Info 4164: (272-303): Inferred type: 'bi:(type, D) -> word
|
||||||
|
// Info 4164: (282-294): Inferred type: 'bi:(type, D)
|
||||||
|
// Info 4164: (283-293): Inferred type: 'bi:(type, D)
|
||||||
|
// Info 4164: (289-293): Inferred type: 'bi:(type, D)
|
||||||
|
// Info 4164: (298-302): Inferred type: word
|
@ -0,0 +1,30 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
type word = __builtin("word");
|
||||||
|
|
||||||
|
function f(x: word) -> word {
|
||||||
|
g(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
function g(x: word) -> word {
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Info 4164: (31-61): Inferred type: word
|
||||||
|
// Info 4164: (63-104): Inferred type: word -> word
|
||||||
|
// Info 4164: (73-82): Inferred type: word
|
||||||
|
// Info 4164: (74-81): Inferred type: word
|
||||||
|
// Info 4164: (77-81): Inferred type: word
|
||||||
|
// Info 4164: (86-90): Inferred type: word
|
||||||
|
// Info 4164: (97-101): Inferred type: word
|
||||||
|
// Info 4164: (97-98): Inferred type: word -> word
|
||||||
|
// Info 4164: (99-100): Inferred type: word
|
||||||
|
// Info 4164: (106-147): Inferred type: word -> word
|
||||||
|
// Info 4164: (116-125): Inferred type: word
|
||||||
|
// Info 4164: (117-124): Inferred type: word
|
||||||
|
// Info 4164: (120-124): Inferred type: word
|
||||||
|
// Info 4164: (129-133): Inferred type: word
|
||||||
|
// Info 4164: (140-144): Inferred type: word
|
||||||
|
// Info 4164: (140-141): Inferred type: word -> word
|
||||||
|
// Info 4164: (142-143): Inferred type: word
|
38
test/libsolidity/syntaxTests/experimental/sorts.sol
Normal file
38
test/libsolidity/syntaxTests/experimental/sorts.sol
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
pragma experimental solidity;
|
||||||
|
|
||||||
|
type word = __builtin("word");
|
||||||
|
type uint = word;
|
||||||
|
|
||||||
|
class Self: Number {}
|
||||||
|
|
||||||
|
instantiation uint: Number {}
|
||||||
|
|
||||||
|
function f(a: T: Number) {}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
let x: uint: Number;
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 2264: (0-29): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// Info 4164: (31-61): Inferred type: word
|
||||||
|
// Info 4164: (62-79): Inferred type: uint:(type, Number)
|
||||||
|
// Info 4164: (74-78): Inferred type: word
|
||||||
|
// Info 4164: (81-102): Inferred type: Number
|
||||||
|
// Info 4164: (87-91): Inferred type: 'v:(type, Number)
|
||||||
|
// Info 4164: (104-133): Inferred type: void
|
||||||
|
// Info 4164: (135-162): Inferred type: 'z:(type, Number) -> ()
|
||||||
|
// Info 4164: (145-159): Inferred type: 'z:(type, Number)
|
||||||
|
// Info 4164: (146-158): Inferred type: 'z:(type, Number)
|
||||||
|
// Info 4164: (149-158): Inferred type: 'z:(type, Number)
|
||||||
|
// Info 4164: (149-150): Inferred type: 'z:(type, Number)
|
||||||
|
// Info 4164: (152-158): Inferred type: 'z:(type, Number):(type, Number)
|
||||||
|
// Info 4164: (164-218): Inferred type: () -> ()
|
||||||
|
// Info 4164: (177-179): Inferred type: ()
|
||||||
|
// Info 4164: (190-205): Inferred type: uint
|
||||||
|
// Info 4164: (193-205): Inferred type: uint
|
||||||
|
// Info 4164: (193-197): Inferred type: uint
|
||||||
|
// Info 4164: (199-205): Inferred type: uint:(type, Number)
|
||||||
|
// Info 4164: (211-215): Inferred type: ()
|
||||||
|
// Info 4164: (211-212): Inferred type: uint -> ()
|
||||||
|
// Info 4164: (213-214): Inferred type: uint
|
Loading…
Reference in New Issue
Block a user