►
From YouTube: RustConf 2019 - Messing Around with fn main() and Getting Away with it by Yoshua Wuyts
Description
RustConf 2019 - Messing Around with FN Main() and Getting Away with it by Yoshua Wuyts
The introduction of return types in main has made writing binaries a lot nicer. But why stop there? What if we could make main an async fn to support top-level await? Or perhaps allow main to take command line arguments as parameters?
In this talk I’ll show how to make fn main perform party tricks, make boilerplate disappear, and saw code size in half. And by the end of the show you’ll have a good picture to take home of what Rust might look like in the future.
A
Hello,
I'm
Yosh:
this
is
my
talk.
It's
called
messing
around
with
Maine
and
getting
away
with
it
now
Who
am
I.
I
am
Yosh,
like
I
said,
like
Suns
already
said
so
it's
three
times,
I
guess
I'm
a
research
engineer,
which
means
I,
guess
I
do
open
source
anyway,
oh
yeah
background
I
used
to
do
like
loads
of
JavaScript.
I
did
I
look
for
like
five
years
published
like
things
on
NPM
a
lot
and
then
I
moved
to
rust
like
two
years
ago,
I,
like
economics,
I,
guess
it's.
A
The
is
the
main
thing
that
I
want
to
share
there
anyway,
introducing
the
main
characters
of
today's
talk,
because
it's
not
me:
it's
not
function
man,
it's
actually
this
guy
over
here,
name's
Joshua,
another
cat,
it's
naughty,
and
because
this
is
a
rest
talk,
you
know
we
need
to
introduce
some
concurrency,
some
parallelism,
so
here
they
are
together
all
right,
okay,
cool.
So
why
are
we
giving
this
talk?
Well,
first
off
my
refseq
of
my
proposal
got
accepted,
which
means
that
no
organisers
were
like.
A
Okay,
we
think
you
can
give
a
talk,
but
I
was
surprised,
though
it's
like
I
like
function
main
and
in
JavaScript.
You
don't
really
have
function,
man,
you
just
add
a
pragmatic
to
the
top
of
a
file,
and
you
execute
that
file
and
it's
like
oh
cool
that
works,
but
you
know
a
roast
wavefunction
man,
it's
like
a
clear
defined
entry
point
into
your
program.
I
think
that's
very
cool
I
think
when
we
added
the
result
to
it.
That
was
a
nice
addition.
A
I
was
like
thinking
hey
what
other
things
can
we
like
I,
like
your
wax
I
like
it?
You
know,
people
also
call
this
urban
onyx
or
like
developer
experience.
I.
Think
that's
nice
I
think.
If,
if
we
provide
a
nice
way
for
people
to
use
things,
then
they'll
tend
to
use
it
and
fewer
mistakes
are
made
and
we
all
have
a
little
bit
more
fun.
Oh
yeah.
Third,
one
is
sharing
ideas.
I
have
a
bunch
of
ideas.
I've
got
a
stage
so
sharing
ideas,
that's
what
I'm
getting
this
stuff
cool.
A
So
let's
pretend
we're
all
like
time:
travelers
I'm,
gonna,
fast
forward
to
the
year
2021.
We
have
a
new
addition
out
and
we're
gonna
write
function
main
for
a
little
HTTP
server
that
we're
building
so
well.
We
started
off
with
a
function
main.
You
know.
You
know
this
one,
because
we're
building
an
HTTP
server
and
with
some
concurrency
it's
gonna
be
a
async
function
main.
You
can't
call
a
wait
without
a
sync,
so
you
know
it's
a
sing
function.
Man
also,
we
need
to
handle
errors,
we're
not
sure
quite
what
kind
of
errors.
A
So
we
just
say
hey.
This
thing
throws
if
you're
familiar
with
Java,
it's
like
checked
up
session
exceptions,
sweet
a
little
common
because
we're
like
good
citizens,
we
say
started
HTTP
server,
then
you
know
we
need
input
to
our
applications
or
going
to
find
some
input
arguments
args
of
type
args
which
we're
defining
out
there.
You
know:
well,
it's
HP
server,
so
we
need
a
port.
We
need
an
address
and
I
always
say
cool.
Let's
turn
this
into
CLI,
so
we
derive
something
from
crates
I/o
which
implements
CLI
so
wait.
A
But
yeah
we're
gonna,
build
a
low,
HP
server,
say:
I
create
a
new
tied,
app
and
I'm
on
the
on
the
route,
slash
for
the
methods,
it
just
be
method,
get
we're
gonna,
say
hello,
world
man,
that's
pretty
nice
and
then
we
say
start
this
thing
on
the
address
and
the
port,
and
we
await
it,
which
is
fallible.
And
then
this
thing
goes:
that's
a
HTTP
server
in
ten
lines,
it's
pretty
good
for
a
scene.
Competitor
might
say:
oh
I
forgot
about
this
one,
but
you
know
we
need
to
start
logging.
A
A
You
get
listening
on
localhost
8080
and
the
things
now
running.
Sweet,
alright.
So
for
today
what
we're
gonna
do
is
we're
gonna
go
over.
How
do
you
get
to
async
function
main?
How
do
you
get
main
arcs
like
args,
amen
and
finally
improving
errors
in
main
or
as
I
like
to
say?
We
have
three
main
courses,
no
joke,
they're,
happy,
Oh,
laughs,
all
right.
Let's
write
function,
man
likes
2021
in
2019
sorta,
and
also
we're
using
proc
macros
procedural
macros.
A
If
you're
familiar
with
the
word,
you
might
be
like
oh
yeah,
so
I'm,
sorry,
I'm,
sorry
through
everyone
who
knows
what
this
means
all
right
act:
1
async
all
right.
So
how
do
you
do
this
today?
The
async
function
main
well,
you
don't,
but
you
define
a
function
main
Oh
under
server.
I
should
preface
this
on
this
server,
which
is
native
or
whatever
you
get
a
little
executor
in
this
case,
we're
using
async
stood
which
came
out
last
week.
Let
me
say
block
on
and
inside
of
it
would
put
a
sink
closure.
A
So
what
happens
here
is
you
need
something
to
execute
the
async
code,
all
the
futures
and
stuff
and
at
the
top
level
you
know
you
mess
it
all
the
way
down,
but
top
levels.
Something
needs
to
be
running
this
in
this
case
block
on
it
runs
all
that
async
code
until
it's
done
at
blocks
until
it's
done
inside
of
it
we're
gonna,
say
hello
Joshua,
which
we
met
a
bit
earlier.
We're
gonna
sleep,
the
sleep
to
task
for
one.
Second,
we'll
wait
it
and
under
it
I'm,
gonna,
say
hello.
Naughty.
A
Now,
I
want
you
to
just
take
a
split
second
here
to
be
like
okay,
what's
what's
the
ordering
in
which
these
things
get
printed
cool,
let's
write
C.
So
we
run
this
thing.
We
say.
First
comes
hello!
Joshua,
then
comes
hello
naughty.
So
this
one
came
first.
This
one
came
second
cool
all
right
now,
let's,
let's
do
the
same
thing
for
the
browser
all
right,
so
we
have
a
function
main.
We
can't
use
a
6th
ed.
Quite
yet
so
we
use
a
wise
and
bunch
and
futures
and
their
spawn
local
I
would
say
spawn
local.
A
We
give
it
a
sync
closure.
We
say
hello
Joshua.
We
sleep
the
task
for
like
one
second
again
and
then
we
say
hello
naughty.
Now
again
like
what's
the
ordering
here,
that's
C!
Well,
hey,
oh,
hey!
I
forgot
about
this.
Alright.
In
order
to
like
make
this
make
this
work,
you
actually
need
to
do
a
pub
function
main
and
likewise,
invitin
start
there's
an
actual
code
that
will
actually
work
if
you
use
this
I
hope
so
to
run
this.
A
You
know
awesome
example:
hello,
naughty,
hello,
Joshua
yeah,
that's
not
super,
because
it
means
that
this
one's
running
first
and
this
one's
running.
Second,
and
the
reason
for
that
is
because
we're
not
in
control
of
the
executor
in
the
browser,
because
we're
hooking
into
JavaScript
promises
and
promises
are
invocate
immediately,
which
means
that
spawn
local
essentially
kicks
off
a
background
task
as
queued
for
a
next
take
on
the
event.
Loop
and
print
line,
nor
or
hello.
Naughty
is
printed
immediately
right.
A
Sirs
differences
between
how
it
works
in
the
browser
and
how
it
works
on
servers
were
difference
in
control
and
there's
like
more
environments
where
these
differences
exist.
So
a
solution
to
this
would
be
where
you
can't
get
it
wrong
is
if
we
had
something
like
async
function,
main
in
which
we
can
just
say,
hey
sleep
for
one
sec,
then
we
say
hello,
Joshua,
hello,
naughty!
There's!
No
more
a
question
of
ordering
and
a
way
we
can
make
this
happen
today
is
using
runtime,
which
is
I'm,
not
sure.
A
If
you
should
be
using
this,
but
it
works.
You
can
add
a
little
attribute
to
the
top,
which
just
says
like
it
is
async
function
main
and
we
have
a
PR
out,
we're
not
smart
to
forget
that
actually
makes
this
work
on
both
the
server
and
in
the
browser
removing
the
differences
which
is
kind
of
cool,
so
yeah,
that's
that's
the
first
one.
A
I
was
second
one
right
go
chapter,
two
arguments:
how
do
we
get
arguments
in
main
well
little
primer
on
what
arguments
are
I
like
to
think
of
them
as
input
to
your
application
right?
So
you
boot
up
your
app
and
like
it
gets
arguments
it
gets
input
from
somewhere,
so
a
classic
one
is
for
command
line.
Apps.
You
have
your
command
line
arguments,
but
also,
if
you're
running
stuff
again
in
a
browser.
What
you
might
actually
have
is
URLs,
like
query,
parameter
like
stuff
on
window
navigator.
A
That
is
like
initial
state,
but
you
need
to
read
out
before
you
can
boot
up
your
application
or
someone's
inlining
JSON
and
your
HTML
header
and,
like
whatever,
but
you
know,
there's
an
initial
status
thing,
another
one's
like
serverless
apps,
which
might
have
an
incoming
request.
That's
the
thing
that's
like
given
to
it
my
boot
up
and
has
like
some
form
of
output
at
the
end
again
so
arguments
today.
How
would
you
go
about
writing
a
little
command
line?
App?
Probably
something
like
this
little
function.
Man,
let
me
say,
stay
down.
A
You
know
the
N
marks,
so
we
get
the
arguments
and
I
only
say
for
Argan
args,
let's
print
the
Arg
cool
sweet.
Well,
not
really!
That's
not
really
how
you
do
things.
That's
that's
the
the
pretty
example.
The
actual
example
with,
probably
you
know,
look
a
bit
more
like
this.
You
know
it's
a
function,
man.
We
got
sedan,
mugs
again,
you
know,
and
instead
of
like
iterating
over
it
nicely
oops,
it
needs
to
be
mutable.
Also.
We
need
to
skip
the
first
one
because
those
are
self
you
know,
then
we
get
the
next
one.
A
Oh
we're
building
HTP
server
again
by
the
way
we
get
the
address
out,
Oh,
unwrapped
or
Hanalei,
or
somehow
cool.
Let's
get
the
port
that
is
next
on
the
wrap.
Parse
unwrapped.
Alright,
that's
not
that
great!
So
in
practice,
people
don't
really
do
that
they
tend
to
use
struct,
opt
more
likely
or
clap,
which
is
similar.
Sorry,
you
know
you
define
a
little
struct,
you
say
like
hey
I
want
to
port
you
16
I
want
to
address
which
is
string.
Then
we
derive
struct,
opt
on
it
and
then
we
say
4,
P
or
port.
A
Is
that
one
instead
of
like
positional
a
or
address
is
the
other
one?
You
know
I
really
like
that
can
just
like
click
to
the
next
line,
yeah
and
then
like
the
way
we
instantiate
this
and
we
say
like
we
get
the
struct,
which
now
implements
a
from
args
argument
that
you
need
to
know
about
there's
a
few
others
which
I've
never
used.
Then
you
say
Argos
remarks
and
then
we
get
that
which
means
in
either
instantiates
or
panics.
You
know
is
they
like?
The
questionnaire
is
like?
A
Is
it
clear
that
we
are
instantiating
application
input,
I,
don't
think
so
so
arguments
of
tomorrow,
a
better
way
of
doing
this
I
think
would
be
if
we
followed
what
oh
I
have
a
double
slider.
If
we
follow
what
C
does
with
Arg,
C
and
argue,
but
instead
of
like
doing
those
which
is
only
for
iterating,
we
could
just
put
arbitrary
like
structs
in
it
as
long
as
they
implement
some
sort
of
trait
into
the
main
position
can
do
the
parsing
for
us.
A
So
in
this
case
we
would
be
able
to
define
args
and
args
like
and
it
if,
as
long
as
it
parses,
we
get
the
actual
instantiation.
So
it's
cool
from
from
there
on
out.
We
can
look
assume
that
the
states
correctly
be
initialized
wait.
So
how
can
we
make
this
happen
today
is
using
a
little
attribute
called
pas
main
from
a
critical
path.
I
would
not
recommend
you
use
this
in
production,
but
definitely
try
it
out.
A
A
Is
for
service?
You
know
we
were
talking
about
like
a
server
list.
How
would
this
work?
So
it
is
a
function
main.
Let's
async,
we
get
an
incoming
event.
So
this
this
app
is
like
boot
like
triggered,
started
whenever
there's
an
event
incoming,
in
this
case
its
type
string.
Then
we
say
cool
we're,
gonna
print
it
out
and
like
return
it,
it's
like
a
little
fallible
signature.
There
we
say:
okay
event.
Then
we
add
a
lambda
lambda
in
the
case
of
AWS.
A
A
There's
a
there's
two
kinds
of
errors:
I
like
to
think
about:
there's
the
errors
you
can
handle
which
I
like
to
refer
to
as
exceptions,
they're,
the
result
or
type
and
there's
the
errors
you
can't
really
handle,
which
are
the
panic
types
which
are
invoked
through
panic
and
they
they
tend
to
crash
your
app
there's
some
edge
cases
around
threads
and
whether
or
not
that
should
like
crush
your
app.
But
let's
just
assume
it
crashes,
your
app
right
cool.
A
So
today,
there's
a
little
thing
about.
Oh,
is
this
okay
mess
up
my
slides,
I'm,
not
sure
I.
Think
I
messed
up
my
slides
here,
alright,
so,
okay,
rapping
I,
think
this
is
supposed
to
be
catch-all,
but
whatever
alright.
So
we
start
off
with
async
function
main,
which
returns
a
results,
and
it's
gonna
return
some
form
of
some
form
of
error
which
we're
going
to
find
it
a
bit.
A
We
just
say,
is
type
exception
all
right,
the
inside
of
it
we're
gonna
do
two
things:
we
have
a
get
cat
method
which
queries
an
API
somewhere
to
get
a
cat.
We
wrapped
it
in
debug
before
I
forget
why
and
we
have
another
method
called
process
cat
which
may
or
may
not
do
some
sort
of
like
I
owe
my
do.
Sabretooth
database
I'm,
not
sure
right.
We,
we
don't
really
know
we're
just
looking
at
this
at
this
method.
A
We
have
these
two,
these
two
methods
that
were
like
trying
to
do
something
with
they're,
both
async
they're,
both
fallible,
and
we
don't
really
know
what
the
what
the
error
type
here
is
right.
We
just
see
like.
Oh,
it
returns
a
result
of
something
and
the
other
one
probably
returns
a
different
result.
A
So
what
we
actually
want
to
have
is
we're
going
to
have
an
error
type
in
our
top
level
that
can
like
abstract
over
both
of
them,
where
we
don't
need
to
choose
one,
but
we
just
you
know
like
it's
an
error,
sweet,
let's
propagate
it.
So
the
way
we
would
define
this
today
is
by
oh
and
we're
missing
a
little
little
okay
of
unit
at
the
end,
which
is
very
common.
So
the
way
we
would
define
us
today
is
we
would
define
a
little
arrow
type
up
top
with
which
is
din.
Error
then
stood
error.
A
Error
I
didn't
want
to
type
it
out.
It
didn't
fail
in
the
slide,
so
just
in
there
we
need
to
box
it
so
I'm
going
to
turn
into
a
pointer
because
it's
async
code
we
need
to
add
a
send
bound.
We
also
need
to
add
a
sync
bound,
unfortunately,
and
we
need
to
make
sure
it
doesn't
borrow,
so
it
needs
to
be
a
static
lifetime,
all
right,
that's
pretty
verbose
and
if
you're
new
to
rust
or
need
to
async
rest
you're,
like
whoa
I,
need
to
type
that
out
every
single
time.
A
It's
like
yeah
or
reuse
it
somehow,
but
it's
not
built-in.
So
that's
not
great
so
challenges.
Yes,
okay
fix
the
slide,
catch
all
exceptions.
That's
that's!
That's
one
challenge
right!
Next
challenge:
okay,
wrapping,
alright,
so
yeah
like
I,
said
earlier
as
we
need.
We
need
this
little
this
little
thing
here
at
the
end,
okay
of
type
unit,
and
that's
not
great
when
we're
like
writing,
like
infallible
code
code,
that
doesn't
return
results.
The
the
return
type
is
always
unit
and
I
was
like
assume
that
is
unit,
so
we
don't
need
to
write
it
out.
A
A
So
you
know
a
one-liner
might
become
like
a
two
liner
for
sure
and
like
in
this
case
we
have
a
method,
that's
actually
supposed
to
be
like
two
lines,
but
we
need
to
add
that
okay
of
that
thing,
at
the
end,
it's
not
super,
and
so
another
one
is
okay.
Wrapping.
That's
that's
a
bit
of
a
challenge
these
days.
It's
it's
a
little
work
there.
So
finally
is
exception
contacts.
A
So
in
this
case,
if
we
have
a
panic,
Kotick
and
panic,
you
know,
for
example,
a
function
man
just
panics
with
oops,
and
when
you
run
this,
it
will
look
something
like
this.
You
know
it
says
thread
man,
panic
that
oops
source
may
in
our
ass
line,
six
in
there
or
whatever
the
sides.
I,
don't
know
what
it's
called
and
then
then
we
get
a
back-trace,
a
list
of
reasons
how
we
got
there.
A
A
It
doesn't
panic,
it
might
look
something
like
this.
It's
like,
oh,
we
got
an
error,
socket,
hang
out
cool.
Did
this
happen
when
we
had
like
an
incoming
request?
Did
this
happen
when
we
had
like
an
outgoing
requests?
Where
is
this
happening
right?
So
yeah?
It's
not
super.
So
that's
not
a
challenge
era
context.
So
in
the
errors
of
tomorrow.
What
would
be
nice
is
if
we
could
get
rid
of
this,
if
we
can
also
like
get
rid
of
this.
A
A
way
to
do
this
might
be
to
have
a
type
of
stood
error
exception,
but
we
don't.
Instead,
what
we're
proposing
is
throws
right.
So
we
add
a
little
keyword
which
removes
the
need
for
okay
wrapping,
which
allows
you
to
use,
throw
which
we're
not
showing
here
inside
the
function
body
to
propagate
errors.
Question
mark
keeps
on
working,
but
we
get
rid
of
the
okay
wrapping.
A
A
A
Whoops,
you
can't!
Well,
you
really
would
want
is
if
this
was
possible
and
we
have
a
little
gist
somewhere.
I
hacked
something
together
with
like
try
functions
in
the
block
and
like
proc
macros,
to
make
this
work.
It's
not
usable
this
really
someone!
Someone
should
just
like
build
that
so
yeah.
If
you're
looking
for
side
projects,
please
do
anyway
what
we
can
do.
So
we
come
to
the
throws
thing.
A
What
we
can
do
today
is
using
arrow
contacts,
so
the
in
failure
there's
a
thing
called
result:
X,
which
allows
you
to
add
context
to
an
error
which
looks
kind
of
like
this.
So
say
our
error,
dot
context.
Whew
wait
did
that
mess
around
a
wait
and
question
mark
no
turfy
orderings
exactly
right
here,
but
the
idea
is,
you
say,
doc,
context
on
your
result,
type
and
I
new
add
a
little
message
like
hey
we're,
trying
to
get
a
cat
from
the
API.
A
But
what
we're
doing
here
is
we're
using
it
at
the
time
of
our.
What
do
we
call
it,
but,
but
but
at
the
time
that
we're
calling
it
what
we
really
want
is
like
sorta
inside
of
the
function,
definition
inside
the
function
body
so
yeah,
it
should
actually
part
of
Kali
it'd
be
nicer
if
that
was
like
there
yeah
anyway
Eric
context
tomorrow.
What
can
we
do
here?
Is
now
imagine
the
little
get
cat
function.
We
would
probably
define
it
something
like
this.
Where
you
say
hey,
it
returns
a
string.
A
It's
called
get
cat,
it's
an
async
function
inside
of
it
we're
gonna
call
an
HTTP
client.
This
case
we're
using
Cerf,
give
it
a
little
URL
we
say,
get
something
from
the
API
gives
us
back
a
cat's
truck
that
we're
like
destructuring
into
just
the
name
value,
because
that's
the
only
thing
we
care
about
and
we
await
it
now,
look
at
this
function.
It's
like,
if
we're
wondering
like
what
does
this
do
then.
Actually
it's
pretty
easy
to
see,
because
we
have
a
little
comment
up
there.