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

Add more functionality to where clause #2715

Open
CGQAQ opened this issue Jun 23, 2019 · 10 comments
Open

Add more functionality to where clause #2715

CGQAQ opened this issue Jun 23, 2019 · 10 comments

Comments

@CGQAQ
Copy link

CGQAQ commented Jun 23, 2019

The where clause is compile-time check, it's a great idea. but I think we can make it even more great by add some more functionality to it.

  1. range check: require port is constexpr implicitly
fn foo(port: usize)
    where   port <= 65535,
            port > 1000,
            port in 1000..65536 // or this one, much better
{}
  1. make it general purpose
let foo = 1..500 where _ % 4 == 0 // something like this ( _ maybe better with it )
let foo = 1..100 where it % 2 == 0 //ah much better

Motivation
In 1, it will improving some performent and much easier to optimize code, not letting code jump around
In 2, just let where everywhere, I think people will love it

@RustyYato
Copy link

I think this falls under const-generics, although with a different syntax.

@CGQAQ
Copy link
Author

CGQAQ commented Jun 23, 2019

I think this falls under const-generics, although with a different syntax.

I don't think so, with

fn foo(port: usize)
    where   port <= 65535,
            port > 1000,
            port in 1000..65536 // or this one, much better
{}

compile-time range check, you can reduce several jumps(conditional jump) in final generate, just because in order to compile-time range check, you need know the param value on the compile time, don't same with const-generics at all

@RustyYato
Copy link

RustyYato commented Jun 23, 2019

That is the same as const-generics once it gets extended with where clauses,

fn foo<const port: usize>()
    where   port <= 65535,
            port > 1000,
            port in 1000..65536 // or this one, much better
{}

Right now const generics can't do this, but they should be able to once they get extended later.

@CGQAQ
Copy link
Author

CGQAQ commented Jun 23, 2019

@KrishnaSannasi in the RFC, I didn't see any about where clause range check thing, my proposal is only relevant to where clause, make it more general purpose

@RustyYato
Copy link

RustyYato commented Jun 23, 2019

That is true, in the discussion for the RFC, these where clauses were considered and postponed until after we got const generics. Implementing these where clauses is a large effort, and can only be done after const generics, specifically after we stop treating expressions in const generics as black boxes.

I wasn't trying to discourage this, just noting that this seemed to be related to const generics, sorry if I gave the wrong impression.

@nielsle
Copy link

nielsle commented Jun 23, 2019

Here is an issue that links to other issues about refinement types. They don't us the where syntax, but the ideas are similar to yours. #671

If you are just interested in speed, then it may help to add an assert! at the beginning of the function.
https://gist.github.com/kvark/f067ba974446f7c5ce5bd544fe370186#assert-conditions-beforehand

@tema3210
Copy link

Sounds like Haskells guard expression, in your examples above just .filter() can be used.

That is the same as const-generics once it gets extended with where clauses,

fn foo<const port: usize>()
    where   port <= 65535,
            port > 1000,
            port in 1000..65536 // or this one, much better
{}

Right now const generics can't do this, but they should be able to once they get extended later.

That's it, we will have this instead, moreover thing you are proposing is actually the same.

@sivizius
Copy link

sivizius commented May 12, 2020

This might allow/help tools to do formal verification of code. Even if there are no runtime checks (at least in release mode), e.g. Hoare-logic and wp-calculus comes to my mind here: fn abs(value: i8) { … } for example could be annotated as:

  fn abs<P,Q>(value: P) -> Q
  where
    P: i8 + (i8::MIN+1)..=i8::MAX, // abs(-128) is -128, which is wrong
    Q: i8 + 0..=i8::MAX, // the return type is i8, but it is guarantied to be positive
  { … }

and every call of this function could be back traced so that every value, that might end up in this call, is guarantied to be in this range. I have read this pdf and I think, it might be useful to implement this into the language itself in an optional manner, even if the compiler usually ignores these annotations.

@hadronized
Copy link
Contributor

hadronized commented May 12, 2020

This is an interesting idea but I would prefer we get ConstraintKinds first — so that we can declare constraints. Then, a simple bool can become a constraint, and your code is valid if the bool is const.

In Haskell, you typically use the Constraint kind to introduce this. For instance, you can declare a type operator, data a <= b, which kind will be Constraint, so that you can use it in the place of constraints — so-called trait bounds in Rust, in which we currently have bounds and lifetime annotations.

@kennytm
Copy link
Member

kennytm commented May 12, 2020

Regarding #2715 (comment), this syntax conflicts with type ascription when parsing.

macro_rules! x {
    ($i:item) => {}
}
macro_rules! y {
    (fn f() where $e:expr, $f:expr,;) => {}
}
x! {
    fn f()
    where 
        A: B + C<D, E>::F,
    ;
}
y! {
    fn f() 
    where 
        A: B + C < D, 
        E > ::F,
    ;
}

This is also why #1932 chose the with keyword. If we could really get a where clause for const generics, I suggest we combine with the syntax of #2920 to get an unambiguous syntax.

where
    const { A: B + C < D },
    const { E > ::F },
    A: B + C<D, E>::F,

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

No branches or pull requests

7 participants