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

Discussion: Constrains for numerical types? #16257

Closed
iam3yal opened this issue Jan 5, 2017 · 11 comments
Closed

Discussion: Constrains for numerical types? #16257

iam3yal opened this issue Jan 5, 2017 · 11 comments

Comments

@iam3yal
Copy link

iam3yal commented Jan 5, 2017

At the moment we can have constraints for generics parameters, I wonder what people think about constrains for the native numerical types?

I know it's related to Design by Contract but I think that this is a more simple problem and isn't so ambitious and it can always be expanded in the future either to support more types or/and user-defined types.

So what I'm thinking is something like this:

class Point
{
	Point(int x where x > 0, int y where y > x)
	{
	}
}

Bad idea? good idea? what do you think?

@HaloFour
Copy link

HaloFour commented Jan 5, 2017

I think that this falls firmly under Method Contracts. I certainly wouldn't want one way to enforce numeric "constraints" vs. enforcing method contracts. I'd suspect that 99% of method contracts would be validating non-null references and ensuring that numbers are within range.

@iam3yal
Copy link
Author

iam3yal commented Jan 5, 2017

@HaloFour

I certainly wouldn't want one way to enforce numeric "constraints" vs. enforcing method contracts.

I don't think that we will ever see method contracts and this is the reason I'm thinking about ways to somehow have a slim down version to at least have preconditions formalized as part of the language as constraints.

I'd suspect that 99% of method contracts would be validating non-null references and ensuring that numbers are within range.

This is the reason I'm thinking about it.

Non-null references can be or should be implied whereas range needs to be explicit so I thought that the way we express constraints for generic parameters can be a good fit.

@gordanr
Copy link

gordanr commented Jan 5, 2017

I am very interested in constraints, but I would rather wait for general solution with method contracts.
...
Whenever it would be ready for implementation (C# 10/11/...)

@HaloFour
Copy link

HaloFour commented Jan 5, 2017

@eyalsk

I don't think that we will ever see method contracts and this is the reason I'm thinking about ways to somehow have a slim down version to at least have preconditions formalized as part of the language as constraints.

Perhaps, but the reasons that method contracts might not happen would apply equally to this proposal. Specifically how the constraints would be encoded in the assembly metadata and exactly how the constraint is enforced when violated. Your proposal doesn't touch on either.

@iam3yal
Copy link
Author

iam3yal commented Jan 5, 2017

@HaloFour This isn't a proposal, just a discussion... 😄

@iam3yal
Copy link
Author

iam3yal commented Jan 5, 2017

@gordanr

I am very interested in constraints, but I would rather wait for general solution with method contracts.

I'd love it myself but seeing that there were many attempts and the design team still think it's a bad idea or that it's too complex or too verbose I'd say the odds aren't in our favour.

@HaloFour
Copy link

HaloFour commented Jan 5, 2017

@eyalsk

This isn't a proposal, just a discussion... 😄

Either way, I'd argue that it's the most important aspect of the discussion.

Source generators could probably handle the simpler cases. Toss attributes on the parameters and the generator could emit replacements which perform argument validation.

@iam3yal
Copy link
Author

iam3yal commented Jan 5, 2017

@HaloFour

Source generators could probably handle the simpler cases. Toss attributes on the parameters and the generator could emit replacements which perform argument validation.

The issue is that two different implementations may generate different attributes for different projects and you may end up needing multiple source generators, another issue is you don't really want to fail-fast at run-time, you want compile-time errors and analysis.

Now, we can probably implement this through analyzers but there's no formalized attributes that are standardized for this so each 3rd-party may have its own thing.

@iam3yal
Copy link
Author

iam3yal commented Jan 5, 2017

@HaloFour

Either way, I'd argue that it's the most important aspect of the discussion.

I'll think about it, I mostly think about having the information embedded as attributes but it's a bit cumbersome.

There are some high level questions like:

  1. How operators are represented in attributes? ">" as a string or ContractGreaterThanAttribute as a type or IsGreaterThan as a method, etc..

  2. How conditions are composed together? e.g., y > x || 0 > y

I think that the first part should be about having the information available so analyzers can take advantage of this or something like this.

p.s. I think you want this information or at least prefer this information to be part of the PE metadata but I'm not sure what changes this require.

@iam3yal iam3yal closed this as completed Jan 6, 2017
@gordanr
Copy link

gordanr commented Jan 6, 2017

Maybe it is better not to work with construcors (special case) in constraint examples. Let we take general method with slightly changed syntax (#119).

class Point
{
	public void DoSomething(int x, int y) requires x > 0 && y > x
	{
	    ...	
	}
}

@eyalsk I don't think that attributes are good approach to encoding constraints in assembly metadata. It is too complicate and impractical.

Compiler could easily generate private hidden method for every constraint and every constraint type (requires, ensures).
This method is hidden and always returns bool value.
Method is encoded in the assembly without losing any information about constraint.
Generated method is associated with constraint definition. Over it's name or in any other way.
This method is ready for any type of use (run time violation report or much better some compile time analysis).
Expression in constraint probably should not be part of the method signature, but it is shown in documentation and hints (similar as return type).
This approach doesn't require any clr change. (I hope)

class Point
{
    public void DoSomething(int x, int y)
    {
       if (!$requires_DoSomething(x, y)) => throw MethodContractException(nameof(DoSomething));            
       ...
    }

    private bool $requires_DoSomething(int x, int y) => x > 0 && y > x;
}

I put throw Exception in the case of violation, but it is open question.
I had focus on encoding constraints in assembly metadata.

@iam3yal
Copy link
Author

iam3yal commented Jan 6, 2017

@gordanr

I don't think that attributes are good approach to encoding constraints in assembly metadata. It is too complicate and impractical.

Yeah that is the reason I've closed this discussion, I've played with it and it seems really chaotic. 😄

Compiler could easily generate private hidden method for every constraint and every constraint type (requires, ensures).
This method is hidden and always returns bool value.
Method is encoded in the assembly without losing any information about constraint.
Generated method is associated with constraint definition. Over it's name or in any other way.
This method is ready for any type of use (run time violation report or much better some compile time analysis).
Expression in constraint probably should not be part of the method signature, but it is shown in documentation and hints (similar as return type).
This approach doesn't require any clr change. (I hope)

The best second place I can think about adding this information is xml comments but yeah the best place is in the PE metadata, the question what needs to change in order for this to take place and how complex this change is and then I'm not sure whether it impact compatibility.

I think that the approach you're proposing can probably be done with generators but it has the same problem as I pointed above

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

No branches or pull requests

4 participants