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

Support constraint intersection syntax #15413

Merged
merged 16 commits into from
Aug 2, 2023
Merged

Support constraint intersection syntax #15413

merged 16 commits into from
Aug 2, 2023

Conversation

kerams
Copy link
Contributor

@kerams kerams commented Jun 15, 2023

Implements fsharp/fslang-suggestions#1262.

devenv_FWOQ9ny9h7

The parser changes could quite possibly be improved - it's not my forte.

RE: fsharp/fslang-suggestions#1262 (comment)

If we had intersection types there would be all sorts of restrictions - e.g. string & int is not possible nor any sealed type.

Elsewhere in the code, there's this check:

if newOk = NoNewTypars && isSealedTy g tyR then
    errorR(Error(FSComp.SR.tcInvalidConstraintTypeSealed(), m))

Not sure why this should only kick in for NoNewTypars. In TcIntersectionConstraint new typars seemed to always be OK, so such check would have no effect. However, currently we get this, which should be sufficient anyway:

image

@kerams kerams requested a review from a team as a code owner June 15, 2023 17:21
@vzarytovskii
Copy link
Member

Probably needs a small addition to rfc/new small rfc, so behaviour is documented.

@Lanayx
Copy link
Contributor

Lanayx commented Jun 15, 2023

@kerams will it make possible to intersect generic and non-generic restrictions? E.g.

let test (env: 'T & #IDisposable & #ILogger<'T>) =
    ()

@kerams
Copy link
Contributor Author

kerams commented Jun 15, 2023

Yes, but unless I am misunderstanding something, your constraints are not satisfiable. 'T cannot be an ILogger of itself.

This appears to be doable:

let test (env: 't & #seq<'u> & #Collections.IEnumerable) =
    ()

test [ [ 1 ] ]

src/Compiler/FSComp.txt Outdated Show resolved Hide resolved
@Lanayx
Copy link
Contributor

Lanayx commented Jun 15, 2023

'T cannot be an ILogger of itself.

I think it can, the whole Generic Maths feature is build atop of 'T when 'T :> INumber<'T>
https://learn.microsoft.com/en-us/dotnet/standard/generics/math

@kerams
Copy link
Contributor Author

kerams commented Jun 15, 2023

@Lanayx, you're right. I don't quite understand how, but this works:

let test (env: 't & #System.Numerics.INumber<'t> & #IEquatable<'t>) =
    ()

let test2 (env: 't when 't :> #System.Numerics.INumber<'t> and 't :> IEquatable<'t>) =
    ()

test 1
test2 1

@vzarytovskii
Copy link
Member

@Lanayx, you're right. I don't quite understand how, but this works:

let test (env: 't & #System.Numerics.INumber<'t> & #IEquatable<'t>) =
    ()

let test2 (env: 't when 't :> #System.Numerics.INumber<'t> and 't :> IEquatable<'t>) =
    ()

test 1
test2 1

Yeah, that's pretty much due to changes we introduced for static abstracts in interfaces. At least I believe so.

@Lanayx
Copy link
Contributor

Lanayx commented Jun 15, 2023

That's great! In that case it will subsume the old syntax (which I didn't like anyway), e.g. instead of

let test (env: 'T when INumber<'T>) =
    ()

we'll be able to write

let test (env: 'T & #INumber<'T>) =
    ()

@En3Tho
Copy link
Contributor

En3Tho commented Jun 15, 2023

Why do you think constraints are not solvable? It's just an interface like for example INumber'TSelf which works via implementing an interface of itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

7 participants