►
Description
Alex will try to convince us that procedural macros are the best thing since sliced bread. With "macros 1.2" now on stable Rust there's no better time to discover the world of procedural macros and what they can do for us.
We've already seen the power of derive macros shoot Serde to one of the most popular crates in Rust. With attribute macros we can go even further with lightweight annotations powering frameworks. And finally with procedural macros the sky is the limit!
Let's learn about tips, tricks, and usage of the procedural macro world!
Follow us on Twitter: https://twitter.com/rustlatamconf
A
All
right
good
afternoon,
everyone,
my
name,
is
Alex
and
today
I
have
one
goal,
which
is
to
convince
you
that
procedure
macros
are
better
than
sliced
bread.
Now
you
might
not
think
that's
actually
that
much
of
a
kind
of
bar
to
live
up
to,
but
there's
a
very
common
phrase
saying
that
this
is
the
best
thing
since
sliced
bread,
and
so
this
it's
actually
it's
it's
you
so
often
a
lot
of
things
are
compared
to
sliced
bread.
A
I
figured
I'd
continue,
continue
the
tradition
so
to
start
off,
I'd
like
to
tell
you
what
the
rise
of
procedure
macros
and
kind
of
a
little
bit
of
history,
of
how
we
came
from
the
dark
ages
of
rust,
1.0.
It's
a
procedure
macros
that
we
have
today.
The
first
thing
you'll
notice,
is
that
back
around
at
January
2014,
this
is
about
a
year
before
1.0
was
released.
We
have
this
poor
request,
number,
the
infamous
one
one,
one,
five
one
land
for
loadable,
syntax
extensions.
A
The
next
thing
was
these
two
RFC's
happening
in
quick
succession,
which
is
starting
to
formally
design
the
macro
system.
This
happened
about
a
year
after
1.0,
and
we
had
these
two
one
for
modularizing
the
macro
system
and
the
one
for
actually
specifying
what
a
procedure
macro
is,
and
so
I'll
be
kind
of
going
into
more
details
about
what's
going
on
here,
but
you
can
see
how
years
ago
is
when
we
actually
started
the
stabilization
process
and
specification
process
for
the
macros
that
we
actually
have
today.
A
Now
they
have
been
tweaked
since
then,
since
they
were
designed
back
then,
but
they're,
mostly
the
same
in
spirit.
Next
up,
we
have
in
mid-2016
the
first
stabilization
of
macros
with
derive
macros.
So
many
of
you
might
know
this
is
when
Surrey
first
started
to
compile
on
stable
rest,
and
this
was
a
massive
boon
for
the
ecosystem
as
I.
A
Like
macros,
and
so
these
ended
up
actually
being
stabilized
in
October
of
2018,
and
so
this
is
kind
of
where
we
are
today
and
I'm
gonna
be
talking
a
little
bit
more
about
kind
of
what
the
current
state
of
macros
are
and
going
into
all
the
attributes
to
rise
and
functions.
So
it's
only
fair
that
we
talk
about
the
rise
of
sliced
bread
as
it's
the
comparison
as
well,
and
so
most
of
this
is
copied
from
Wikipedia.
But
there's
two
notable
points.
A
One
is
the
inventor
of
sliced
bread
is
from
Iowa
I
also
came
from
Iowa,
so
I'm
very
proud
of
that.
I
did
not
know
that
before
I
anyway.
The
next
thing
is
that
in
World
War
2
the
u.s.
banned
sliced
bread
because
it
was
so
difficult
to
produce,
but
then
they
had
to
undo
that
because
it
was
too
popular
and
everyone
revolted
alright
back
to
the
actual
technical
content.
I'm
gonna
first
tell
you
a
little
bit
about
what
a
procedure
macro
is
now
if
you
are
at
David's
workshop
yesterday.
A
This
is
probably
going
to
be
a
bit
of
a
review,
but
it'll
kind
of
get
us
all
on
the
same
page
and
then
I
want
to
talk
a
little
bit
more
about
how
we
actually
write
these
procedure
macros,
so
not
just
what
they
are.
But
how
do
you
actually
functionally
use
them
in
the
ecosystem
and
then,
finally,
some
fun
stuff
coming
down
the
pike
and
just
some
cool
examples
of
macros?
So
all
right
macros
come
in
three
primary
forms
in
the
compiler.
A
The
first
of
these
is
function
like
they
are
denoted
by
this
bang
and
then
there's
delimited
sides,
and
then
one
of
the
most
common
ones
is
print
'ln.
Now
print
'ln
isn't
literally
procedure
macro,
but
it's
the
same
thing
in
spirit.
The
next
is
the
very
familiar
derived
macros,
and
so
this
is
everything
to
do
with
Sergey
and
everything
to
do
with
every
other
form
of
derive
on
the
kraits
Iuka
system
and
it's
a
sort
of
annotations
for
structs
and
enums
to
extend
with
various
functionality,
and
the
last
is
attribute
macros.
A
Now
we've
heard
some
talk
of
isin
bindings
and
I'm.
Not
gonna,
go
too
much
into
the
details
about
that,
but
this
is
effectively
a
macro
that
is
defined
on
crates,
IO
and
as
a
library,
if
I'd
a
definition
of
how
it
works
so
to
actually
start
out
by
writing
in
a
proc
macro,
you
have
to
tell
both
cargo
and
the
compiler
what
you're
doing
because
the
coop,
the
macro
has
to
be
compiled
a
little
bit
differently,
especially
when
you're
cross
compiling
into
all
that
crazy
stuff.
And
so
all
you
have
to
do
is
open
up.
A
The
Lib
section
of
your
carbo
tamil
right
in
proc
macro
equals
true
and
you're
good
to
go
now,
you're
ready
to
start
writing
some
procedure
macros
if
you're
writing
a
print,
Lin
macro
or
a
function
like
macro,
we're
going
to
use
this
pound.
Proc
macro
attribute
and
then
take
this
weird
token
stream
thing
and
return.
A
This
weird
token
stream
things
and
the
general
goal
here
is
that
we
have
this
invocation
like
print
land
of
a
wheat
bread,
and
we
want
to
transform
that
and
completely
replace
it
with
some
other
ugly
expanded
thing
that
the
contents
don't
matter
too
much,
but
it's
something
the
users
not
going
to
write
and
have
to
worry
too
much
about,
and
so
to
kind
of
connect.
All
the
dots
here
we
can
see
the
function
name
of
the
procedure.
Macro
is
actually
connected
to
the
macro
itself.
A
The
next
of
these
is
derive
macros,
and
so
this
is
an
example
of
how
sir
you
might
actually
be
defining
their
derive
macro
inside
there.
We
can
see
it's
a
little
bit
different
where
it's
not
just
proc
macro,
but
it's
proc
macro
derive
and
then
the
name
of
looks
in
there,
and
the
input
and
output
is
also
slightly
different
here
as
well.
So
a
derive
macro
is
only
only
ever
used
to
annotate,
either
a
struct
or
an
enum,
and
so
that'll
be
the
input
here
and
the
output
is
something
that
we
append.
A
So
we
can
kind
of
see
the
connections
here
where
the
name
is
specified
on
the
attribute.
The
name
of
the
function
action
doesn't
matter
too
much.
The
input
is
just
the
struct,
not
the
attribute
with
it,
and
then
the
output
does
not
include
the
struct.
It's
just
this
one
in
palak,
and
so
the
main
thing
here
is
that,
with
a
derived
macro,
you
cannot
modify
the
structure
of
the
enum.
You
cannot
change
what's
happening,
you
can
only
append
to
it
typically
by
adding
trade,
imple
or
other
items.
A
A
It's
got
a
bunch
of
crazy
stuff,
plus
the
original
item
itself
right
there
and
we
start
looking
at
the
connections.
We
can
see
kind
of
like
with
function
like
macros.
The
name
of
the
function
is
connected
to
the
name
of
the
attribute
and
then
the
args.
So
this
first
argument
is:
what's
provided
in
parentheses,
to
the
argument
to
the
attribute
itself,
and
so
here
ours
is
just
going
to
be
start
and
nothing
else,
and
if
you
don't,
you
don't
have
to
provide
the
parentheses
it'll
just
be
an
empty
token
stream.
A
If
we
want
the
bake
function
to
persist,
we
got
to
make
sure
to
put
it
in
the
output
as
well,
so
we
can
not
only
have
our
generated
goop,
but
we
also
have
the
bake
function,
serialize
straight
into
the
output,
so
that's
kind
of
the
interface
that
we
have
with
these
three
kinds
of
macros,
and
the
next
thing
you
might
be
wondering
is:
what's
this
token
stream
thing?
What
is
the
I?
A
Is
the
input,
this
weird
token
thing,
and
so
a
token
stream
is
sort
of
the
lexical
foundation
for
all
rest
syntax,
and
this
is
where
it
includes
atomic
tokens
inside
of
it's
not
a
string,
it's
not
some
other
serialized
form,
but
it's
kind
of
a
parse
representation
in
memory
of
each
token
that
you
passed
in,
and
this
is
all
defined
in
the
compiler,
it's
completely
unstable
internally.
You
can
use
it
stable
externally,
but
it's
all
kind
of
a
bunch
of
weird
details,
but
you
can
kind
of
sufficiently
think
about
this
as
a
cheaply
cloneable.
A
Hence
the
RC
here
list,
and
so
it's
not
literally
that
eternally,
but
you
can
very
cheap
to
clone
it.
You
could
iterate
over
it
and
see
what's
inside
now.
The
really
interesting
part
here
is
what's
actually
inside
of
it,
which
is
this
token
tree,
and
so
the
tree
aspect
comes
from
this
first
area
variant
called
group,
but
I'll
go
ahead.
Go
over
that
in
a
second
and
suffice
to
say
that
these
four
variants,
these
four
pieces
of
syntax,
are
enough
to
capture
all
of
Russ,
syntax
and
and
a
bunch
more
syntax
as
well.
A
So
I
want
to
break
down
this
derive
example
and
show
you
some
what
each
of
these
syntax
of
variants
corresponds
to
in
this
example,
and
so
we
have
this
derived
macro,
which
is
30
and
then
a
couple
of
30
attributes
and
some
fields
inside
there.
So
first
up
we
have
a
group.
A
group
represents
a
delimited
set
of
tokens
by
a
balanced
delimiter,
so
these
are
parentheses
or
brackets
or
curly
braces,
and
so
here
we
have
three.
A
We
have
just
the
bracket
on
Surti,
the
parentheses
on
30
and
then
the
curly
braces
on
the
struct
itself,
and
so
that's
kind
of
the
nesting
form
here,
and
this
is
why
it's
a
token
tree,
as
opposed
to
just
a
token
or
a
token
list,
is
that
this
is
a
nesting
where
the
group
internally
has
another
token
stream
of
what's
inside
there.
The
next
are
identifiers,
and
so
these
are
key
words.
These
are
variable
names.
These
are
struck
names.
These
are
type
names.
A
This
is
just
kind
of
any
valid
rust'
identifier,
which
is
various
rules
for
that.
But
so
here
we
have
30,
rename
all
structs
the
fields,
the
types
all
those
are
identifiers
which
are
kind
of
they
have
no
internal
spaces.
They're.
Just
one
valid
rust'
identifier,
nice
to
me,
have
punctuation,
which
is
kind
of
all
the
little
bits
of
syntax
here
and
there,
like
commas
and
pounds
and
colons
and
equals
and
critically
a
punctuate
piece
of
punctuation
is
one
character
large,
and
so
it's
just
one
utf-8
character
or
one
Unicode
character.
A
And
this,
although
internally,
if
you
have
like
a
shift
left
which
has
two
less
than
signs
that'll,
be
two
different
pieces
of
punctuation
and
I'm,
not
gonna,
go
too
much
in
details.
We
can
all
figure
that
out
later
and
the
final
one
here
is
literals,
and
so
these
are
numbers.
These
are
strings.
In
this
case
we
could
have
byte
strings.
We
could
have
arrays
well
anyway,
so
those
are
kind
of
the
bare
values
which
you'll
kind
of
which
are
compiled
in
a
static
memory
and
kind
of
say,
different
class
of
syntax.
A
So
these
four
pieces
are
what
encompasses
everything
that
you
will
receive
in
your
procedure.
Macro
you'll
be
getting
a
giant
list
of
all
that
and
expected
to
produce
a
giant
list
of
all
that,
and
so
to
kind
of
talk.
Another
feature
about
the
macula
system
that
we've
been
developing
is
the
fact
that
we've
been
modularizing
all
of
these
as
well
so
before
we
actually
had
stable
macros
in
2018.
A
We
had
to
use
these
funky
macro
use
attributes
we
had
to
use
other
funky
attributes,
they
had
kind
of
weird
scoping
rules,
and
so,
with
the
recent
push
for
a
stabilization
of
macros,
we've
added
new
support
in
the
entire
module
system.
The
correctly
scope
these
work
through
the
same
module
system
that
you're
kind
of
used
to,
and
so
we
can
bring
in
print
Lin,
serialized
wise
and
bind
gen.
A
We
can,
if
you
re
export,
and
so
typically
as
I
was
saying,
you
have
a
dedicated
crate
for
defining
a
procedure
macro,
but
you
might
re-export
it
from
a
different
crane.
So
the
wise
and
bind
gen
create
will
react
sport
this
from
the
wise
and
bind
in
macro
create
kind
of
internally,
and
one
of
the
nice
aspects
of
this
is
the
macros
of
their
own
namespace.
And
so
this
means
that
you
can
bring
in
multiple
values
or
types
went
into
scope
at
the
same
time.
A
So
when
you
say
use
Sur
to
serialize,
that's
actually
bringing
into
scope
both
the
tree
and
the
macro,
so
it
kind
of
cuts
down
on
the
number
of
imports
that
you
have
to
write.
There's
also
kind
of
a
nice
thing
for
library
authors
where,
if
you
have
everything
line
up
very
nicely
trait
wise
and
derive
wise,
then
you
can
have
one
import
to
bring
everything
into
scope
all
at
once.
A
Sorry
that
was
a
little
bit
about
a
whirlwind
tour
of
what
procedure
macros
are,
and
so,
let's
dive
into
some
internal
details
of
how
you
would
actually
write
these
macros
and
generate
these
giant
lists
and
parse
these
giant
lists,
and
so
our
problem
here
is:
we
have
this
print
Lin
macro.
We
want
to
write.
We
have
this
input,
which
is
some
list
of
tokens,
just
some
list
of
syntax
that
we
have
to
figure
out
and
we
have
to
produce
this
stuff,
I,
Oh,
printing,
whatnot,
but
internally,
it's
kind
of
hard
to
work
with
all
that.
A
So
what
we
morally
want
to
do
here
is
have
kind
of
a
parsed
representation
of
what
we
might
be
receiving,
and
so,
if
we
say
printing
some
number
of
lows,
then
we
want
kind
of
the
format
string
to
be
parsed
directly
into
memory,
and
then
we
also
want
some
expressions.
Now
we
don't
really
know
where
this
expression
type
is
coming
from,
but
we
want
kind
of
arbitrary
rest
expressions
because
it
won't
rust
to
be
very
familiar
at
that
point
and
then
so
after
we
actually
parse
it.
A
We
might
do
some
validation
to
make
sure
that
the
number
of
curly
braces
placeholders
matches
the
number
of
arguments
a
path
soon
and
then
finally,
we
want
to
actually
expand
it
to
generate
that
stood,
I,
hope,
ritalin
business
that
we
were
seeing.
So
it
turns
out
the
crates.
I
of
ecosystem
has
a
number
of
very
handy
crates
for
doing
exactly
this,
the
first
of
which
is
a
crate
called
sin,
and
so
what
sin
does?
A
A
Utilities
will
see
those
in
a
second
for
implementing
this
parse
function,
so
we
can
very
easily
write
our
parsers
and
we
don't
have
to
parse
all
of
us
syntax
and
every
single
crate
and
have
a
little
buggy
here
in
there
and
then
to
actually
expand
this
crate
to
actually
create
some
token
streams
and
make
more.
We
can
use
the
quilt
crate,
which
we'll
be
looking
at
in
some
detail
after
this
as
well.
A
So
as
I
was
saying,
sin
will
be
used
to
parse
all
of
the
rest
code
that
we
are
that
we
receive
and
the
way
that
it
mostly
works
is
kind
of
a
lot
of
times
when
you
write
a
macro
you're,
extending
rust,
syntax
and
very
small
or
very
tiny
ways.
So
in
a
print
lean
format,
we
kind
of
have
custom
for
syntax
in
the
string,
but
everything
after
that
is
just
a
bunch
of
function.
Arguments
this
is
commas
and
expressions
and
all
existing
rust,
syntax
and
so
the
well.
A
The
reason
sin
is
so
powerful
is
it's
kind
of
giving
you
all
these
parsers,
which
you
can
already
leverage.
But
then
you
can
write
the
top-level
logic
for
right
having
a
little
pieces
of
custom
syntax
here
and
there
and
then
use
the
rest
of
cinder
to
kind
of
do
the
real
work
of
actually
parsing
an
expression
or
kind
of
dealing
with
precedents,
and
all
that
crazy
stuff.
A
When
you
type
carve
a
build,
you
have
to
actually
build
a
rust
parser
on
the
spot
and
so
there's
a
lot
of
feature
gates
to
aggressively
remove
code
that
we
don't
have
to
compile,
and
so
it
compiles
very
very
quickly
for
most
average
cases
and
to
give
you
a
bit
of
an
idea.
If
you're
writing
a
derived
macro,
you
can
you
don't
actually
have
to
define
anything.
We
don't
need
this,
my
invocation
or
any
other
serialized
instance.
We
can
just
use
the
the
utilities
provided
by
sin.
A
So
sin
gives
us
this
derive
input
type
that
gives
us
a
convenient
macro
for
parsing
directly
into
it
and
we're
off
to
the
races.
We
can
immediately
take
a
look
at
that
see
if
it's
a
struct
or
an
enum,
how
many
fields
it
has,
what
kind
of
variants
all
those
various
aspects
of
the
input
and
just
keep
on
going,
and
it
goes
a
little
bit
beyond
this,
where
it's
a
little
bit
more
advanced,
and
you
might
have
seen
this
in
the
workshop
yesterday.
A
We
now
need
to
generate
a
bunch
of
token
streams,
and
so
that's,
where
quotes
gonna
come
in
where,
if
you
take
a
look
at
the
bare
fundamentals,
it's
hard
to
parse
they're
hard
to
take
a
look
at
this
token
stream
and
interpret
it.
So
we
parse
it.
But
similarly,
it's
very
difficult
to
create
token
streams
and
all
you
can
do
is
create
them
from
a
list
or
kind
of
create
an
empty
one
or
kind
of
add
new
tokens
to
an
existing
one.
A
But
I'll
talk
a
little
bit
more
about
it
and
the
idea
is,
you
can
have
these
interpolations,
where
you
can
splice
in
pieces
of
syntax
that
don't
always
make
sense
in
isolation,
but
when
you
have
it
look
at
it,
when
you
take
a
look
at
it
as
a
whole,
it
kind
of
creates
a
valid
Russ
program
and
to
give
you
a
bit
of
an
idea,
this
is
producing
the
same
syntax.
So
let's
slices
equals
42
and
so
at
the
top.
Here
is
what
you
would
be
doing
with
the
raw
token
stream
and
token
tree
api's.
A
It's
basically
terrible.
It's
it's
horribly
an
ergonomic
to
create
each
identifier
to
create
each
piece
of
punctuation.
It's
very
difficult
to
read
this,
to
modify
it
to
understand.
What's
going
on,
whereas
below
hand,
it's
actually
pretty
obvious,
we're
creating.
Let's
slices
equal
42,
you
also
get
some
nice
syntax,
highlighting
in
here
kind
of
cuz.
A
It
looks
a
little
bit
like
brush
syntax,
but
these
are
functionally
the
same
where
they're
not
actually
executing
this
code,
they're
producing
a
token
stream
that
represents
that
code,
which
will
then
be
compiled
by
the
compiler
later
on,
and
this
interpolation
aspects
comes
in
when
you
have
local
variables,
such
as
the
name
of
some
structure
generating
or
the
fields
that
it
contains
internally,
and
then
you
can
just
kind
of
do
this
splicing,
where
you
can
have
little
pound
names
or
you
can
do
it
eration
with
these.
It's
sort
of
like
a
macro
rules,
style
syntax.
A
But
the
idea
here
is
it's
all
very
valid
rests
in
text
and
you
don't
have
to
worry
so
much
about
what's
going
on,
but
it's
very
easy
to
read,
see
what's
being
generated
as
opposed
to
manually
generating
each
of
these
kinds
of
token
streams,
and
so
quote,
ends
up
being
a
very,
very
powerful,
create
and
for
writing
very
concise
code.
Generators
are
kind
of
all
these
crazy
different
kinds
of
expanders
and
sin
itself
comes
with
all
of
these.
So
if
you're,
given
an
expression,
you
can
both
parse
it
and
then
create
a
token
stream.
A
As
well,
it's
all
provided
for
you.
There
sorry,
the
last
thing
to
consider
when
you're
writing
a
macro
is
the
span
information
which
I've
been
saying
about,
and
so,
as
Esteban
was
saying
earlier,
a
span
is
all
about.
Where
does
this
piece
of
code
come
from,
and
so
that's
all
primarily
used
in
Diagnostics,
but
it's
also
used
of
things
like
debug
information,
for
if
you
set
breakpoints
on
line
numbers,
but
the
idea
here
is
that
every
token
tree,
so
the
groups,
the
literals,
the
punctuation
you
saw
earlier-
are
all
annotated
with
the
span.
A
So
just
this
is
from
byte
4
to
byte
size.
This
is
on
line
6
line
7
that
kind
of
stuff
and
if
you
actually
erase
all
span
information.
So
if
you
take
this
input
and
this
bake
at
macro-
and
you
just
stringify
everything
and
parse
it
back
out,
you're
gonna
get
a
horrible
error
message
here
that
says:
oh
it
points
to
bake
at
pound,
375,
it's.
It
doesn't
actually
point
to
split
out
1/2
and
it's
very
difficult
to
know
in
your
code
where
that
is
actually
located.
A
Whereas,
if
you
actually
correctly
preserve
the
span
information,
then
you
can
get
the
normal
compiler
errors
of
saying.
Oh
look.
It
actually
is
happening
at
this
line
at
this
method
call
or
not
at
this
exact
location,
and
so
this
is
something
that's
very,
very
important
to
remember
when
you're
writing
procedure.
A
You
shouldn't
have
done
that.
You
forgot
to
use
this
all
that
kind
of
good
stuff.
Sorry,
the
last
thing
I
want
to
talk
about
is
a
little
bit
about
the
future
of
macros.
You
know,
look
have
some
features.
We
have
coming
down
the
pike
as
well
as
social,
some
examples
of
some
cool
macros
a
little
bit
later,
and
it
would
be
remiss
of
me
to
not
talk
about
the
word
hygiene.
A
A
This
might
have
a
compiler
unless
you
have
that
in
scope
as
a
macro,
Arthur
will
fix
that
we'll
say.
Oh,
this
comes
from
my
Cretan,
so
we'll
say:
oh
it's
located
here
at
this
path
and
my
create
and
therefore
this
will
always
compile,
because
you
don't
have
to
have
it
in
scope.
You
just
have
to
make
sure
to
link
to
my
crate,
but
you're,
probably
pulling
in
my
crate
there,
the
macro
through
the
crate
anyway,
but
even
this
doesn't
work.
A
Refer
to
this
treat
no
matter
what
you're
linking
to
no
matter
what
you
called
things,
no
matter
what
you
say
anything
about,
and
so
that
that
problem
is
very,
very
difficult
and
one
that
we
have
not
tackled
yet,
and
so
all
the
procedure
macros
are
not
hygienic
where
they're,
just
taking
your
tokens
and
copy
pasting
them
and
they're
effectively.
Best-Effort,
where
you
kind
of
just
have
to
write
this
and
hope
for
the
best
and
make
sure
that
idiomatically
your
crates
not
renamed
or
idiomatically,
no
one
writes
other
crazy
stuff
or
tries
to
react.
A
That's
coming
down
the
pike,
but
not
stabilized,
yet
I
think
it's
implemented
on
nightly
right
now
and
you
can
play
around
with
it,
but
it's
still
a
little
bit
of
time
before
stabilization
now.
The
last
thing
that
I
would
like
to
see
is
kind
of
a
better
experience
for
debugging
macros,
and
so
when
you're
working
with
macros,
you
tend
to
be
producing
pieces
of
russ
syntax
and
it's
you
have
to
produce
valid
russ
syntax
because
it's
gonna
be
turned
around
and
parsed
by
the
compiler.
A
But
if
you
produce
invalid
russ
syntax,
you
get
a
crazy
error
message
like
this.
That
doesn't
make
any
sense,
and
so
this
has
to
do
again
with
the
span
information,
where
the
spans
all
point
to
this
original
macro
and
kind
of
this
way.
It's
a
lot
of
internal
details
here,
but
I
would
love
to
see
kind
of
a
better
system,
for
maybe
we
can
pretty
print
in
the
compiler.
We
can
have
a
better
experience
where
you
don't
have
to
add
random
print
lines
in
your
macro
to
see.
A
A
Seeing
the
possibilities
of
procedure,
macros
I've
been
talking
a
lot
about
what
they
are
and
kind
of,
tell
what
they
can
do
at
a
technical
level,
but
I
love
seeing
examples
of
how
people
are
doing
completely
crazy
things
with
macros
that
I
would
never
even
considered
so
David
showed
me
this
one,
which
is
what,
if
you
had
a
macro
to
say
that
your
enum
was
always
sorted.
So
if
I
put
R
I
before
focaccia
have
a
get
a
compile
time
error
saying:
oh
you
put
this
in
the
wrong
place.
A
This
is
just
arbitrary
token
streams
and
so
class
isn't
a
thing
in
rust,
but
you
can
make
it
a
thing
in
the
back
row.
If
you
want,
and
then
one
other
important
thing
to
point
out
here
is
that
this
is
again
one
of
those
instances
where
there's
so
much
code
here
in
the
middle,
you
could
have
any
sort
of
compiler
errors
with
that,
but
you
could
have
type
check
errors.
You
could
have
weird
integer
errors
or
anything
like
that.
So
you
want
to
make
sure
that
that
span
information
is
all
preserved
here.
A
So
if
each
slice
has
a
random
bug
inside
of
it
not
associated
with
the
macro,
you
still
have
so
those
high
quality
error
messages
coming
out
of
it
and
then
the
last
thing
I
thought,
which
was
really
really
cool,
is
David's
actually
also
created.
A
macro
called
no
panic
where
you
put
it
on
a
function,
and
if
this
compiles
the
function
doesn't
panics.
A
That's
kind
of
I
I've
heard
that
a
lot
with
kind
of
embedded
systems
where
they
want
a
system
where
they
want
functions
that
can
never
panic
or
functions
that
are
guaranteed
to
not
panic.
For
code
code,
size
reasons
or
just
have
correctness
reasons,
and
so
this
is
a
very
lightweight
way
to
say
to
do
crazy
analysis
at
compile
time
and
a
kind
of
a
interesting
sense.
But
the
idea
is
that
this
is
at
least
a
way
to
say
this
function
never
panics
when
at
runtime,
when
I
actually
compile
it,
and
you
can
know
that
statically.
A
Sorry,
that's
what
I
have
if
you
have
some
further
questions.
These
are
some
great
links,
the
first
of
which
is
David's
proc
macro
workshop
done
yesterday,
which
has
a
lot
of
excellent
exercises
to
kind
of
get
your
feet
wet,
see
how
these
macros
work
in
various
different
ways
and
kind
of
get
used
to
sin
and
quote,
and
all
that
the
reference
for
procedure.
Macros
is
actually
pretty
up-to-date
and
it
has
none
necessarily
it's
it's.
It's
very
technical.