►
Description
Rust expresses trait bounds using the where clause. It is an essential tool for all generic Rust programming. Yet, many Rust programmers don't know about the full expressiveness of it!
This talk guides us through most of the features and shows us how to creatively use where clauses to both keep our code clean and flexible, but also sound and hard to use in a wrong way.
This talk will teach us the basic building blocks to not get lost in a forest of constraints.
Follow us on Twitter: https://twitter.com/rustlatamconf
A
Well,
hello
and
thank
you
first
of
all,
Alex
has
not
told
you
the
full
story.
This
is
now
a
completely
valid
Ross
program
and
you
actually
don't
need
to
program
anything
anymore.
You
can
just
have
everything
generated.
We
just
lost
their
jobs,
so
Who
am
I
I'm
Rory
on
Twitter
and
company
links
on
this
slide.
A
I'm
here
for
Mozilla,
actually
Mozilla
sent
me
here
as
a
part
of
the
tech
speaker
program,
and
this
is
actually
my
second
time
I'm
on
this
stage.
I
was
here
before
at
Rubicon.
Why
keeping
my
I
was
10
years
in
the
Ruby
community.
Talk
now
I'm
5
years
in
the
rust
community
is
something
like
that
and
I
met
a
lot
of
familiar
faces,
I'm
happy
to
be
again:
I
started
rust
in
2015,
mostly
out
of
personal
curiosity
and
because
I'm,
not
a
good
solo
learner.
A
I
immediately
started
the
Berlin
user
group,
which
is
one
of
the
biggest
and
most
active
around
the
globe.
I'm
organizing
a
to
Russ
conferences,
Wurstfest
and
oxidized
conf
I
can
have
the
emphasize
with
how
much
and
have
much
of
a
great
job.
This
is
having
that
and
I'm
a
product.
Member
since
2015,
mostly
in
the
community
team
and
now
also
moving
to
other
spaces
and
I,
can
definitely
agree
with
Nico
that
the
Russ
project
is
very,
very
easy
to
join
on
all
positions.
If
you
have
something
that
specifically,
this
is
specifically
off
your
interest.
A
It's
really
easy
to
get
in
touch
with
people
and
get
involved,
and
this
is
also
my
first
talk
on
a
Russ
conference.
I've
organized
them,
I
have
never
given
a
talk
in
Russ
conference
and
what
I
want
to
do
is
I
want
to
make
you
competent
at
reading
and
writing
where
classes,
because
they
are
important,
but
have
some
subtleties
to
understand.
So,
just
as
a
bit
of
background,
what
is
the
where
clause?
Let's
say
we
have
a
pretty
simple
data
type.
A
We
have
a
point
point
has
an
X
and
the
y
value
and
we
have
a
function.
That's
called
print
point
that
just
takes
a
reference
to
that
point.
It
prints
it
out
nothing
important.
The
most
important
thing
here
is
this
point
implements
debug,
because
our
println
macro
requires
things
that
we
print
out
using
the
coop
question.
Mark
syntax,
sorry,
it
requires
them
to
be
debug,
but
this
version
of
this
function
just
takes
a
bear
point.
So
whatever
have
squares
so
I
have
a
square,
it
has
an
x
and
y
position
and
width.
A
That's
enough
to
describe
a
square
and
I
can
write
a
print
square
function
that
takes
the
square
and
just
does
exactly
the
same
thing.
That's
very
repetitive
and
computers
are
very
good
at
repetitive.
We
are
not
as
good
as
computers
here
and
the
unifying
thing,
but
the
instant
between
these
two
is
not
that
they're
shapes
for
the
printing
function.
What
we
need
is
actually
that
both
of
them
implement
the
debugging
representation
by
using
the
derive
debug
statement
up
there.
So
we
can
rewrite
that
function
as
FN
print
takes
a
shape.
A
S
takes
a
borrow
of
the
shape
s
and
prints
it
out,
but
the
important
thing
is:
we
need
to
indicate
to
the
compiler
in
some
way
that
we
only
accept
types
that
we
can
actually
turn
into
this
debug
representation
that
we
do
using
the
where
Clause.
So
we
put
there
where,
as
is
debug,
the
thing
under
number
three
is
called
the
trade
bound
and
the
thing
under
number
one
is
called
a
trade
variable,
a
type
variable
sorry.
A
So
now
we
can
both
create
a
point
and
a
Square
and
use
both
print,
both
of
them
out
using
print.
The
important
part
here
is
the
first
statement.
The
first
print
statement
internally
calls
a
function.
That's
called
something
like
print
point
and
the
second
something
like
print
Square
important
thing
here
is
those
are
actually
different
functions.
The
compiler
just
generates
them
for
us.
Logically
speaking,
there
is
an
infinite
number
of
those
there's,
an
infinite
number
of
those
function
for
every
type
that
is
debug,
but
in
case
of
this
program
we
actually
only
compiled
two.
A
So
for
rust.
From
rust
point
of
view,
those
functions
will
be
compiled
on
need.
We
are
actually
using
print
point.
We
are
actually
using
print
square.
These
two
are
needed.
These
two
are
going
to
be
generated.
There
are
other
places
where
the
where
Clause
can
be
stated.
For
example,
we
can
create
a
struct
that
is
generic.
That
inside
has
to
some
things,
preferably
numbers.
A
If
we
representing
a
point-
and
we
can
also
say
he
needs
to
be
debug
most
of
the
stuff-
that's
important-
you
can
totally
exercise
on
functions
a
bit
more
detail
here,
so
we
have
a
function
that
takes
that
has
two
generics
T
and
E
and
I
can
express
what
I
want
from
them.
First
of
all,
what
the
wave
function
the
where
Clause
gives
me
over
any
color
other
shorthand
syntax
is
that
I
can
split
it
up,
so
it
can
state
but
bounce
multiple
times,
I
can
say:
I
want
t
to
implement
a
trade
call.
A
A
A
A
Where
classes
are
important
for
a
couple
of
reasons,
for
example,
they
are
the
way
how
we
can,
for
example,
constrain
on
the
type
that
an
iterator
returns
us
so
again,
using
just
the
bear.
Debug
trade
and
printing
stuff
out
to
the
console
I
can
have
a
function
called
debug
eater
that
takes
any
kind
of
iterator.
The
iterator
trade
is
again
standard
iterator,
but
it
has
an
Associated
type,
which
is
the
item
that
it's
going
to
return.
I,
don't
know
what
the
item
is,
but
using
the
where
Clause
I
can
at
least
say.
A
A
That's
the
okay
variant
of
the
result,
enum
or
it
gives
me
an
error
back
that
doesn't
give
me
a
lot
and
if
you
have
a
look
at
the
standard
library,
implementation
of
results,
there's
a
couple
of
functions
defined
that
this
is
less
actually
a
lot
of
functions
defined
on
this
type
and
the
most
basic
ones
are,
for
example,
here
the
implementation
for
any
kind
of
result,
value
or
error
I
have
two
functions,
is
okay
or
is
error?
Just
let
just
tell
me
which
of
the
variants.
A
The
other
way
around
there's
implementations
for,
if
T
value,
when
when
everything
work,
if
T
implements
default,
so
it
has
a
default
value,
result
gains
a
function,
that's
called
unwrap
or
default,
which
doesn't
panic,
but
instead,
in
case
of
an
error,
gives
me
the
default
value
back,
so
we
are
gradually
constraining
the
result,
type
more
and
the
more
we
know
about
it.
The
more
functions
get
unlocked
on
it
and
gradually
unlocking
features
based
on
these
kinds
of
bounds
is
a
common
API
strategy
in
rosslyn.
You
can
see
that
all
through
the
standard
library.
A
A
The
threading
API
is
generic
because
they
can
push
anything
inside
and
get
anything
back
so
coming
up
with
a
first
attempt
at
writing
that
on
my
own,
you
could
come
up
with
something
like
this.
You
have
the
sweat
spawn
function.
It
takes
an
F
and
the
T
type
takes
in
DF.
It
returns
me
the
T.
Why
is
it
F
second
thread
spawn
takes
the
closure
ones.
That
closure
includes
all
the
data
that
is
my
close
close
over.
In
this
case
the
vector
and
returns
me
whatever.
A
That
closure
has
actually
returned
as
the
join
handle
so
join
handle
will
be
me.
Information
of
has
that
one
has
that
that
actually
run
to
completion.
Was
there
an
error
whatever,
but
it
gives
me
the
result.
All
you
back.
The
problem
is
what
fits
these
slots,
what
can
I
put
into
that
F
and
that
T
problem
there
is
threats
if
I'm
spawning
a
thread.
A
classic
problem
is
all
the
data
that
is
put
on.
That
thread
should
preferably
not
reference
anything
out
of
the
context
where
the
thread
was
spawned
in.
Why?
A
Because
both
are
going
to
run
in
parallel
and
the
data
in
the
first
part
might
be
removed,
changed
whatever
and
is
independent
of
the
second.
So
I
want
to
have
this
idea
that
Nikko
introduced
today
today
in
the
morning
of
actually
giving
complete
packages
over
and
also
getting
complete
packages
back
and
forcing
the
forcing
the
programmer
to
actually
move
everything
over
and
not
half
of
it.
A
The
problem
is
if
I
would
write
the
API
like
this,
that
were
actually
possible
because
I
have
not
any
have
no
other
constraints
on
F
and
T,
then
that
they
actually
generic
types
that
might
be,
they
might
end
up
being
references.
They
might
be
any
kind
of
valid
lost
type.
So
what
I
can
do?
I
can
use
the
work
where,
at
the,
where
clause
here
to
express
additional
things
here
and
a
way
of
expressing
what
I
just
said,
you
can
actually
send
that
stuff
over
to
a
thread.
A
A
That's
called
to
ecstatic
and
the
bound
any
type
plastic
static
essentially
means
it
must
own
all
data,
so
you
can
give
up
complete
ownership,
like
the
party
that
spawns
the
threat
must
give
up
complete
ownership
of
all
the
data
of
all
the
payload
it
puts
on
the
Fed
and
after
the
threat
is
done,
we
want
to
remove
it
and
throw
it
away.
We
also
need
to
have
the
ability
to
bring
everything
back
that
you
want
to
bring.
So
this
F
cent
prostatic
bound
expresses
this
quite
neatly.
A
There
was
an
issue
in
my
teaching
in
like
two
or
three
years
ago
that
people
felt
like
expressing
plastic
static
is
cheating
because
you
don't
take
part
in
the
references
game.
It's
actually
a
meaningful
statement.
If
you
don't
want
to
deal
with
references,
if
you
don't
want
to
deal
with
borrows
just
Express
tic
static
and
that's
probably
a
very
valid
solution
to
your
problem
and
just
deal
with
ownership.
A
Trade
now
I
have
another
function
that
takes
that
rapper
into
some
raps
it
and
takes
the
inner
part,
but
because
I
have
expressed
that
rapper
only
can
can
only
have
pipes
with
a
certain
bound
inside
if
I
want
to
write,
take
inner
I
also
to
fulfill
that
I
also
always
have
to
constrain
the
generic
type
or
the
generic
variables
of
take
inner
as
debug
the
function
itself
doesn't
actually
use
it,
though.
So
that's
a
problem,
I'm
I
want
to
try
I
want
to
write
this
function.
A
It
just
does
nothing
more
than
taking
that
structure
taking
out
whatsoever
inside,
but
I
do
have
to
express
an
additional
bound
just
to
basically
reiterate
that
rapper
already
expects
the
inner
part
to
be
debug,
and
nothing
else
is
so.
What
can
I
do
against
that?
There's
a
pattern
in
which
you
can
write
this
rapper
in
a
way
that
it
actually
itself
can't
contain
any
type,
but
you
can
exactly
only
create
that
rapper
in
a
fashion
where
it
is
debug.
Let's
just
do
me
in
here.
The
way
it
works.
A
Is
you
don't
consider
you
don't
allow
users
to
directly
construct
the
type
and
you're
only
giving
them
a
constructor,
and
that
constructor
carries
the
bound
that
I
want
to
express
the
what
you
can
then
do
is
later,
if
you
actually
want
to
use
this
bound,
for
example,
by
putting
in
and
putting
an
inspect
method
on
that
wrapper,
and
you
just
need
to
restate
it,
but
because
the
compiler
actually
follows
all
those
variables
through
the
whole
program.
It
will
still
know.
A
A
So
where
classes
are
primary,
refactoring
targets,
if
you
want
to
change
your
program
and
make
it
more
flexible,
more
constrained,
depending
on
what
your
goal
is
your?
Where
classes
are
your
primary
refactoring
target
also
don't
start
out
extremely
generic,
like
don't
try
to
write
generic
code
out
of
the
blue.
The
pattern
that
I've
shown
in
the
beginning,
figuring
out
that
two
or
three
functions
are
basically
the
same,
and
you
probably
can
move
them
into
into
a
generic
function
is
a
very
useful
one.
A
It's
probably
the
thing
that
I've
shown
in
the
beginning,
you
that's
something
you
could
write
immediately,
but
any
kind
of
more
complex
system
start
simple
start
building
up
stop
building
into
the
generic
into
generic
us.
Also,
the
finding
the
right
level
is
important,
though
that's
a
classic
in
programming.
A
lot
of
application
programming,
like
outer
edge
application
programming,
suffers
from
the
fact
that
people
try
to
do
it
to
make
it
too
generic,
so,
but
for
library,
authors,
for
giving
flexibility
and
for
communicating
intent
to
the
outside.
A
This
is
very
useful,
so
always
be
aware
where
you
are
and
whether
that's
actually
needed
and
in
the
end
you
might
have
ended
up
writing
terrible
clauses
like
this.
This
is
from
one
of
my
current
projects,
I'm
going
to
refactor
that
tomorrow,
as
literary
work
in
progress,
ok,
some
advanced
examples,
drape
penetrates
and
bounds
can
be
used
to
express
relationships
between
types,
and
this
becomes
very
useful.
This
is
one
of
my
favorite
Twitter
accounts.
It's
called
a
happy
automata
or
vaguely
reassuring
state
machines.
A
It
generates
state
machines
like
this
and
I
would
like
to
write
one
of
those
state
machines.
Myself
and
state
machines
usually
have
States
some
of
those
states
or
terminals
I
skip
having
stop
states
in
this
example.
Just
because
that
will
be
wrote
and
would
just
make
the
example
bigger,
but
what
I
can
have
is
I
can
write,
for
example,
two
traits
the
first
one
being
transitioned
to
s.
Another
state
expressing
the
work
loss-
s
needs
to
be
a
state.
A
Self
also
needs
to
be
a
state.
So
it
can
make
a
statement
about
the
the
type
that
this
trait
is
going
to
be
implemented
on
and
give
that
a
function,
called
transition
and
transition
will
take
the
current
state
actually
owning
and
thereby
destroying
it
and
return
the
next
state
and
another
trade
terminate
that
can
only
be
called
in
terminal
states
that
just
removes
the
state
machine
it
calls
it
done
and
I
can
create
myself
three
states
the
state
machines
that
I'm
creating
here
is
basically
there's
a
start.
A
There's
a
mid
state
that
I
can
actually
loop
into
again
and
then
there's
an
end.
So
I
have
start
looping
stops
I
implement
state
for
them.
This
is
actually
an
empty
trait.
It's
just
a
marker
to
make
the
compiler
know
these
types
are
states,
there's
no
again
no
functionality
from
that
and
stop
is
actually
the
terminal
state.
A
That's
where
I'm
ending
and
then
I
can
implement
transition
to
loop
from
start
I
can
go
from
loop
to
start
transition
to
loop
for
loop,
so
I
can
go
back
into
it
again
and
transition
to
from
to
end
for
loop.
Sorry,
there's
an
error
on
the
slide
and
implement
terminate
for
end,
so
I
can
actually
call
so
I
can
actually
stop.
That
means.
I
cannot
terminate
that
state
machine
if
I
have
not
ended
up
in
the
end
state.
A
So
I
need
to
make
sure
that
people
are
actually
that
the
users
of
the
state
machine
actually
follow
through
and
take
this
process
to.
The
end
of
the
code
here
is
simple.
This
is
one
pattern:
how
to
write
this
there's
a
whole
blog
post
on
this
by
community
member
called
hover
bear
and
the
setup,
and
the
programming
of
this
is
a
little
involved,
but
the
usage
is
rather
straightforward.
A
The
reason
why
I
have
to
type
the
left
side
so
I
need
to
actually
Express
what
the
next
set
is
going
to
be
is
exactly
because
I
have
this
loop
state
where
it
can
either
loop
again
or
go
to
the
end
state,
and
this
is
something
where
I
actually
have
to
tell
the
type
checker
I
intend
to
be
this
this
to
be
the
next
state.
The
two
comments
in
the
middle,
those
wouldn't
compile.
A
A
A
The
problem
with
this
definition
is
I
could
try
to
get
anything
out
of
that.
I
could
try
to
read
strings
vectors
mutexes
whatever,
because
every
type
is
valid
to
fill
that
variable,
and
this
is
what
constraining
gives
me
constrain
to
the
things
that
are
meaningful
and
I
can
define
a
coat
right
here
that
says,
stores
model
and
I
can
also
constrain
the
stores
model
trade
to
it
can
only
be
different.
A
They
only
be
implemented
on
storages,
then
I
can
extend
my
function
with
where
self
actually
stores
that
model,
and
now
I've
defined
a
function
that
communicates.
You
can
try
to
query
models
out
of
this,
but
only
if
it
actually
stores
them
and
you
force
the
implementer
to
actually
declare
what's
stored
here,
to
declare
that
to
the
component.
A
So,
for
example,
I
can
have
a
users
database.
This
uses
database
implements
storage
by
what
do
I
know
an
SQLite
back
database
source
Cresson,
whatever
I
have
a
user
model
and,
for
example,
another
Avatar
model,
so
they
can
have
users
and
davit
house
in
the
same
database
and
then
I
implement,
implements
stores
user
and
implements
stores
avatar
for
users
database,
and
this
becomes
pretty
natural
it
so
having.
A
And
in
the
end,
I
have
things:
I
can
write
a
program
that
boil
down,
looks
like
this:
I
can
have
I
can
connect
to
my
database.
I
can
try
to
query
it.
I
actually
have
to
state
at
this
point
what
model
I
actually
want
to
query
out
of
it.
A
So
here
the
type
checker
won't
help
me
because
I've
actually
said
I
want
to
have
multiple
options
and
I
need
to
decide
so
I'm
saying
query
the
user
out
of
that
database,
but
if
I
would
try
to
query
a
string
out
of
it
or
any
kind
of
other
type,
it
will
tell
me
no
I
actually
don't
store
this.
The
error
message
in
this
case
would
be
that
the
storage
actually
doesn't
implement
and
the
function
exists,
but
it
doesn't
implement
the
the
right
bounds.
A
So
the
conclusion
out
of
all
of
this
I'm
getting
comfortable
with
all
the
stuff
that,
where
clauses
give
you
is
important,
take
it
slow,
though
so.
Don't
start
writing
big
ones,
just
right
out
of
the
door,
exactly
picking
which
constraints
you
need.
Where
is
key
and
spending
some
time
and
actually
figuring
out
what
you
need
potentially
over
constraining.
First
later,
maybe
removing
some
of
the
constraints
may
help.
There's
also
an
API
concern
around
this.