►
From YouTube: RustConf 2021 - Supercharging Your Code With Five Little-Known Attributes by Jackson Lewis
Description
Supercharging Your Code With Five Little-Known Attributes by Jackson Lewis
Attributes are one of the most useful and convenient features in the Rust language, enabling programmers to auto-derive traits, set up a test suite in minutes, and conditionally compile code for different platforms. But there are many other useful attributes, both inside and outside of the standard library, that often go unnoticed. Join us as we go through five attributes you might not know about - and how you can use them to both optimize and strengthen your code.
A
I'm
going
to
assume
that
you
have
an
intermediate
understanding
of
rust
for
this
talk,
because
today
is
going
to
be
a
deep
dive
into
some
of
the
more
obscure
aspects
of
the
language.
That
being
said,
I've
done
my
best
to
make
this
accessible
to
everyone.
Let's
get
right
into
it,
shall
we
so,
as
albert
einstein
once
said,
rust
attributes
are
pretty
lit.
A
A
Luckily,
we
rust
stations
have
tools
to
help
mitigate
this
issue,
code,
comments,
idiomatic
guidelines
and
strong
typing,
but
in
my
opinion
the
attribute
is
one
of
the
greatest
tools
we
have
as
rust.
Programmers
one
that
can
save
on
boilerplate,
reduce
the
chances
of
making
mistakes
and
bruise
and
boost
productivity
all
at
the
same
time.
A
If
you've
ever
derived
a
trade
for
a
struct,
then
you've
used
an
attribute
from
the
standard
library
or
you
might
have
used
the
test
attribute
before
to
write
a
unit
test.
But
that's
not
all.
You
can
also
define
your
own
attributes
and
import
them
from
third-party
creates,
for
example,
seer
day
is
a
popular
third-party
attribute
that
will
automatically
derive
functions
to
manage
the
serialization
and
deserialization
of
your
structs.
A
If
you
browse
through
crates.io,
you
will
find
hundreds
of
attribute
libraries
that
get
completely
neglected
and
even
in
the
standard
library
there
are
attributes
that
no
one
seems
to
use.
So
today
I
want
to
talk
about
five
of
these
attributes
that
are
hidden
in
both
the
standard
library
and
package
registry
and
how
they
can
give
your
code
superpowers
so
to
keep
this
talk,
interesting,
interesting,
I'll,
be
explaining
these
attributes
through
a
hypothetical
story.
A
Okay,
what
we
have
right
here
is
the
option
enum
one
of
the
most
foundational
types
in
rust.
One
day,
a
controversial
feature
request
proposed
is
adding
a
third
variant
to
the
option.
Enum
called
possible,
while
the
maintainers
insist
that
it's
rather
redundant.
The
creator
of
this
feature
request
says
that
it
will
revolutionize
the
language
but
there's
a
problem.
A
As
you
can
see,
exhaustive
matches
are
fragile
to
changes
in
enum
variants
or
struct
fields,
because
of
this
crate,
maintainers
can
often
feel
pressure
to
push
a
new
major
version
every
single
time
they
make
modifications
to
public,
enums
or
structs
in
the
worry
that
the
changes
will
break
downstream
crates.
But
is
there
a
way
to
prevent
this
from
happening?
A
A
A
It
should
be
noted
that
adding
non-exhaustive
to
your
enum
or
struct
is
a
breaking
change
to
your
api,
because
it
invalidates
any
match
statements
that
do
not
have
a
wild
card
branch.
So
if
you
want
to
make
your
e-number
struck
non-exhaustive
it's
best
to
do
it
when
you
first
make
it
okay,
let's
go
back
to
our
code
from
earlier.
A
If
non-exhaustive
had
been
added
to
the
option,
enum
our
pattern
matching
code
would
wouldn't
just
look
like
this.
We
would
need
to
add
this
wildcard
statement
too
yeah,
even
though
we've
exhaustively
matched
all
the
variants,
we
need
to
add
that
wildcard
or
the
compiler
will
throw
an
error,
because
the
wildcard
will
cover
future
changes
to
this
enum.
A
As
you
can
see,
even
after
we
add
the
new
variant,
this
code
will
not
break
since
the
new
variant
will
be
covered
by
the
wildcard
branch
that
we
added
and
that's
the
power
of
non-exhaustive
okay.
So
shortly
after
this
controversial
rewrite,
you
take
a
break
from
open
source
to
work
for
a
local
pizza
restaurant.
They
are
very
forward
thinking,
so
their
website
back
end
has
been
written
entirely
in
rust.
A
However,
they
also
have
a
legacy
code
base,
written
in
c,
which
is
slowly
being
replaced
with
rust
code.
They
have
a
function
in
this
rest
code
called
pizza,
validator
that
checks
if
a
customer's
pizza
order
is
valid.
Unfortunately,
it
has
two
major
problems:
one
it's
poorly
optimized
and
two.
It
allows
customers
to
order
pineapple
on
their
pizza
gross.
A
A
So
a
short
while
later
you've
written
a
new
and
improved
pizza,
validation
function
that
outlaws
pineapples
and
you've
gone
around
the
code
for
the
new
site
and
replaced
many
of
the
existing
calls
to
pizza
validator
with
the
new
function.
But
there's
a
problem.
A
few
days
later,
in
order
for
pineapple
pizza
comes
in,
which
you
know
shouldn't
be
happening,
you
identify
the
problem
in
a
function
called
add
to
order.
A
A
Well,
it
would
be
nice
if
we
could
mark
this
old
function
as
being
improper
to
use
without
outright
removing
it,
and
it
turns
out
that
the
standard
library
gives
us
a
way
to
do
this.
All
we
need
to
do
is
put
the
deprecated
attribute
at
the
top
of
the
function
and
the
compiler
will
emit
a
warning.
When
someone
tries
to
use
it,
you
can
even
provide
a
custom
message
to
go
with
this
warning.
A
So
now,
if
we
try
to
use
the
old
pizza
validation
function
in
the
new
function
code,
we're
going
to
get
a
warning
from
the
compiler,
and
in
this
case
you
don't
just
want
a
warning.
You
want
to
make
sure
that
using
a
deprecated
function
will
throw
an
error
for
certain
parts
of
your
code
base.
So
if
you
put
a
deny
deprecated
attribute
here
or
at
a
higher
level
in
the
crate,
the
compiler
will
make
this
an
error
instead
of
a
warning
and
that's
the
power
of
deprecated.
A
A
few
days
after
this
incident,
a
report
comes
in
about
the
legacy
code
base.
A
segmentation
fault
is
occurring
due
to
a
mistake
that
a
programmer
made
while
using
an
unsafe
function
called
two
box.
This
legacy
code
base
has
several
unsaved
functions
that
require
the
usage
of
raw
pointers
in
order
to
work
with
the
old
c
library,
and
two
boxes
meant
to
convert
these
raw
pointers
back
into
a
safe
box,
pointer,
as
you
can
see,
whoever
wrote
this
function
left
safety
documentation
in
the
comments
which
is
the
right
thing
to
do.
A
However,
there
are
still
two
problems
with
this
code.
The
first
problem
is
that
two
box
can
still
be
used
without
the
programmer
looking
at
the
safety
documentation,
and
the
second
problem
is
that
the
this
safety
documentation
fails
to
mention
that
passing
in
a
null
pointer
will
also
cause
a
segmentation
fault,
and
it
is
unsound
to
pass
in
a
pointer
that
points
to
memory
which
was
not
allocated
by
the
global
rest
allocator.
A
But
you
know
I
can
understand
that,
because,
when
you're
writing
a
safety
comment,
it's
possible
to
accidentally
overlook
some
edge
cases.
Now.
What
can
we
do
to
fix
this?
Well,
we
could
start
by
expanding
the
safety
section
and
putting
a
debug
assertion
to
check
if
the
pointer
is
null,
but
still
proving
that
the
function
is
safe,
is
still
dependent
on
the
function
itself
and
not
on
its
color.
Wouldn't
it
be
better
if
the
caller
was
responsible
for
proofing
that
they're
using
the
function
safely.
A
A
A
A
As
you
can
see,
the
code
first
creates
a
pizza
struct
by
calling
into
the
legacy
cc
library,
which
appears
to
be
wrapped
with
a
safe
binding
on
the
rest
side.
So
we
don't
need
to
use
unsafe
here.
The
pizza
struct
does
have
a
default
method
on
the
rest
side
of
things,
but
it
looks
like
we're
using
a
function
from
c
to
allocate
it
for
whatever
reason.
A
Then
it
passes
the
pointer
into
the
randomize
function,
which
will
randomize
the
toppings
for
the
pizza,
though
this
also
calls
across
the
cffi.
It
appears
to
be
wrapped
here,
so
we
don't
need
to
use
unsafe
and
then
finally,
it
gets
a
unique
box
pointer
to
the
pizza
back
using
two
box.
Since
two
box
is
an
unsafe
function,
we
need
an
unsafe
block
here.
A
However,
since
we've
added
preconditions
to
the
to
box
function,
we
also
need
to
assure
that
we're
using
this
function
correctly
or
this
code
will
no
longer
compile
and
adding
these
assurances
will
help
us
spot.
The
reason
why
this
code
is
segfaulting,
so
first
we
need
to
assure
that
this
pointer
won't
be
null
by
putting
the
assure
attribute
which
is
part
of
the
pre-library.
A
On
this
two
box
call.
This
will
run
an
assertion
in
debug
mode
at
the
call
site,
with
the
provided
condition
in
this
case.
That
pizza
pointer
is
not
null
note
that
we
also
have
to
add
a
reason
as
to
why
this
precondition
is
satisfied
which
makes
users
more
aware
of
whether
or
not
the
provided
condition
will
hold.
A
A
After
we
rewrite
the
code
to
allocate
the
pizza
on
the
rest
side,
we
can
provide
a
proper
reason
in
the
sure
attribute
for
why
these
conditions
are
satisfied.
A
The
next
week,
you're
asked
to
perform
a
refactor
on
the
pizza
struct.
When
you
go
to
make
some
changes
to
it,
the
definit,
the
definition
looks
off
something
about.
It
is
seriously
bothering
you,
but
you
can't
place
your
finger
on
it.
Oh
that's
right!
It's
these
publicity
modifiers
right
here
the
fields
are
public
so
that
you
can
read
from
from
them
directly.
Instead
of
using
a
getter
function,
that's
useful,
but
any
programmer
could
also
modify
these
fields
if
they
owned
this
pizza
variable
immutably.
A
Furthermore,
since
all
the
struct
fields
are
public,
the
struct
can
be
initialized
elsewhere,
using
raw
struct,
initialization
syntax
and
all
of
this
bypasses
the
existing
functions,
which
are
meant
to
handle
state
changes
and
initialization
of
the
pizza
struct.
But
the
good
news
is
there's
an
attribute
to
fix
this.
It's
so
useful.
In
fact,
I
wish
it
was
in
the
standard
library
it's
called
read-only.
A
All
you
have
to
do
is
add
read-only
as
a
dependency
to
your
crate
and
then
put
the
read-only
make
attribute
on
the
struct
of
your
choosing
any
function
that
would
have
had
access
to
these
fields,
even
if
they
weren't
public
can
still
write
to
them.
For
example,
this
mozzarella
method
can
still
write
to
the
struct
directly,
but
outside
the
file
you
can
only
read
from
the
public
fields
and
you
can't
initialize
the
struct
with
struct
initialization
syntax.
A
So
this
function
right
here
will
compile
just
fine,
since
we
only
read
from
the
cheese
field,
even
though
we're
taking
the
struct
as
a
mutable
reference.
However,
this
function
will
not
work
since
we
try
to
modify
the
field
directly
and
then
we
also
try
to
build
a
new
struct
using
initialization
syntax.
This
will
create
two
separate
compile
errors
so,
but
to
solve
our
particular
problem,
we
don't
need
to
make
all
the
fields
read.
Only
we
just
need
to
keep
a
few
fields
from
being
changed.
The
good
news
is
that
read
only
supports
this
too.
A
By
putting
the
read-only
attribute
on
individual
fields,
the
other
fields
can
still
be
written
to,
based
on
the
normal
publicity
modifiers
and
that's
the
power
of
read-only
okay.
Finally,
there
is
one
major
problem
that
still
needs
to
be
resolved
with
the
pizza
restaurant's
website.
The
legacy
system
and
the
new
system
use
a
separate
database
for
storing
customer
orders.
A
Since
the
new
system
should
read
from
both
databases,
a
trait
called
order
has
been
created,
which
provides
a
common
interface
over
the
two
order
formats,
which
will
let
the
new
system
deserialize
operate
on
and
then
serialize
these
two
schemas
interchangeably,
but
unfortunately
that
doesn't
work
because
cerade
can't
serialize
and
deserialize
trade
objects
due
to
object
safety
rules
with
serialized
and
deserialized
traits.
A
As
you
can
see
here,
if
we
try
to
create
a
box
pointer
to
a
dynamic
trade
object,
the
compiler
will
tell
us
that
order
is
not
object
safe,
and
this
is
because
seer
day,
cyrado's,
serialized
and
deserialized
traits
are
requirements
for
this
trait
and
those
are
not
objects
safe
themselves.
A
So,
let's
go
back
to
the
order
trade
this
time
with
no
requirements
for
serialize
or
deserialize,
because
that
clearly
didn't
work
as
planned
in
order
to
serialize
and
deserialize
an
arbitrary
object
of
this
we're
going
to
need.
The
third
party
type
tag
attribute
type
tag.
Lets
you
serialize
a
trade
object
as
an
enum
or
each
variant
is
an
implementer
of
that
trait
and
the
content
is
the
serialized
version
of
that
implementer.
A
All
we
need
to
do
is
put
the
attribute
above
each
implementation,
and
this
works,
even
if
the
implementations
are
in
different
crates,
which
I
think
is
really
cool
now
the
code
which
previously
failed
will
compile
without
any
problems
and
that's
the
power
of
type
tag,
alright,
that
just
about
wraps
it
up.
I
hope
you
learned
at
least
a
few
new
attributes
and
how
you
can
apply
them
to
real
world
scenarios.