Skip to content

Commit 783fc79

Browse files
committed
Extract function type member validation to a function.
1 parent 24b3df4 commit 783fc79

File tree

2 files changed

+75
-42
lines changed

2 files changed

+75
-42
lines changed

libsolidity/analysis/TypeChecker.cpp

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3171,6 +3171,59 @@ void TypeChecker::handleUnresolvedMemberAccessErrors(
31713171
);
31723172
}
31733173

3174+
void TypeChecker::validateAccessMemberFunctionType(
3175+
FunctionType const* _accessedMemberFunctionType,
3176+
Type const* _expressionObjectType,
3177+
ASTString const& _memberName,
3178+
SourceLocation const& _location,
3179+
bool _emptyArguments,
3180+
bool _isDefined
3181+
) const
3182+
{
3183+
solAssert(
3184+
!_accessedMemberFunctionType->hasBoundFirstArgument() ||
3185+
_expressionObjectType->isImplicitlyConvertibleTo(*_accessedMemberFunctionType->selfType()),
3186+
"Function \"" + _memberName + "\" cannot be called on an object of type " +
3187+
_expressionObjectType->humanReadableName() +
3188+
" (expected " + _accessedMemberFunctionType->selfType()->humanReadableName() + ")."
3189+
);
3190+
3191+
if (
3192+
dynamic_cast<FunctionType const*>(_expressionObjectType) &&
3193+
!_isDefined &&
3194+
(_memberName == "value" || _memberName == "gas")
3195+
)
3196+
m_errorReporter.typeError(
3197+
1621_error,
3198+
_location,
3199+
"Using \"." + _memberName + "(...)\" is deprecated. Use \"{" + _memberName + ": ...}\" instead."
3200+
);
3201+
3202+
if (
3203+
_accessedMemberFunctionType->kind() == FunctionType::Kind::ArrayPush &&
3204+
!_emptyArguments &&
3205+
_expressionObjectType->containsNestedMapping()
3206+
)
3207+
m_errorReporter.typeError(
3208+
8871_error,
3209+
_location,
3210+
"Storage arrays with nested mappings do not support .push(<arg>)."
3211+
);
3212+
3213+
if (
3214+
_accessedMemberFunctionType->kind() == FunctionType::Kind::Send ||
3215+
_accessedMemberFunctionType->kind() == FunctionType::Kind::Transfer
3216+
)
3217+
m_errorReporter.warning(
3218+
9207_error,
3219+
_location,
3220+
fmt::format(
3221+
"'{}' is deprecated and scheduled for removal. Use 'call{{value: <amount>}}(\"\")' instead.",
3222+
_accessedMemberFunctionType->kind() == FunctionType::Kind::Send ? "send" : "transfer"
3223+
)
3224+
);
3225+
}
3226+
31743227
bool TypeChecker::visit(MemberAccess const& _memberAccess)
31753228
{
31763229
_memberAccess.expression().accept(*this);
@@ -3210,56 +3263,26 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
32103263
// TODO: Explain
32113264
VirtualLookup requiredLookup = VirtualLookup::Static;
32123265

3213-
if (auto funType = dynamic_cast<FunctionType const*>(accessedMemberAnnotation.type))
3266+
if (auto accessedMemberFunctionTypeType = dynamic_cast<FunctionType const*>(accessedMemberAnnotation.type))
32143267
{
3215-
solAssert(
3216-
!funType->hasBoundFirstArgument() || expressionObjectType->isImplicitlyConvertibleTo(*funType->selfType()),
3217-
"Function \"" + memberName + "\" cannot be called on an object of type " +
3218-
expressionObjectType->humanReadableName() + " (expected " + funType->selfType()->humanReadableName() + ")."
3219-
);
3220-
3221-
if (
3222-
dynamic_cast<FunctionType const*>(expressionObjectType) &&
3223-
!accessedMemberAnnotation.referencedDeclaration &&
3224-
(memberName == "value" || memberName == "gas")
3225-
)
3226-
m_errorReporter.typeError(
3227-
1621_error,
3228-
_memberAccess.location(),
3229-
"Using \"." + memberName + "(...)\" is deprecated. Use \"{" + memberName + ": ...}\" instead."
3230-
);
3231-
3232-
if (
3233-
funType->kind() == FunctionType::Kind::ArrayPush &&
3234-
arguments.value().numArguments() != 0 &&
3235-
expressionObjectType->containsNestedMapping()
3236-
)
3237-
m_errorReporter.typeError(
3238-
8871_error,
3239-
_memberAccess.location(),
3240-
"Storage arrays with nested mappings do not support .push(<arg>)."
3241-
);
3242-
3243-
if (!funType->hasBoundFirstArgument())
3268+
// Update required lookup
3269+
if (!accessedMemberFunctionTypeType->hasBoundFirstArgument())
32443270
if (auto typeType = dynamic_cast<TypeType const*>(expressionObjectType))
32453271
{
32463272
auto contractType = dynamic_cast<ContractType const*>(typeType->actualType());
32473273
if (contractType && contractType->isSuper())
32483274
requiredLookup = VirtualLookup::Super;
32493275
}
32503276

3251-
if (
3252-
funType->kind() == FunctionType::Kind::Send ||
3253-
funType->kind() == FunctionType::Kind::Transfer
3254-
)
3255-
m_errorReporter.warning(
3256-
9207_error,
3257-
_memberAccess.location(),
3258-
fmt::format(
3259-
"'{}' is deprecated and scheduled for removal. Use 'call{{value: <amount>}}(\"\")' instead.",
3260-
funType->kind() == FunctionType::Kind::Send ? "send" : "transfer"
3261-
)
3262-
);
3277+
// Validate an accessed member function type.
3278+
validateAccessMemberFunctionType(
3279+
accessedMemberFunctionTypeType,
3280+
expressionObjectType,
3281+
memberName,
3282+
_memberAccess.location(),
3283+
(*arguments).numArguments() == 0,
3284+
accessedMemberAnnotation.referencedDeclaration != nullptr
3285+
);
32633286
}
32643287

32653288
accessedMemberAnnotation.requiredLookup = requiredLookup;

libsolidity/analysis/TypeChecker.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ class TypeChecker: private ASTConstVisitor
202202
size_t _initialMemberCount
203203
) const;
204204

205+
void validateAccessMemberFunctionType(
206+
FunctionType const* _accessedMemberFunctionType,
207+
Type const* _expressionObjectType,
208+
ASTString const& _memberName,
209+
langutil::SourceLocation const& _location,
210+
bool _emptyArguments,
211+
bool _isDefined
212+
) const;
213+
214+
205215
SourceUnit const* m_currentSourceUnit = nullptr;
206216
ContractDefinition const* m_currentContract = nullptr;
207217

0 commit comments

Comments
 (0)