Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved type testing #71

Open
oscbyspro opened this issue Apr 8, 2023 · 3 comments
Open

Improved type testing #71

oscbyspro opened this issue Apr 8, 2023 · 3 comments
Labels
await can't be done yet brrr such code, much wow

Comments

@oscbyspro
Copy link
Owner

oscbyspro commented Apr 8, 2023

Joseph Groff mentioned a potential type testing feature:

Ultimately, though, I'd like to see us expose that kind of more expressive efficient type testing in the language too. It would be great if you could do things like [...] without the overhead of the extraneous checks, the need for a value of a type to ask for properties of the type itself, or the implied wrapping of casting something as? P.

func foo<T>(x: T, y: T) -> T {
    if  where T == Int {
        return x + y // we can assume x and y are Int here
    }

    if <U> where T == Array<U> {
        return x + y // we can assume x and y are some kind of Array here
    }

    if  where T: Addable {
        return x.add(y) // we can assume x and y conform to Addable here
    }

    return x
}
@oscbyspro oscbyspro added brrr such code, much wow await can't be done yet labels Apr 8, 2023
@oscbyspro
Copy link
Owner Author

oscbyspro commented Apr 8, 2023

The type inference part would allow me to omit the "OrCrash" part from methods like:

func _multipliedFullWidth(by amount: Self) -> DoubleWidth {
    if  High.Magnitude.self == Low.self {
        return self._multipliedFullWidthAsKaratsubaAsDoubleWidthOrCrash(by: amount)
    }
    
    return self._multipliedFullWidthAsNormal(by: amount)
}
func _multipliedFullWidthAsKaratsubaAsDoubleWidthOrCrash(by amount: Self) -> DoubleWidth {
    assert(High.Magnitude.self == Low.self)
    let negate: Bool = self.isLessThanZero != amount.isLessThanZero
    let lhs =   self.magnitude as! ANKFullWidth<Low, Low>
    let rhs = amount.magnitude as! ANKFullWidth<Low, Low>
    let product = lhs._multipliedFullWidthAsKaratsubaAsUnsigned(by: rhs) as! Magnitude.DoubleWidth
    return DoubleWidth(bitPattern: negate ? product.twosComplement() : product)
}

@oscbyspro
Copy link
Owner Author

oscbyspro commented Apr 8, 2023

Another directly applicable use case would be improving methods like the following:

init?(exactly source: some BinaryInteger) {
    if  let source = source as? Self {
        self = source
        return
    }
    
    if  let source = source as? Int {
        self.init(_exactlyAsDigit: source)
        return
    }
    
    if  let source = source as? UInt {
        self.init(_exactlyAsDigit: source)
        return
    }
    
    if  let source = source as? Magnitude {
        self.init(_exactlyAsMagnitude: source)
        return
    }
   
    self.init(_exactlyAsBinaryInteger: source)
}

@oscbyspro oscbyspro changed the title Efficient type testing Better type testing Apr 9, 2023
@oscbyspro oscbyspro changed the title Better type testing Improved type testing Apr 9, 2023
@oscbyspro
Copy link
Owner Author

oscbyspro commented Apr 10, 2023

It hasn't even been pitched yet, but I want the ability to add paths that are only evaluated when a function is specialized. This would be useful in cases where a type-checked fast path is slower than an unchecked slow path. It would also speed up the unspecialized slow path, which is otherwise slowed down by having to fail a bunch of type checks first.

init?<T>(exactly source: T) where T: BinaryInteger {
    // fast paths that only exist when specialized
    if where(specialized) T == Self { ... }
    if where(specialized) T == Int  { ... }
    if where(specialized) T == UInt { ... }
    // only the slow path exists when unspecialized
    self.init(_exactlyAsBinaryInteger: source)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
await can't be done yet brrr such code, much wow
Projects
None yet
Development

No branches or pull requests

1 participant