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

Inferred generic (poly type) constraints #35

Open
kaleidawave opened this issue Jun 19, 2023 · 2 comments · May be fixed by #197
Open

Inferred generic (poly type) constraints #35

kaleidawave opened this issue Jun 19, 2023 · 2 comments · May be fixed by #197
Assignees
Labels
checking Issues around checking feedback-needed Extra attention/consensus is needed
Milestone

Comments

@kaleidawave
Copy link
Owner

kaleidawave commented Jun 19, 2023

This was implemented in the initial release but relied on mutating Type during checking which caused problems in conditional branches and the such. This issues is a second attempt that stores "requests" that are applied at the boundary.

A aim of Ezno is to work without writing type annotations. Variables don't need them because of the value system, return types are based on the body. The final piece is the unknown-ness of inputs to functions.

This can be in several places:

Explicit parameter

function func1(a) {
    return a.x // The constraint of `a` should be inferred as `{ x: any }`
}

Non restricted variable

let a = 4;
function func2() {
    return Math.sin(a) // The constraint of closed over references `a` should be inferred as number (with strict casts at least)
}

Cycles (recursion)

interface Node {
    parent: Node | null,
    x: 
}

function depth(obj: Node) {
    if (obj.parent) {
        // `depth` hasn't been checked yet. A restriction should be made
        return depth(obj.parent) + 1
    } else {
        return 0
    }
}

See #29

Others

  • Throw...

any as unknown

To better support existing codebases any should be treated as unknown. No annotation should be treated as unknown

Combining restrictions

When two restrictions are made they are combined using &

interface X {
    readable: boolean
}

interface Y {
    name: string
}

function x(p: X) {}
function y(p: Y) {}

function z(param1) {
    x(param1)
    y(param1)
}

param1 is now restricted to X & Y.

this might create impossible types (string & number), which is fine but a warning should be raised

Places where constraint inference is done

  • Calling a type
  • Getting a property
  • subtype-ing. If x has a unknown restriction and x <: number is evaluated, then x's restriction becomes number

I had up to here existing implemented, the hard part is now:

Nesting

function x(obj) {
     return obj.prop1.prop2.prop3
}

This needs to place a inference condition on a inference restriction 😅

The non-local unknown issue

If unknown is found on a fixed restriction, then a nested dynamic restriction might have to be on a fixed restriction.

interface Something {
    prop: any
}

function doSomethingWithSomething(s: Something) {
    return Math.sin(s.prop)
}

extended from https://github.com/kaleidawave/ezno/blob/main/checker/docs/inference.md

It is still in progress the best way to tackle this, interested if people have real world parameter inference examples they want supported:

@kaleidawave kaleidawave added feedback-needed Extra attention/consensus is needed checking Issues around checking labels Jun 19, 2023
@kaleidawave kaleidawave self-assigned this Jun 19, 2023
@kaleidawave kaleidawave added this to the 0.1.0 milestone Jun 23, 2023
@kaleidawave

This comment was marked as resolved.

@kaleidawave
Copy link
Owner Author

Above comment should be figured out in #60

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
checking Issues around checking feedback-needed Extra attention/consensus is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant