Repository navigation
[v2] fix(semantic): type address literals as address - #2184
Conversation
|
|
| Branch | bas/v2-address-literal-overload |
| Testbed | ci |
🐰 View full continuous benchmarking report in Bencher
⚠️ WARNING: Truncated view!The full continuous benchmarking report exceeds the maximum length allowed on this platform.
address
bcfc879 to
86179ad
Compare
ggiraldez
left a comment
There was a problem hiding this comment.
I'm not sure I agree with the proposed changes. With them, we're removing detail from the type system and it's probably unnecessary.
I see in the PR history that you started with the implicit conversion route, which was my initial intuitive solution to the presented problem. The change to find_canonical_type_id to handle literal addresses with using attached functions is sound. We may need to add other similar cases for the other literal kinds. Removing the LiteralKind::Address from Number::from_literal_kind is required as well as it is a bug, but it might have been what tipped you to dropping the literal kind altogether.
Did you find any other strong reasons to remove LiteralKind::Address and type it as Type::Address directly?
ggiraldez
left a comment
There was a problem hiding this comment.
I took a second look at this and the disadvantages of keeping the literal type are bigger than any advantage of the additional provenance information. We'd need to add the literal case to many places to match the behaviour of Type::Address and there's no real upside.
What I would ask is a bit of coverage improvement, especially surrounding the previously implicit conversion to number from a constant, eg. 0x... + 1 which is no longer typed as a number (not necessarily rejected yet because the diagnostic is not implemented).
Claude also found these adjacent cases, although I'm not sure we should follow solc here (I'd either reject or accept all of these):
uint[0x0000…0003] x; // accepted
uint[0x0000…0003 + 1] x; // accepted, but solc rejects
contract C layout at 0xb701…7641 {} // same, should be rejected
OTOH, a parenthesized address literal can no longer be used from Yul:
address constant K = 0x1111…1111; // accepted
address constant K = (0xb701…7641); // now rejected
Which matches solc, but maybe doesn't make sense and it's not consistent with our constants treatment above.
An address literal had no implicit conversion to `address`, so overload resolution rejected every candidate taking one and reported `no-matching-callable-declaration`, or `member-not-found` through a member access. Calls with a single candidate never compare argument types, which is why only overloaded callees failed. solc 0.8 types the literal as non-payable `address`, so it converts to `address` only. Fixes #2179.
…erals solc types an address literal as `address`, so `using L for address` applies to it. The directive lookup matched the literal's own type and reported `member-not-found`. Integer literals stay unattached, as in solc.
With different arities the call count alone ruled out the other candidate, so the test didn't show the literal choosing between overloads.
solc types a 40-digit hex literal as non-payable `address` and never as a literal type. Keeping a separate LiteralKind::Address meant every consumer of `address` had to special-case it; #2179 and the using-for lookup were two that did not. It also let the value fold as a number, so `0x… + 1` typed as an integer literal. The AST still reads a hex literal's value off its type and parses the source text only for an address literal, whose type carries none.
Typing a 40-digit hex literal as `address` stops it folding as a number in expressions, but the constant evaluator still reads its digits for array lengths and storage base slots. The fixtures pin both sides: a bare length and a parenthesised assembly constant agree with solc, while `0x… + 1` as a length and `layout at 0x…` are accepted pending the operator (SDR #839) and base-slot type (SDR #778) checks.
86179ad to
f585526
Compare
|
Thanks! Added a typing test for Note that NomicFoundation/slang-diagnostics-research#778 was already closed, so I'm reopening it to be addressed as a follow-up, rather than fixing it in this PR. |
Type address literals with
addressexplicitly. This mainly matters in overloading context.Claude summary
Fixes #2179. solc types a 40-digit hex literal (
0xb701…) as non-payableaddress. Slang gave itits own literal kind,
LiteralKind::Address, and every rule aboutaddresshad to handle thatkind separately. Two rules didn't:
address, so when a call had severalcandidates, every overload taking an
addressrejected it. Slang reportedno-matching-callable-declaration, ormember-not-foundwhen the callee was reached through amember (
Address.functionDelegateCall(0x142F…, …),Clones.clone(0xeA34…)). A callee with asingle candidate never compares argument types, so only overloaded calls failed.
using L for addressdid not apply to the literal (0xb701….tag()reportedmember-not-found).The literal kind is gone. The literal is now typed
address, so both cases go through ordinaryaddressresolution, and so do built-in members, mobile types and the inline-assembly constantcheck. The kind also let the value fold as a number:
0x… + 1was typed as an integer literal and(0x…)counted as a number in assembly. Now the first is no longer typed as a number, and thesecond is rejected, as in solc (7615).
The AST's
HexNumberExpression::integer_value/number_valuestill read the value off thenode's type. Only an address literal, whose type carries no value, is parsed from its source text.
Tests. Three overload tests (bare name, member access through
this,addressvsaddress payable) and ausing fortest. All four fail onmain: the overload tests with thediagnostics from the issue, the
using fortest withmember-not-found. The existing AST testfor
integer_valueon a 40-digit literal fails without the source-text fallback. No snapshotchanges.
Sourcify census (all 0.8.x, 2,326,676 contracts, #2181 harness, first commit only): failures
drop from 40,830 to 8,126, no contract that passed before fails, no panics.
bind:resolution/member-not-foundbind:resolution/no-matching-callable-declarationReplacing the literal kind with
addresschanges no contract's outcome on the same corpus.Most of the remaining
no-matching-callable-declarationcontracts (75 of 114) are a differentshape: a string literal shorter than N passed to a
bytesNoverload (DssExecLib'ssetValue(_vat, "Line", …)), filed as #2182.Public API.
slang_solidity_v2_semantic:LiteralKind::Addressis removed andtypes::literals::value_of_hex_number_expressionis added. The AST'sLiteralType::mobile_typeno longer returns an address.
Downstream. solx reads literal values off the type, so it needs a small change when it bumps
its Slang pin: lower an unfolded hex literal from
integer_value(). That change is ready. Builtagainst this branch, the solx lit suite and
cargo test-slangpass, and the Sol MLIR isbyte-identical to
mainfor every lit input plus an inline-assembly address constant.Not covered: solc rejects a 40-digit literal with an invalid checksum, and Slang still accepts it
(
TODO SDR[38]).Bencher. Two alerts on
compute_contracts_abi(merkle_proof+1.7%,pointer_libraries+2.5%estimated cycles). Instructions and memory accesses are identical to
main; only 1 and 3 accessesmoved from L1 to RAM, which the cycle estimate weights 35×.
semanticoncooldogsdrops 8.5% ininstructions.