diff --git a/Changelog.md b/Changelog.md index 97113fcf7..3a38456d7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ Compiler Features: Bugfixes: * Type Checker: Disallow ``virtual`` for modifiers in libraries. * ViewPureChecker: Prevent visibility check on constructors. + * Type system: Fix internal error on implicit conversion of contract instance to the type of its ``super``. ### 0.7.1 (2020-09-02) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f4085c07d..a367b6b49 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1569,11 +1569,15 @@ BoolResult ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const return true; if (_convertTo.category() == Category::Contract) { + auto const& targetContractType = dynamic_cast(_convertTo); + if (targetContractType.isSuper()) + return false; + auto const& bases = contractDefinition().annotation().linearizedBaseContracts; return find( bases.begin(), bases.end(), - &dynamic_cast(_convertTo).contractDefinition() + &targetContractType.contractDefinition() ) != bases.end(); } return false; diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol new file mode 100644 index 000000000..b2f5ba881 --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_comparison.sol @@ -0,0 +1,27 @@ +contract D {} + +contract C { + C c; + D d; + + function foo() public { + // Current instance of the current contract vs super + super != this; + this != super; + + // Different instance of the current contract vs super + super != c; + c != super; + + // Instance of an unrelated contract vs super + super != d; + d != super; + } +} +// ---- +// TypeError 2271: (144-157): Operator != not compatible with types contract super C and contract C +// TypeError 2271: (167-180): Operator != not compatible with types contract C and contract super C +// TypeError 2271: (254-264): Operator != not compatible with types contract super C and contract C +// TypeError 2271: (274-284): Operator != not compatible with types contract C and contract super C +// TypeError 2271: (349-359): Operator != not compatible with types contract super C and contract D +// TypeError 2271: (369-379): Operator != not compatible with types contract D and contract super C diff --git a/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_operators.sol b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_operators.sol new file mode 100644 index 000000000..2cb104dbd --- /dev/null +++ b/test/libsolidity/syntaxTests/conversion/implicit_conversion_of_super_in_operators.sol @@ -0,0 +1,56 @@ +contract C { + function foo() public { + super << this; + super >> this; + super ^ this; + super | this; + super & this; + + super * this; + super / this; + super % this; + super - this; + super + this; + super ** this; + + super == this; + super != this; + super >= this; + super <= this; + super < this; + super > this; + + super || this; + super && this; + + super -= this; + super += this; + + true ? super : this; + } +} +// ---- +// TypeError 2271: (49-62): Operator << not compatible with types contract super C and contract C +// TypeError 2271: (72-85): Operator >> not compatible with types contract super C and contract C +// TypeError 2271: (95-107): Operator ^ not compatible with types contract super C and contract C +// TypeError 2271: (117-129): Operator | not compatible with types contract super C and contract C +// TypeError 2271: (139-151): Operator & not compatible with types contract super C and contract C +// TypeError 2271: (162-174): Operator * not compatible with types contract super C and contract C +// TypeError 2271: (184-196): Operator / not compatible with types contract super C and contract C +// TypeError 2271: (206-218): Operator % not compatible with types contract super C and contract C +// TypeError 2271: (228-240): Operator - not compatible with types contract super C and contract C +// TypeError 2271: (250-262): Operator + not compatible with types contract super C and contract C +// TypeError 2271: (272-285): Operator ** not compatible with types contract super C and contract C +// TypeError 2271: (296-309): Operator == not compatible with types contract super C and contract C +// TypeError 2271: (319-332): Operator != not compatible with types contract super C and contract C +// TypeError 2271: (342-355): Operator >= not compatible with types contract super C and contract C +// TypeError 2271: (365-378): Operator <= not compatible with types contract super C and contract C +// TypeError 2271: (388-400): Operator < not compatible with types contract super C and contract C +// TypeError 2271: (410-422): Operator > not compatible with types contract super C and contract C +// TypeError 2271: (433-446): Operator || not compatible with types contract super C and contract C +// TypeError 2271: (456-469): Operator && not compatible with types contract super C and contract C +// TypeError 4247: (480-485): Expression has to be an lvalue. +// TypeError 7366: (480-493): Operator -= not compatible with types contract super C and contract C +// TypeError 4247: (503-508): Expression has to be an lvalue. +// TypeError 7366: (503-516): Operator += not compatible with types contract super C and contract C +// TypeError 1080: (527-546): True expression's type contract super C does not match false expression's type contract C.