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

[WIP] Warn when $name:matcher syntax is used on expansion side #47967

Closed
wants to merge 8 commits into from

Conversation

krdln
Copy link
Contributor

@krdln krdln commented Feb 2, 2018

This pull request is in obviously unfinished state (missing tests, etc.), but I wanted to publish it anyway to ask whether you think this kind of warning is a good idea in the first place.

I do often make mistake by unnecessarily adding :tt-like annotations on the expansion side, which may result in weird errors in unrelated places. That's why I wanted to take a stab at creating warning for such a case. Here's an example how the warning looks like.

tt-warning

Unresolved questions

  1. Does this warning is worth creating at all?
  2. Should we warn on any $foo:bar or only when bar is an actual tt, expr etc.?
  3. Is the .clone() in the implementation lightweight enough?
  4. Should the warning be registered, so one can allow it?
  5. The exact warning/note message.

cc @estebank

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @nikomatsakis (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@shepmaster shepmaster added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Feb 3, 2018
@nikomatsakis
Copy link
Contributor

I think I've made this mistake from time to time.

@estebank
Copy link
Contributor

estebank commented Feb 5, 2018

It's even specifically called out in the Programming Rust book. I'd be on favor of this lint, specially given the current error.

@estebank
Copy link
Contributor

estebank commented Feb 6, 2018

Does this warning is worth creating at all?

I think so.

Should we warn on any $foo:bar or only when bar is an actual tt, expr etc.?

I think we should be supplying the warning only when not only it is a valid macro argument matching type, but also the same matching type for the argument.

Is the .clone() in the implementation lightweight enough?

Given that you're cloning an Iterator it should be cheap enough to do liberally.

Should the warning be registered, so one can allow it?

Probably, although I am happy with gating the warning on adding a space.

The exact warning/note message.

Lets think about the wording. I think there's some improvement possible.

Also, add a test for this.

@durka
Copy link
Contributor

durka commented Feb 6, 2018

Should the warning be registered, so one can allow it?

All warnings should, IMO. One situation where you might have to allow this warning, depending on how it's implemented, is for a macro-writing macro, e.g.

macro_rules! foo {
    ($dol:tt $a:ident) => {
        macro_rules! bar {
            ($dol$a:ident) => { $dol$a }
        }
    }
}

The exact warning/note message.

I think your current text is rather cryptic. As an aside, terminology for the parts of a macro is wildly inconsistent. The Reference seems to use "matcher" and "transcriber" to mean the entire left and right sides of a macro, respectively. It uses "designator" for the :tt part (what you called a "matcher"). Rust By Example also uses "designator". Meanwhile, the Book calls it a "fragment specifier". TLBoRM uses "pattern", "expansion", and "kind of capture".

How about this:

warning: macro expansion includes fragment specifier
 --> confusing-macro.rs:2:22
  |
2 |     ($tt:tt) => { $tt:tt }
  |                      ^^^
  |
  = help: did you mean `$tt`?
  = help: to suppress this warning, add a space: `$tt: tt`

This is still cryptic IMO. But it'd be better if we picked one of the terms "designator"/"fragment specifier" and went with that everywhere.

@nikomatsakis
Copy link
Contributor

r? @estebank

@nikomatsakis
Copy link
Contributor

(Just lightening my review load, @estebank if that doesn't work for you, feel free to reassign back.)

@estebank
Copy link
Contributor

estebank commented Feb 6, 2018

Nitpick: use span_suggestion instead of notes:

warning: macro expansion includes fragment specifier
 --> confusing-macro.rs:2:22
  |
2 |     ($tt:tt) => { $tt:tt }
  |                      ^^^
help: if you meant to use the macro argument, do not include the fragment specifier:
  |
2 |     ($tt:tt) => { $tt }
  |                   ^^^
help: to suppress this warning, add a space after the type argument:
  |
2 |     ($tt:tt) => { $tt: tt }
  |                   ^^^^^^^

@pietroalbini
Copy link
Member

Hi @krdln, there are some failing tests on Travis and a comment from the reviewer in #47967 (comment). Could you address those so the PR can be merged? Thanks!

@krdln
Copy link
Contributor Author

krdln commented Feb 12, 2018

@pietroalbini I'd be more than happy to finish this PR – I'll do it as soon as I have some free time, hopefully it'll be sometime this week.

@pietroalbini
Copy link
Member

Weekly ping for you @krdln!

@krdln
Copy link
Contributor Author

krdln commented Feb 25, 2018

@durka

Should the warning be registered, so one can allow it?

All warnings should, IMO.

I was trying to convert this warning to a lint, but I'm a little stuck here. The perfect method I could use would be struct_span_lint, but it's not available on Handler. What would be appropriate way to emit this warning as a lint? Should I approach this similarly to MISSING_FRAGMENT_SPECIFIER, which is somehow buffered and emitted in librustc_driver/driver.rs? (I feel like driver would be a weird place for such a warning)

@krdln
Copy link
Contributor Author

krdln commented Feb 25, 2018

@estebank I've reworded the error message according to your suggestion (also, thanks for pointing me to span_suggestion!) and added a test. Not sure what the appropriate place for a test would be, so for now, i've put it directly in ui.

I think we should be supplying the warning only when not only it is a valid macro argument matching type, but also the same matching type for the argument.

I've decided to just check whether it is a valid fragment specifier. My rationale for not checking whether it's the same type as argument (apart for implementation complexity) is that it wouldn't let us detect the mistake when the user changed the kind only on one side, or they tried to use the : syntax to eg. cast the expr back to tt.

I've tried to make this warning a proper lint, but I'm not sure how to approach it (see the comment above), so for now I've left it as it was.

@kennytm kennytm added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 25, 2018
@shepmaster
Copy link
Member

Ping from triage, @estebank !

@estebank
Copy link
Contributor

estebank commented Mar 8, 2018

I've decided to just check whether it is a valid fragment specifier.

Could you add a test with @durka's macro usage to see the way this would work in that case?

@durka I'm ok with the solution presented in this PR. Do you have an objection with the current safeguards (checking for valid specifiers, allowing using a space after the colon to avoid the warning)?

@durka
Copy link
Contributor

durka commented Mar 8, 2018

I'd prefer #[allow(fragment_specifier_in_expansion)], but adding a space is fine -- just seems slightly hacky.

@pietroalbini pietroalbini added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 12, 2018
@krdln
Copy link
Contributor Author

krdln commented Mar 13, 2018

@durka – as I said above I'd be happy to implement #[allow(fragment_specifier_in_expansion)], but got stuck, and I'll need a little guidance (or we can leave the hacky solution)

@estebank Regarding @durka's macro, I'm not sure what you mean – do you mean just to just copy this macro and test that it indeed incorrectly warns? Or do you mean to test the "silencing by space"?

@estebank
Copy link
Contributor

@krdln I only just now noticed the reason that sample is problematic. I don't think we should merge before we have a way to enable this selectively or to have this not trigger in the nested macro case. The simplest will be to add #[allow(fragment_specifier_in_expansion)]. I'll try to make time to help you there this weekend.

@shepmaster
Copy link
Member

Ping from triage, @krdln ! It looks like you got some feedback on your questions; will you be able to apply that feedback soon?

@bors
Copy link
Contributor

bors commented Mar 23, 2018

☔ The latest upstream changes (presumably #49308) made this pull request unmergeable. Please resolve the merge conflicts.

@shepmaster
Copy link
Member

Since we haven't heard from you in a few weeks, I'm going to go ahead and close this to keep things tidy. If you have time to resume work on this, please feel free to do so and reopen this pull request! Thank you for your hard work!

@shepmaster shepmaster closed this Mar 30, 2018
@shepmaster shepmaster added S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive Status: Inactive and waiting on the author. This is often applied to closed PRs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants