mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Extract type class member registration into a separate experimental analysis pass
This commit is contained in:
parent
4960de7b42
commit
ea8daf1613
@ -188,6 +188,8 @@ set(sources
|
||||
experimental/analysis/Analysis.h
|
||||
experimental/analysis/DebugWarner.cpp
|
||||
experimental/analysis/DebugWarner.h
|
||||
experimental/analysis/TypeClassMemberRegistration.cpp
|
||||
experimental/analysis/TypeClassMemberRegistration.h
|
||||
experimental/analysis/TypeClassRegistration.cpp
|
||||
experimental/analysis/TypeClassRegistration.h
|
||||
experimental/analysis/TypeInference.cpp
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||
#include <libsolidity/experimental/analysis/DebugWarner.h>
|
||||
#include <libsolidity/experimental/analysis/SyntaxRestrictor.h>
|
||||
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeInference.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.
|
||||
struct Analysis::AnnotationContainer
|
||||
{
|
||||
TypeClassMemberRegistration::Annotation typeClassMemberRegistrationAnnotation;
|
||||
TypeClassRegistration::Annotation typeClassRegistrationAnnotation;
|
||||
TypeRegistration::Annotation typeRegistrationAnnotation;
|
||||
TypeInference::Annotation typeInferenceAnnotation;
|
||||
@ -35,11 +37,37 @@ struct Analysis::AnnotationContainer
|
||||
|
||||
struct Analysis::GlobalAnnotationContainer
|
||||
{
|
||||
TypeClassMemberRegistration::GlobalAnnotation typeClassMemberRegistrationAnnotation;
|
||||
TypeClassRegistration::GlobalAnnotation typeClassRegistrationAnnotation;
|
||||
TypeRegistration::GlobalAnnotation typeRegistrationAnnotation;
|
||||
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<>
|
||||
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,
|
||||
TypeClassRegistration,
|
||||
TypeRegistration,
|
||||
TypeClassMemberRegistration,
|
||||
TypeInference,
|
||||
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;
|
||||
};
|
||||
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
#include <libsolidity/experimental/analysis/TypeInference.h>
|
||||
|
||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
|
||||
@ -51,56 +52,6 @@ TypeInference::TypeInference(Analysis& _analysis):
|
||||
m_unitType(m_typeSystem.type(PrimitiveType::Unit, {})),
|
||||
m_boolType(m_typeSystem.type(PrimitiveType::Bool, {}))
|
||||
{
|
||||
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 TypeInference::analyze(SourceUnit const& _sourceUnit)
|
||||
@ -112,19 +63,17 @@ bool TypeInference::analyze(SourceUnit const& _sourceUnit)
|
||||
bool TypeInference::visit(FunctionDefinition const& _functionDefinition)
|
||||
{
|
||||
solAssert(m_expressionContext == ExpressionContext::Term);
|
||||
auto& functionAnnotation = annotation(_functionDefinition);
|
||||
if (functionAnnotation.type)
|
||||
return false;
|
||||
|
||||
// For type class members the type annotation is filled by visit(TypeClassDefinition)
|
||||
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);
|
||||
|
||||
Type argumentsType = m_typeSystem.freshTypeVariable({});
|
||||
Type returnType = m_typeSystem.freshTypeVariable({});
|
||||
Type functionType = TypeSystemHelpers{m_typeSystem}.functionType(argumentsType, returnType);
|
||||
|
||||
m_currentFunctionType = functionType;
|
||||
functionAnnotation.type = functionType;
|
||||
|
||||
m_currentFunctionType = annotation(_functionDefinition).type;
|
||||
auto [argumentsType, returnType] = TypeSystemHelpers{m_typeSystem}.destFunctionType(m_currentFunctionType.value());
|
||||
|
||||
_functionDefinition.parameterList().accept(*this);
|
||||
unify(argumentsType, typeAnnotation(_functionDefinition.parameterList()), _functionDefinition.parameterList().location());
|
||||
@ -180,21 +129,27 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
|
||||
_typeClassDefinition.typeVariable().accept(*this);
|
||||
}
|
||||
|
||||
std::map<std::string, Type> functionTypes;
|
||||
|
||||
solAssert(m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.has_value());
|
||||
TypeClass typeClass = m_analysis.annotation<TypeClassRegistration>(_typeClassDefinition).typeClass.value();
|
||||
|
||||
Type typeVar = m_typeSystem.typeClassInfo(typeClass).typeVariable;
|
||||
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())
|
||||
{
|
||||
subNode->accept(*this);
|
||||
auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(subNode.get());
|
||||
solAssert(functionDefinition);
|
||||
auto functionType = typeAnnotation(*functionDefinition);
|
||||
if (!functionTypes.emplace(functionDefinition->name(), functionType).second)
|
||||
m_errorReporter.fatalTypeError(3195_error, functionDefinition->location(), "Function in type class declared multiple times.");
|
||||
|
||||
// For type class members the type is assigned by TypeClassMemberRegistration.
|
||||
// Fill in the `type` annotation to avoid `visit(FunctionDefinition)` giving it a fresh one.
|
||||
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);
|
||||
if (typeVars.size() != 1)
|
||||
m_errorReporter.fatalTypeError(8379_error, functionDefinition->location(), "Function in type class may only depend on the type class variable.");
|
||||
@ -202,8 +157,6 @@ bool TypeInference::visit(TypeClassDefinition const& _typeClassDefinition)
|
||||
typeMembersAnnotation[functionDefinition->name()] = TypeMember{functionType};
|
||||
}
|
||||
|
||||
annotation().typeClassFunctions[typeClass] = std::move(functionTypes);
|
||||
|
||||
for (auto [functionName, functionType]: functionTypes)
|
||||
{
|
||||
TypeEnvironmentHelpers helper{*m_env};
|
||||
@ -270,15 +223,16 @@ bool TypeInference::visit(BinaryOperation const& _binaryOperation)
|
||||
{
|
||||
auto& operationAnnotation = annotation(_binaryOperation);
|
||||
solAssert(!operationAnnotation.type);
|
||||
auto const& memberRegistrationAnnotation = m_analysis.annotation<TypeClassMemberRegistration>();
|
||||
TypeSystemHelpers helper{m_typeSystem};
|
||||
switch (m_expressionContext)
|
||||
{
|
||||
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;
|
||||
// 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.rightExpression().accept(*this);
|
||||
@ -603,8 +557,6 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
|
||||
[&](ASTPointer<IdentifierPath> _typeClassName) -> std::optional<TypeClass> {
|
||||
if (auto const* typeClassDefinition = dynamic_cast<TypeClassDefinition const*>(_typeClassName->annotation().referencedDeclaration))
|
||||
{
|
||||
// visiting the type class will re-visit this instantiation
|
||||
typeClassDefinition->accept(*this);
|
||||
// TODO: more error handling? Should be covered by the visit above.
|
||||
solAssert(m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.has_value());
|
||||
return m_analysis.annotation<TypeClassRegistration>(*typeClassDefinition).typeClass.value();
|
||||
@ -672,7 +624,8 @@ bool TypeInference::visit(TypeClassInstantiation const& _typeClassInstantiation)
|
||||
if (auto error = m_typeSystem.instantiateClass(type, arity))
|
||||
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();
|
||||
if (!newEnv.unify(m_typeSystem.typeClassVariable(*typeClass), type).empty())
|
||||
|
@ -45,8 +45,6 @@ public:
|
||||
};
|
||||
struct GlobalAnnotation
|
||||
{
|
||||
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;
|
||||
};
|
||||
bool visit(Block const&) override { return true; }
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <libsolidity/experimental/analysis/Analysis.h>
|
||||
#include <libsolidity/experimental/analysis/TypeClassRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeClassMemberRegistration.h>
|
||||
#include <libsolidity/experimental/analysis/TypeInference.h>
|
||||
#include <libsolidity/experimental/analysis/TypeRegistration.h>
|
||||
|
||||
@ -199,7 +200,7 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binaryOperation)
|
||||
Type rightType = type(_binaryOperation.rightExpression());
|
||||
Type resultType = type(_binaryOperation);
|
||||
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);
|
||||
// TODO: deduplicate with FunctionCall
|
||||
// TODO: get around resolveRecursive by passing the environment further down?
|
||||
@ -229,7 +230,7 @@ FunctionDefinition const& IRGeneratorForStatements::resolveTypeClassFunction(Typ
|
||||
TypeSystemHelpers helper{m_context.analysis.typeSystem()};
|
||||
|
||||
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);
|
||||
solAssert(typeVars.size() == 1);
|
||||
solAssert(env.unify(genericFunctionType, _type).empty());
|
||||
|
Loading…
Reference in New Issue
Block a user