Files
swift-mirror/test/LiteralExpressions/IntegerGenericArithmetic.swift
Artem Chikin 0d39a2b257 [Literal Expressions] Use arithmetic shift for signed >>
The expression folder previously applied `APInt::lshr` for every `>>` regardless of signedness. For a negative signed operand this yields a large positive value and diverges from Swift runtime behavior, which performs an arithmetic right shift that preserves the sign bit.

Dispatch to `APInt::ashr` when the operand type is signed, and retain `APInt::lshr` for unsigned operands.
2026-05-08 14:23:24 +01:00

152 lines
6.2 KiB
Swift

// Literal expressions in integer generic parameter values
// REQUIRES: swift_feature_LiteralExpressions
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature LiteralExpressions -verify
// =============================================================================
// Arithmetic operators
// =============================================================================
let add1: InlineArray<(2 + 3), Int> = [1, 2, 3, 4, 5]
let add2: InlineArray<(0 + 5), Int> = [1, 2, 3, 4, 5]
let add3: InlineArray<(1 + 1 + 1), Int> = [1, 2, 3]
let sub1: InlineArray<(5 - 2), Int> = [1, 2, 3]
let sub2: InlineArray<(10 - 5 - 2), Int> = [1, 2, 3]
let mul1: InlineArray<(2 * 3), Int> = [1, 2, 3, 4, 5, 6]
let mul3: InlineArray<(2 * 2 * 2), Int> = [1, 2, 3, 4, 5, 6, 7, 8]
let div1: InlineArray<(10 / 2), Int> = [1, 2, 3, 4, 5]
let div2: InlineArray<(9 / 3), Int> = [1, 2, 3]
let mod1: InlineArray<(7 % 4), Int> = [1, 2, 3]
let mod2: InlineArray<(10 % 3), Int> = [1]
// =============================================================================
// Bitwise operators
// =============================================================================
let and1: InlineArray<(7 & 3), Int> = [1, 2, 3]
let or1: InlineArray<(2 | 1), Int> = [1, 2, 3]
let xor1: InlineArray<(5 ^ 2), Int> = [1, 2, 3, 4, 5, 6, 7]
let lshift1: InlineArray<(1 << 3), Int> = [1, 2, 3, 4, 5, 6, 7, 8]
let lshift2: InlineArray<(1 << 5), Int> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32]
let rshift1: InlineArray<(16 >> 2), Int> = [1, 2, 3, 4]
let rshift2: InlineArray<(32 >> 3), Int> = [1, 2, 3, 4]
// Signed right shift folds arithmetically. Without arithmetic shift, the size
// would either be negative or an enormous logical-shift result, both of which
// would fail to type-check as an InlineArray size.
let rshiftSigned: InlineArray<(0 - (-8 >> 1)), Int> = [1, 2, 3, 4]
// =============================================================================
// Overflow arithmetic operators
// =============================================================================
let overflowAdd: InlineArray<(2 &+ 3), Int> = [1, 2, 3, 4, 5]
let overflowSub: InlineArray<(7 &- 2), Int> = [1, 2, 3, 4, 5]
let overflowMul: InlineArray<(2 &* 3), Int> = [1, 2, 3, 4, 5, 6]
// =============================================================================
// Masking shift operators
// =============================================================================
let maskingLShift: InlineArray<(1 &<< 3), UInt8> = [0, 0, 0, 0, 0, 0, 0, 0]
let maskingRShift: InlineArray<(16 &>> 2), UInt8> = [0, 0, 0, 0]
// =============================================================================
// Operator Precedence
// =============================================================================
let prec1: InlineArray<(2 + 3 * 2), Int> = [1, 2, 3, 4, 5, 6, 7, 8]
let prec2: InlineArray<(10 - 6 / 2), Int> = [1, 2, 3, 4, 5, 6, 7]
let prec3: InlineArray<(1 << 2 + 1), Int> = [1, 2, 3, 4, 5]
// =============================================================================
// Parentheses
// =============================================================================
let paren1: InlineArray<((2 + 3)), Int> = [1, 2, 3, 4, 5]
let paren2: InlineArray<((2 + 3) * 2), Int> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let paren3: InlineArray<(2 * (1 + 2)), Int> = [1, 2, 3, 4, 5, 6]
let paren4: InlineArray<((1 + 1) * 2), Int> = [1, 2, 3, 4]
// =============================================================================
// Sugar Syntax [N of T]
// =============================================================================
let sugar1: [(2 + 3) of Int] = [1, 2, 3, 4, 5]
let sugar2: [(1 << 2) of String] = ["a", "b", "c", "d"]
let sugar3: [((2 * 3)) of Double] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
// =============================================================================
// Nested
// =============================================================================
let nested1: InlineArray<(1 + 1), InlineArray<(2 + 1), Int>> = [[1, 2, 3], [4, 5, 6]]
let nested2: [(2 * 2) of [(1 + 2) of Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
// =============================================================================
// Function Parameters
// =============================================================================
func takeInlineArray<T>(_ arr: InlineArray<(2 + 2), T>) {}
func takeSugarArray<T>(_ arr: [(1 << 1) of T]) {}
func testFunctionCalls() {
takeInlineArray([1, 2, 3, 4])
takeInlineArray(["a", "b", "c", "d"])
takeSugarArray([1, 2])
takeSugarArray(["x", "y"])
}
// =============================================================================
// Type Aliases with Literal Expression Generics
// =============================================================================
typealias FourInts = InlineArray<(2 * 2), Int>
typealias EightStrings = InlineArray<(1 << 3), String>
typealias SugarSixDoubles = [(2 + 4) of Double]
let alias1: FourInts = [1, 2, 3, 4]
let alias2: EightStrings = ["a", "b", "c", "d", "e", "f", "g", "h"]
let alias3: SugarSixDoubles = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
// =============================================================================
// Struct Fields
// =============================================================================
struct Container {
var data: InlineArray<(3 + 2), Int>
var buffer: [(1 << 2) of UInt8]
}
func testStruct() {
let c = Container(data: [1, 2, 3, 4, 5], buffer: [0, 1, 2, 3])
_ = c
}
// =============================================================================
// Return Types
// =============================================================================
func makeArray() -> InlineArray<(2 + 1), Int> {
return [1, 2, 3]
}
func makeSugarArray() -> [(4 - 1) of String] {
return ["a", "b", "c"]
}
// =============================================================================
// Expression position
// =============================================================================
let addExpr1 = InlineArray<(2 + 3), Int>(repeating: 5)
let addExpr2 = InlineArray<(0 + 5), Int>(repeating: 4)