Skip to content

Commit

Permalink
syntax: Tweak parsing lifetime bounds on closures
Browse files Browse the repository at this point in the history
In summary these are some example transitions this change makes:

    'a ||       => ||: 'a
    proc:Send() => proc():Send

The intended syntax for closures is to put the lifetime bound not at the front
but rather in the list of bounds. Currently there is no official support in the
AST for bounds that are not 'static, so this case is currently specially handled
in the parser to desugar to what the AST is expecting. Additionally, this moves
the bounds on procedures to the correct position, which is after the argument
list.

The current grammar for closures and procedures is:

    procedure := 'proc' [ '<' lifetime-list '>' ] '(' arg-list ')'
                        [ ':' bound-list ] [ '->' type ]
    closure := [ 'unsafe' ] ['<' lifetime-list '>' ] '|' arg-list '|'
                        [ ':' bound-list ] [ '->' type ]
    lifetime-list := lifetime | lifetime ',' lifetime-list
    arg-list := ident ':' type | ident ':' type ',' arg-list
    bound-list := bound | bound '+' bound-list
    bound := path | lifetime

This does not currently handle the << ambiguity in `Option<<'a>||>`, I am
deferring that to a later patch. Additionally, this removes the support for the
obsolete syntaxes of ~fn and &fn.

Closes #10553
Closes #10767
Closes #11209
Closes #11210
Closes #11211
  • Loading branch information
alexcrichton committed Apr 4, 2014
1 parent e63346b commit 304d82a
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 127 deletions.
39 changes: 38 additions & 1 deletion src/doc/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -3327,8 +3327,21 @@ x = bo(5,7);

### Closure types

The type of a closure mapping an input of type `A` to an output of type `B` is `|A| -> B`. A closure with no arguments or return values has type `||`.
~~~~ {.notrust .ebnf .notation}
closure_type := [ 'unsafe' ] [ '<' lifetime-list '>' ] '|' arg-list '|'
[ ':' bound-list ] [ '->' type ]
procedure_type := 'proc' [ '<' lifetime-list '>' ] '(' arg-list ')'
[ ':' bound-list ] [ '->' type ]
lifetime-list := lifetime | lifetime ',' lifetime-list
arg-list := ident ':' type | ident ':' type ',' arg-list
bound-list := bound | bound '+' bound-list
bound := path | lifetime
~~~~

The type of a closure mapping an input of type `A` to an output of type `B` is
`|A| -> B`. A closure with no arguments or return values has type `||`.
Similarly, a procedure mapping `A` to `B` is `proc(A) -> B` and a no-argument
and no-return value closure has type `proc()`.

An example of creating and calling a closure:

Expand All @@ -3351,6 +3364,30 @@ call_closure(closure_no_args, closure_args);

```

Unlike closures, procedures may only be invoked once, but own their
environment, and are allowed to move out of their environment. Procedures are
allocated on the heap (unlike closures). An example of creating and calling a
procedure:

```rust
let string = ~"Hello";

// Creates a new procedure, passing it to the `spawn` function.
spawn(proc() {
println!("{} world!", string);
})

// the variable `string` has been moved into the previous procedure, so it is
// no longer usable.


// Create an invoke a procedure. Note that the procedure is *moved* when
// invoked, so it cannot be invoked again.
let f = proc(n) { n + 22 };
println!("answer: {}", f(20));

```

### Object types

Every trait item (see [traits](#traits)) defines a type with the same name as the trait.
Expand Down
12 changes: 0 additions & 12 deletions src/libsyntax/parse/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ pub enum ObsoleteSyntax {
ObsoleteEnumWildcard,
ObsoleteStructWildcard,
ObsoleteVecDotDotWildcard,
ObsoleteBoxedClosure,
ObsoleteClosureType,
ObsoleteMultipleImport,
ObsoleteManagedPattern,
ObsoleteManagedString,
Expand Down Expand Up @@ -111,16 +109,6 @@ impl<'a> ParserObsoleteMethods for Parser<'a> {
"vec slice wildcard",
"use `..` instead of `.._` for matching slices"
),
ObsoleteBoxedClosure => (
"managed or owned closure",
"managed closures have been removed and owned closures are \
now written `proc()`"
),
ObsoleteClosureType => (
"closure type",
"closures are now written `|A| -> B` rather than `&fn(A) -> \
B`."
),
ObsoleteMultipleImport => (
"multiple imports",
"only one import is allowed per `use` statement"
Expand Down
Loading

4 comments on commit 304d82a

@bors
Copy link
Contributor

@bors bors commented on 304d82a Apr 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from cmr
at alexcrichton@304d82a

@bors
Copy link
Contributor

@bors bors commented on 304d82a Apr 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging alexcrichton/rust/parse-closure = 304d82a into auto

@bors
Copy link
Contributor

@bors bors commented on 304d82a Apr 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alexcrichton/rust/parse-closure = 304d82a merged ok, testing candidate = 899c635

@bors
Copy link
Contributor

@bors bors commented on 304d82a Apr 5, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.