Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions crates/sema/src/ty/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,35 @@ impl<'gcx> Ty<'gcx> {
}
}

// Integer literals can coerce to typed integers if they fit.
// Non-negative literals can coerce to both uint and int types.
(IntLiteral(neg, size), Elementary(UInt(target_size))) => {
// Unsigned: reject negative, check size fits
if neg {
Result::Err(TyConvertError::Incompatible)
} else if size.bits() <= target_size.bits() {
Ok(())
} else {
Result::Err(TyConvertError::Incompatible)
}
}
(IntLiteral(neg, size), Elementary(Int(target_size))) => {
// Signed: non-negative values need strict inequality since they use the
// positive range [0, 2^(N-1)-1]. Negative values use <= since negative
// int_literal[N] can fit in int(N) (e.g., -128 needs 8 bits, fits in int8).
if neg {
if size.bits() <= target_size.bits() {
Ok(())
} else {
Result::Err(TyConvertError::Incompatible)
}
} else if size.bits() < target_size.bits() {
Ok(())
} else {
Result::Err(TyConvertError::Incompatible)
}
}

// TODO: more implicit conversions
_ => Result::Err(TyConvertError::Incompatible),
}
Expand Down
44 changes: 44 additions & 0 deletions tests/ui/typeck/implicit_int_literal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//@compile-flags: -Ztypeck
function f() {
// === Non-negative literals to uint ===
// Value must fit in the unsigned range [0, 2^N - 1]
uint8 u8_max = 255;
uint8 u8_overflow = 256; //~ ERROR: mismatched types
uint16 u16_max = 65535;
uint16 u16_overflow = 65536; //~ ERROR: mismatched types
uint32 u32_max = 4294967295;
uint256 u256_max = 115792089237316195423570985008687907853269984665640564039457584007913129639935;

// === Non-negative literals to int ===
// TypeSize stores the actual bit length. For signed types, non-negative values
// need strict bit comparison since the sign bit takes one slot.
// E.g., 127 needs 7 bits, and int8 has 7 bits for magnitude, so it fits.
// But 128 needs 8 bits, which exceeds int8's 7-bit positive range.

// int_literal[1] (1-8 bits) -> int8+ works for values that fit (0-127)
int8 i8_max = 127;
// int_literal[1] (8 bits) -> int16+ works for 128-255 (needs 8 bits, exceeds int8's 7-bit positive range)
int16 i16_from_128 = 128;
int16 i16_from_255 = 255;

// int_literal[2] (9-16 bits) -> int32+ works for 256-32767
int16 i16_max = 32767;
// 32768 needs 16 bits, exceeds int16's 15-bit positive range
int32 i32_from_32768 = 32768;
int32 i32_from_65535 = 65535;

// Overflow cases
int16 i16_overflow = 65536; //~ ERROR: mismatched types

// === Zero and small values ===
// Zero needs 1 bit, works with uint8+ and int8+
uint8 zero_u8 = 0;
uint256 zero_u256 = 0;
uint8 one_u8 = 1;
uint256 one_u256 = 1;

int8 zero_i8 = 0;
int256 zero_i256 = 0;
int8 one_i8 = 1;
int256 one_i256 = 1;
}
20 changes: 20 additions & 0 deletions tests/ui/typeck/implicit_int_literal.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: mismatched types
╭▸ ROOT/tests/ui/typeck/implicit_int_literal.sol:LL:CC
LL │ uint8 u8_overflow = 256;
╰╴ ━━━ expected `uint8`, found `int_literal[2]`

error: mismatched types
╭▸ ROOT/tests/ui/typeck/implicit_int_literal.sol:LL:CC
LL │ uint16 u16_overflow = 65536;
╰╴ ━━━━━ expected `uint16`, found `int_literal[3]`

error: mismatched types
╭▸ ROOT/tests/ui/typeck/implicit_int_literal.sol:LL:CC
LL │ int16 i16_overflow = 65536;
╰╴ ━━━━━ expected `int16`, found `int_literal[3]`

error: aborting due to 3 previous errors

3 changes: 1 addition & 2 deletions tests/ui/typeck/lvalue/array_length.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//@compile-flags: -Ztypeck
// TODO: `mismatched types` errors on integer literals are a current limitation of solar

contract Test {
uint256[] dynamicArray;
uint256[10] fixedArray; //~ ERROR: mismatched types
uint256[10] fixedArray;
uint256 state;

function testDynamic() external {
Expand Down
8 changes: 1 addition & 7 deletions tests/ui/typeck/lvalue/array_length.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/array_length.sol:LL:CC
LL │ uint256[10] fixedArray;
╰╴ ━━ expected `uint256`, found `int_literal[1]`

error: member `length` is read-only and cannot be used to resize arrays
╭▸ ROOT/tests/ui/typeck/lvalue/array_length.sol:LL:CC
Expand All @@ -22,5 +16,5 @@ error: member `length` is read-only and cannot be used to resize arrays
LL │ arr.length = state;
╰╴ ━━━━━━━━━━

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

7 changes: 2 additions & 5 deletions tests/ui/typeck/lvalue/constant.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
//@compile-flags: -Ztypeck
// TODO: `mismatched types` errors on integer literals are a current limitation of solar

contract Test {
uint256 constant CONST = 1; //~ ERROR: mismatched types
uint256 constant CONST = 1;

function test() external {
CONST = 2; //~ ERROR: cannot assign to a constant variable
//~^ ERROR: mismatched types
}
}

uint256 constant FILE_CONST = 1; //~ ERROR: mismatched types
uint256 constant FILE_CONST = 1;

function fileLevel() {
FILE_CONST = 2; //~ ERROR: cannot assign to a constant variable
//~^ ERROR: mismatched types
}
26 changes: 1 addition & 25 deletions tests/ui/typeck/lvalue/constant.stderr
Original file line number Diff line number Diff line change
@@ -1,38 +1,14 @@
error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ uint256 constant CONST = 1;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: cannot assign to a constant variable
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ CONST = 2;
╰╴ ━━━━━

error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ CONST = 2;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ uint256 constant FILE_CONST = 1;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: cannot assign to a constant variable
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ FILE_CONST = 2;
╰╴ ━━━━━━━━━━

error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/constant.sol:LL:CC
LL │ FILE_CONST = 2;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: aborting due to 6 previous errors
error: aborting due to 2 previous errors

3 changes: 0 additions & 3 deletions tests/ui/typeck/lvalue/immutable.sol
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
//@compile-flags: -Ztypeck
// TODO: assignments to immutables in the constructor should be allowed
// TODO: `mismatched types` errors on integer literals are a current limitation of solar

contract Test {
uint256 immutable IMMUT;

constructor() {
// This should be OK in constructor but currently errors
IMMUT = 1; //~ ERROR: cannot assign to an immutable variable
//~^ ERROR: mismatched types
}

function test() external {
IMMUT = 2; //~ ERROR: cannot assign to an immutable variable
//~^ ERROR: mismatched types
}
}
14 changes: 1 addition & 13 deletions tests/ui/typeck/lvalue/immutable.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,11 @@ error: cannot assign to an immutable variable
LL │ IMMUT = 1;
╰╴ ━━━━━

error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/immutable.sol:LL:CC
LL │ IMMUT = 1;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: cannot assign to an immutable variable
╭▸ ROOT/tests/ui/typeck/lvalue/immutable.sol:LL:CC
LL │ IMMUT = 2;
╰╴ ━━━━━

error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/immutable.sol:LL:CC
LL │ IMMUT = 2;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: aborting due to 4 previous errors
error: aborting due to 2 previous errors

3 changes: 1 addition & 2 deletions tests/ui/typeck/lvalue/tuple.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//@compile-flags: -Ztypeck
// TODO: `mismatched types` errors on integer literals are a current limitation of solar

contract Test {
uint256 constant CONST = 1; //~ ERROR: mismatched types
uint256 constant CONST = 1;
uint256 state;

function testTupleWithConstant() external {
Expand Down
8 changes: 1 addition & 7 deletions tests/ui/typeck/lvalue/tuple.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
error: mismatched types
╭▸ ROOT/tests/ui/typeck/lvalue/tuple.sol:LL:CC
LL │ uint256 constant CONST = 1;
╰╴ ━ expected `uint256`, found `int_literal[1]`

error: cannot assign to a constant variable
╭▸ ROOT/tests/ui/typeck/lvalue/tuple.sol:LL:CC
Expand All @@ -22,5 +16,5 @@ error: mismatched types
LL │ (1, state) = (x, x);
╰╴ ━━━━━━ expected `tuple(int_literal[1],uint256)`, found `tuple(uint256,uint256)`

error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

Loading