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

tt-macro doesn't work #5846

Closed
jbclements opened this issue Apr 12, 2013 · 13 comments · Fixed by #34908
Closed

tt-macro doesn't work #5846

jbclements opened this issue Apr 12, 2013 · 13 comments · Fixed by #34908
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) P-low Low priority T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@jbclements
Copy link
Contributor

I haven't finished investigating this, so I'm making an issue just so I don't forget it:

macro_rules! foo (
    ($x:tt) => {type t = ($x) int;})

foo!(~)
@jbclements
Copy link
Contributor Author

Actually, I'm really not sure this should work. I'm nominating this for well-defined.

@jbclements
Copy link
Contributor Author

Actually... this definitely shouldn't work in our current system. The basic issue is that a lonely sigil is not a complete "thing". The "tt" macro option is only intended for macros that expand into macro invocations. There are a number of ways around this; at the most basic level, you can insist that the user provide the sigil and the thing it's attached to. This works, but it may be unsatisfying if you want the sigil to be attached to names that are introduced by the macro. In this case, you have a couple of choices.

  • use an unhygienic macro (and tell everyone what name you want to attach to the sigil, ugh)
  • explicitly have three different versions of the macro, one for each sigil (bleah)
  • clean up the second option by nesting one macro definition inside another one
  • make sigils expand into macro invocations.

Anyhow, I would say that as of right now, at least, this is not a bug. I'm going to leave this as nominated mostly because this came up in Vancouver as something that Graydon and I both expected to work.

@huonw
Copy link
Member

huonw commented Jul 23, 2013

Visiting for triage: still doesn't work, nothing more to add.

@graydon
Copy link
Contributor

graydon commented Aug 22, 2013

accepted for well-defined milestone

@huonw
Copy link
Member

huonw commented Jan 31, 2014

You can work around this by using a dummy macro so that you can pass the tt directly to it, e.g. for the example in the issue:

#[feature(macro_rules)];

macro_rules! item { ($i: item) => { $i } }

macro_rules! foo (
    ($x:tt) => { item!(type t = $x int;) }
)

foo!(~)

fn main() {}

@jbclements
Copy link
Contributor Author

reading this workaround makes me feel like our macro system is really broken :(.

@steveklabnik
Copy link
Member

/cc @kmcallister

@kmcallister kmcallister added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) and removed A-syntaxext Area: Syntax extensions labels Feb 23, 2015
@kmcallister
Copy link
Contributor

The modernized example

macro_rules! foo {
    ($x:tt) => (type t = $x<int>;)
}

foo!(Box);

gives me

/tmp/foo.rs:2:26: 2:28 error: expected type, found `an interpolated tt`
/tmp/foo.rs:2     ($x:tt) => (type t = $x<int>;)
                                       ^~

which looks like #22819.

@huonw
Copy link
Member

huonw commented Oct 27, 2015

#16036 notes that another hacky work-around is a nested macro invocation, which avoids needing to define/export dummy macros (although one will want to be careful about giving that internal macro a fairly unique name to avoid trampling on any other macros in scope, unfortunately 😞 ).

macro_rules! foo {
    ($x:tt) => (
        macro_rules! internal {
            () => { type t = $x<i8>; }
        }
        internal!();
    )
}

foo!(Box);

@brson brson added P-low Low priority and removed P-medium Medium priority labels Jul 14, 2016
@steveklabnik
Copy link
Member

Updated example:

macro_rules! foo {
    ($x:tt) => (type t = $x<i32>;)
}

foo!(Box);

error:

error: expected type, found `Box`
 --> <anon>:2:26
2 |>     ($x:tt) => (type t = $x<i32>;)
  |>                          ^^

@brson brson added T-lang Relevant to the language team, which will review and decide on the PR/issue. I-nominated labels Jul 14, 2016
@brson
Copy link
Contributor

brson commented Jul 14, 2016

Triage: This is an ancient P-low bug but per @sanxiyn it actually comes up in the wild a lot - macro writers have to know how to do this workaround. Can this be escalated? Is there a solution somebody could mentor?

@nrc
Copy link
Member

nrc commented Jul 14, 2016

Discussed at lang meeting, we believe this should remain p-low since we don't know a very easy fix. It should be fixed by converting macro_rules to expand to pure tokens then parsing, rather than mixing the two steps (which we hop would be back-compat).

cc @jseyfried

@jseyfried
Copy link
Contributor

Fixed in #34908.

bors added a commit that referenced this issue Jul 28, 2016
macros: Improve `tt` matchers

Fixes #5846, fixes #22819.
r? @nrc
flip1995 added a commit to flip1995/rust that referenced this issue Aug 11, 2020
…flip1995

Handle mapping to Option in `map_flatten` lint

Fixes rust-lang#4496

The existing [`map_flatten`](https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten) lint suggests changing `expr.map(...).flatten()` to `expr.flat_map(...)` when `expr` is `Iterator`. This PR changes suggestion to `filter_map` instead of `flat_map` when mapping to `Option`, because it is more natural

Also here are some questions:
* If expression has type which implements `Iterator` trait (`match_trait_method(cx, expr, &paths::ITERATOR) == true`), how can I get type of iterator elements? Currently I use return type of closure inside `map`, but probably it is not good way
* I would like to change suggestion range to cover only `.map(...).flatten()`, that is from:
```
    let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `vec![5_i8; 6].into_iter().flat_map
```
to
```
    let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
                                             ^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `.flat_map(|x| 0..x)`
```
Is it ok?
* Is `map_flatten` lint intentionally in `pedantic` category, or could it be moved to `complexity`?

changelog: Handle mapping to Option in [`map_flatten`](https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten) lint
flip1995 pushed a commit to flip1995/rust that referenced this issue Aug 11, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#5837 (needless_collect: catch x: Vec<_> = iter.collect(); x.into_iter() ...)
 - rust-lang#5846 (Handle mapping to Option in `map_flatten` lint)
 - rust-lang#5848 (Add derive_ord_xor_partial_ord lint)
 - rust-lang#5852 (Add lint for duplicate methods of trait bounds)
 - rust-lang#5856 (Remove old Symbol reexport)

Failed merges:

r? @ghost

changelog: rollup
calebcartwright pushed a commit to calebcartwright/rust that referenced this issue Oct 23, 2023
* improve the file-lines example

* fix help order
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) P-low Low priority T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants