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

Fix grammar for variadic functions #781

Open
wants to merge 2 commits into
base: master
from
Open

Conversation

matklad added 2 commits Mar 13, 2020
First, variadic params can be named:

    extern "C" {
        fn f(_: *mut u8, _: ...);
    }

Second, variadic params can be followed by a comma

    extern "C" {
        fn f(_: *mut u8, ...,);
    }
@ehuss
Copy link
Collaborator

@ehuss ehuss commented Mar 13, 2020

Hm, I'm wondering if this was stabilized accidentally. This was added in rust-lang/rust#57760 (RFC 2137), see also rust-lang/rust#44930 and rust-lang/wg-grammar#45.

Is there any meaning to the identifier of a variadic parameter? Or is it just ignored? That should probably be documented.

(Or, if this was truely a mistake, maybe it should be reverted/fixed/made unstable?)

@matklad
Copy link
Member Author

@matklad matklad commented Mar 13, 2020

I don't know, I guess cc @Centril / @petrochenkov ?

But apparently people use this in the real world already, this was reported against rust-analyzer.

@Centril
Copy link
Contributor

@Centril Centril commented Mar 13, 2020

The function parameter grammar as implemented in rustc is as follows. I've invented new meta grammar notation here, but it should hopefully be understandable.

Let RN ("require name") be a function Edition -> Bool. Then the (higher order) grammar is:

FnParams<RN> = "(" head: FirstParam<RN> tail: { "," Param<RN> %% "," } ")" ;

FirstParam<RN> = SelfParam | Param<RN> ;
Param<RN> = CVariadicTy | AlwaysNamedParam | MaybeNamedParam<RN> ;

MaybeNamedParam<RN> if RN(edition(current_token)) = Pat ":" ParamTy ; // Named param.
MaybeNamedParam<RN> = ParamTy ; // Unnamed param.

// Ambiguous with ^-- but for precedence.
AlwaysNamedParam = NamedStart? Ident ":" ParamTy ;
NamedStart = NtPat | "&" | "&&" | "mut" ;

ParamTy = CVariadicTy | TyPlusAllowed ;
CVariadicTy = "..." ;

For:

  • function pointers, let RN = \_ -> False,
  • functions in traits, let RN = \edition -> edition > 2015,
  • otherwise, let RN = \_ -> True.

This is translated starting with parse_fn_params in the rustc parser.

Beyond this, AST validation imposes other semantic restrictions.

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

Successfully merging this pull request may close these issues.

None yet

3 participants
You can’t perform that action at this time.