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

Precedence of type macros is confusing #52307

Closed
jendrikw opened this issue Jul 12, 2018 · 7 comments
Closed

Precedence of type macros is confusing #52307

jendrikw opened this issue Jul 12, 2018 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST

Comments

@jendrikw
Copy link
Contributor

When calling an associated function on a struct, type macros behave very strange and produce weird error messages.

Example on playground


struct S<T>(PhantomData<T>);

impl<T> S<T> {
    fn associated_function() {}
}

macro_rules! TypeMacro {
    ($x:ty) => { S<$x> };
}

fn main() {
    // compare the error mesages:
    
    // error: expected one of `.`, `;`, `?`, or an operator, found `::`
    let _ = TypeMacro!(u8)::associated_function();
    
    // error: chained comparison operators require parentheses
    let _ = S<u8>::associated_function();
    
    // conclusion:
    // TypeMacro!(u8) is not the same S<u8>
    
    
    // this works
    let _ = <S<u8>>::associated_function();
    let _ = S::<u8>::associated_function();
    let _ = <TypeMacro!(u8)>::associated_function();
}

Naturally, one would expect that TypeMacro!(u8) is the same as S<u8> because it is defined that way.

The result is the same on all rust versions currently in playground

  • 1.27.1
  • 1.28.0-beta.9 2018-07-09 718e759
  • 1.29.0-nightly 2018-07-10 e5f6498
@petrochenkov
Copy link
Contributor

The syntax is PATH::assoc_item, not TYPE::assoc_item, for non-path types angle brackets have to be used - <[T; N]>::assoc_item.

[T; N]::assoc_item/(A, B)::asoc_item/etc even have a special error recovery and help message for this case:

error: missing angle brackets in associated item path
 --> src/main.rs:4:13
  |
4 |     let x = [a; b]::clone;
  |             ^^^^^^^^^^^^^ help: try: `<[a; b]>::clone`

Supposedly mac!()::assoc_item should have this help as well, but it doesn't for some reason.

@petrochenkov petrochenkov added A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST labels Jul 12, 2018
@jendrikw
Copy link
Contributor Author

I've got a few questions about this.
What is a path? I don't think this is documented in the book.
Is S::<u8> the same as <S<u8>>? If so, why are there two ways to write it?

@petrochenkov
Copy link
Contributor

@jendrikw

What is a path?

Something like this a::<b>::c<d>::e<f>, including single-segment cases like a<b> or a.
At least the syntax appendix in the book show it - https://doc.rust-lang.org/book/second-edition/appendix-02-operators.html#appendix-b-operators-and-symbols.

Is S::<u8> the same as <S<u8>>?

No, the <TYPE>::assoc_item is a way to write associated items for "complex" types that are not paths like *const T or [T; 10].
It's not necessary for a type like S<u8> because it's a path syntactically.

@jendrikw
Copy link
Contributor Author

Well, I didn't know the syntax for a path because noone told me I needed a path. Even now, I don't know what it's needed for.

But do you agree that the error messages should me the same?

@petrochenkov
Copy link
Contributor

Yes, the error message should ideally look like one for [T; N], e.g.

error: missing angle brackets in associated item path
 --> src/main.rs:4:13
  |
4 |     let x = mac!()::clone;
  |             ^^^^^^^^^^^^^ help: try: `<mac!()>::clone`

@durka
Copy link
Contributor

durka commented Aug 29, 2018

The syntax is PATH::assoc_item, not TYPE::assoc_item, for non-path types angle brackets have to be used - <[T; N]>::assoc_item.

Quick note: path doesn't work either:

error: expected one of `!`, `.`, `;`, `?`, `{`, `}`, or an operator, found `::`
  --> expr.rs:18:49
   |
18 |     match {macro_rules! call { ($t:path) => { $t::foo() } } call!(Foo);} {
   |                                                 ^^          ----------- in this macro invocation
   |                                                 |
   |                                                 expected one of 7 possible tokens here

@petrochenkov
Copy link
Contributor

Fixed in #59058

Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this issue Mar 22, 2019
 syntax: Better recovery for `$ty::AssocItem` and `ty!()::AssocItem`

This PR improves on rust-lang#46788 covering a few missing cases.

Fixes rust-lang#52307
Fixes rust-lang#53776
r? @estebank
bors added a commit that referenced this issue Mar 23, 2019
 syntax: Better recovery for `$ty::AssocItem` and `ty!()::AssocItem`

This PR improves on #46788 covering a few missing cases.

Fixes #52307
Fixes #53776
r? @estebank
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-parser Area: The parsing of Rust source code to an AST
Projects
None yet
Development

No branches or pull requests

3 participants