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

RFC: should closure type expr (|A| -> B) support an optional & sigil? #10720

Closed
pnkfelix opened this issue Nov 29, 2013 · 1 comment
Closed

Comments

@pnkfelix
Copy link
Member

With new style closure type syntax (|A| -> B, or more generally <'lt>|A|:K -> B), one no longer includes a sigil. I believe the motivation for this was that the type |A| -> B can only be used with borrowed-pointers, and thus one can unambiguously remove the sigil.

The problem, which did not occur to me until last night (see concrete example below [1]), is that the sigiled borrowed pointer syntax &T is more generally &'lt T.

From what I can tell from looking at the parser code and from my own experiments, pcwalton's commit f27272d that added support for new-style closure types made sure that one can still express explicit lifetimes on new-style closure types, even without the sigil.

With commit f27272d, one writes the type like this: 'lt |A| -> B.

  • (Or more generally, 'lt1 <'lt2>|A|:K -> B)

However, I find it disconcerting to see that 'lt floating out there like that. Maybe I just need time to adjust, but I would prefer to keep the & for the cases when one needs to express the lifetime for the reference.


A coherent and non-ugly way to achieve the above goal, IMO, would be to adopt the following syntax:

  • |A| -> B is sugar for &|A| -> B. (This obviously is not a recursive desugaring.)
  • 'lt |A| -> B becomes illegal
  • If you need a lifetime, you have to write it out like so: &'lt |A| -> B

I see the above sugar as having precedent in C function pointers, where

int doub(int x) { return x + x; }
struct Dotwice {
    int (*f)(int);
    ...
};
int main() {
    Dotwice quad;
    quad.f = &doub;
    // is same as quad.f = doub;
    // but not same as quad.f = &&doub;
}

I have not thought through whether an analogous sugaring should be applied to Rust's lambda expression syntax, or even could be. The only case where it would arise would be when you would need to feed in an explicit lifetime for the reference you create when you construct a closure, i.e.:

    let dotwice : <'a>|f:&'a |int| -> int| -> (&'a |int| -> int)
        = |f| { &'a |x| f(f(x)) };

which cannot currently be expressed at all AFAICT. (I think it can make sense in Rust's memory model, though I might not have all the necessary bounds encoded above.)


(I might also have missed some of the relevant conversation here. I.e. perhaps there is some future goal to extend the kind-bounds K on the closure type to allow one to put the lifetime constraint for the reference there; right now the only lifetime allowed there is 'static.)


[1] Concrete example of where the above need to write 'lt |A| -> B arises:

fn main() {
    let double = |x:int| { x + x };
    trait Xform<T> { fn x(&self, T) -> T; }
    struct Dotwice<'a, T> { f: 'a|T| -> T }
    impl<'a, T> Xform<T> for Dotwice<'a, T> {
        fn x(&self, t:T) -> T { (self.f)((self.f)(t)) }
    }

    let quadrupler = Dotwice{ f: double };
    let eight = quadrupler.x(2);

    println!("eight: {}", eight);
}

cc @pcwalton @nikomatsakis

@nikomatsakis
Copy link
Contributor

Dup #10553 -- basically the syntax 'lt |A| -> R is a bug, it should be part of the bound. I'm planning on fixing this.

flip1995 pushed a commit to flip1995/rust that referenced this issue May 5, 2023
run linkcheck in clippy ci

fixes rust-lang#10711

changelog: Run [linkcheck.sh](https://github.com/rust-lang/rust/blob/master/src/tools/linkchecker/linkcheck.sh) from rustc repo in Remark.yml to check Clippy book.
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

2 participants