►
From YouTube: Representing types in rustc
Description
This discussion covers how types are represented in rustc. It discusses the `Ty` type, generics and substitution, and type folding.
The Dropbox paper document that is being shared in the video can be found here:
https://paper.dropbox.com/doc/Ty-lecture--Ab8REO0WfNUvsZSb3L~DliFvAg-8hOUpAEhOvoBQC5EYXKJM
A
A
Yes,
okay,
so
hi
everybody
thanks
for
showing
up
so
yeah
I
wanted
to
talk
today
about
the
the
way
that
rusty
represents
types
and
I'm
curious
for
those
of
you
who
are
here
have
any
of
you
written
code
and
rusty
before
the
used
types
I
know
Santiago,
you
did
a
little
bit.
At
least
you
may
not
know
you
did.
A
Are
we
all
starting
from
scratch?
Okay,
awesome,
so
I'm,
probably
through
in
terms
that
you
don't
know
we'll
come
across
them,
feel
free
to
stop
me.
Let's
start
with
the
kind
of
basic
thing
when
I
talk
about
how
rusty
represents
types,
there's
actually
a
lot
of
types,
neck
planner,
and
if
you
just
look
I'm
talking
sort
of
around
this,
this
type,
we
call
T.
Why
I
mean
you
made
it
short,
because
you
know
we
type
it
a
lot
and
if
you
just
look
for
like
things
name,
T
Y
and
the
compiler.
A
It's
kind
of
our
ast
there's
a
couple
stages,
but
it
basically
represents
the
syntax
that
the
user
wrote
ready
so
the
result
of
parsing
and
after
some
amount
of
G,
sugaring
and
so
on,
and
it
has
a
representation
of
types,
but
that
really
represents
the
syntax
that
the
user
wrote.
So
exactly
what
did
they
write
to
represent
that
type
and
one
way
I
think
they
try
to
explain
the
difference
of
between
that
and
the
rusty
ties
that
we're
gonna
focus
on
is
looking
at
like
look
at
this
function,
for
example,
here
I
have
this
type?
A
U
32,
and
it
appears
twice
right,
but
we
know
that
that's
in
some
sense
the
same
type.
It
takes
an
argument
and
returns
an
argument
of
the
same
type,
but
from
the
point
of
view
of
the
here,
there
would
be
two
distinct
type
instances,
because
these
are
occurring
in
two
different
places
in
the
program
they
have
two
different
spans
so
like
two
different
locations
and
so
on
right
and
there
might
be
information.
That's
left
out
like
this
type
ampersand.
U
32
reference
to?
U
32!
It's
kind
of
incomplete
right
in
the
full,
rust
compiler!
A
It's
more
the
abstract
notion
of
the
type
itself
right.
So
so
this
is
the
title
saying
that
it
describes
the
semantics
of
the
type
in
this
sense,
and
you
can
actually
you
know,
click
on
it
and
see
how
it's
defined.
It's
actually
a
type
alias
and
we're
gonna
get
into
this
lifetime,
but
for
now
I
want
to
just
sort
of
ignore
it,
and
you
see
that
a
type
is
a
reference
to
a
structure
creatively
called
ty
s.
A
A
I'll
come
back
to
that
we're
passing
around
references
or
pointers
to
these
strokes,
and
this
is
the
actual
fields
of
the
type
there's
three
things
here:
the
one
that
matters
most
and
that
we'll
spend
most
of
our
time
on
is
the
sty
for
structured
type,
I,
guess
and
the
other
two,
the
flags
and
the
outer
exclusive
binder
I.
Don't
know
if
we'll
talk
about
those,
but
they
basically
summarize
they're
kind
of
convenient
hacks
for
efficiency,
but
summarize
information
about
the
type
that
we
might
like
to
know
so
I
might
come
back
to
it.
A
A
This
most
of
the
time
you
will
little
there
writing
code
sort
of
like
this,
that
extracts
out
this
sty
field
and
matches
on
it
and
why
do
I
say
match,
because
what
this
sty
a
field
stores
is
something
called
a
type
kind,
and
this
is
kind
if
you're
familiar
with,
like
Haskell
terminology
and
their
functional
programming,
that
that's
sort
of
not
nomenclature.
This
is
not
that
sort
of
kind.
This
is
just
the
kinds
of
types
that
we
have.
That's
what
it
means
like
the
different
sort
sorts.
A
So
it's
all
the
different
variants
there
could
be
boolean,
's
characters.
You
know
this
should
look
kind
of
familiar
too.
These
are
like
the
rust
type
system.
Written
out.
Some
of
them
might
be
a
little
surprising
right,
so
boolean
is
character,
is
integers.
If
you
go
ahead
and
click
on
int,
I
you'll
see
that
it's
like
all
the
different
things
that
you
might
expect.
A
A
And
you
can
see
that
it
basically
means
a
struct,
an
enum
or
a
Union.
All
of
those
are
represented
as
the
same
variant
for
us,
because
they're
kind
of
all
variations
on
a
theme-
it's
basically
a
user
defined
type
in
some
sense
and
we'll
come
back
to
this-
the
details
of
what's
in
here,
but
but
this
would
represent
a
reference
to
a
struck
like
back
of
you
32
or
something
that
would
be
an
ADT
so
for
in
East.
A
Corresponds
to
these
external
that
are
like
experimental
stir
is
the
type
stirred
so
when
you
have
ampersand
stir,
for
example.
This
is
the
stir
of
that.
An
array
is
this:
you
kind
of
see
that
each
case
of
the
reston
like
where
the
rest
syntax
has
a
type
there's
a
corresponding
very
into
raw
pointers.
One
that's
kind
of
interesting
is
ref.
These
stand
for
safe
references
and
it
might
be
episode,
mute
or
neighbor
sanity,
and
they
have
some
parts
to
them.
This
is
the
type
of
the
reference
references.
A
A
Okay,
so
there's
a
whole
family
of
like
related
types
that
are,
in
my
mind,
groups
together,
that
kind
of
represent
different
parts
of
the
semantics
of
the
type,
and
we
kind
of
saw
that
already
there's
stuff
like
you
and
tie
in
in
tie
but
ADT
death,
we'll
come
back
to
that
one
sucks
tref
tie
const
or
region.
So
we'll
see
some
of
these
and
I
kind
of
plan
to
talk
a
little
bit
about
them,
but
but
they're
all
kind
of
parts
of
the
type
in
the
end
of
the
day.
A
So
I
mentioned
this
when
we
were
talking
about
the
definition
of
tie.
I
said
there
was
a
lifetime
TCX
we'll
get
into
more
detail
about
what
that
is,
but
I
just
want
to
talk
about
where
these
types
live
and
how
they're
handled
right
for
a
little
bit
so
types
in
Russy
are
allocated
from
a
global
memory
pool
if
you're,
if
you're
familiar
with
the
term
arena,
we
use
an
arena
and
what
it
means
is
basically,
at
the
beginning
of
compilation
we
make
a
buffer
and
each
time
we
need
to
allocate
a
type.
A
We
kind
of
use
some
of
that
memory.
Buffer
and
if
we
run
out
of
space,
we
get
another
one
and
the
lifetime
of
that
buffer.
That's
what
this
TC
X
is
talking
about.
So
the
idea
is
that
when
we
finish
copulation
we're
gonna,
take
that
buffer
and
just
free
the
whole
thing
really
fast
and
therefore
any
references,
any
types
that
we
allocated
from
that
memory
buffer
are
invalid,
so
they're
they're
tied
to
the
lifetime
of
that
buffer
and
that's
what
this
TC
X
is,
is
basically
telling
us.
A
So
that's
called
well,
that's
called
a
rena
allocation
and
then
we
further
you
look
canonicalization
step.
So
the
idea
is
that
we
don't
just
each
time
you
want
to
construct
the
type
we
don't
just
naively
allocate
from
the
buffer,
but
we
look
and
see.
Have
you
already
constructed
this
type
once
before
and
if
so,
we'll
give
you
the
same
pointer
that
that
you
had
before
and
other
times
otherwise
we'll
make
a
fresh
pointer
and
so
that
we're
interning
them?
A
And
that
means
that
actually,
if
you
want
to
know
if
two
types
are
exactly
the
same
and
they're
allocated
from
this
arena,
all
you
have
to
do
is
compare
the
pointers
which
is
efficient
right
and
you
can
actually
see
that.
So
the
tie
s
struct
it
represents
types
is
only
ever
allocated.
We
never
can
set
up
so
that
you
never
construct
them
just
on
the
stack
right.
A
A
This
is
that
buffer
I
was
talking
about
I'll,
get
things
from
the
buffer,
and
that
has
a
bunch
of
hash
maps,
and
these
are
how
we
make
things
unique
right
and
we
want
to
in
turn
a
title.
For
example,
we
look
in
the
hash
map
to
see.
Is
there
already?
You
have
some
tie
s
that
represents
the
type
and
you
look
in
the
hash
map
to
sees.
Do
we
already
have
that
a
pointer
to
that
exact
is,
and
if
so,
we're
going
to
return?
It.
C
So
the
existing
documentation
mentioned
that
there
are
two
types
of
arenas,
the
global
and
innermost,
and
that
the
innermost
is
used
or
like
local,
when
you're
inferring,
like
a
specific
type,
I
assume
that
the
global
arena
is
allocated
at
the
beginning
of
compilation
and
the
local
arena
is
done
for
each
type.
Difference.
Yeah.
A
B
A
It
is
sometimes
kind
of
in
one
of
these
local
arenas
and
sometimes
not,
but
it
well.
It
will
kind
of
pick
which
of
the
arenas
to
use
based
on
the
type
that
you're
in
in
turning
them.
So
when
you
have
a
given
type
you'll
say:
oh
this
one
has
some
state
that
is
local
to
entrance
I'll
put
it
in
the
local
arena
or
it
doesn't
and
we'll
come
back
to
that
all
right.
So
let's
talk
about
generics.
A
A
So
in
this
example,
there
would
be
at
least
two
def
IDs,
actually
more,
but
at
least
two
all
right,
so
we
would
have
one
def
ID.
That
is
just
the
DEF
idea
of
this
struct
definition
as
a
whole,
and
we
would
have
one
def
ID,
for
example,
for
the
type
parameter
T.
We
would
also
have
one
for
the
field.
We
would
not
have
a
def
ID
for
this
u32
here.
That's
because
that's
not
a
definition.
That's
a
reference
to
the
type!
U
32,
but
we're
not
defining
to
take
you
32
here.
A
So
I'm
gonna
use
the
term
def
ID
a
lot,
but
I
wanted
to
kind
of
clarify
what
it
is.
It's
basically
an
identifier.
It's
an
integer
that
that
identifies
something
that
we
define
somewhere,
it's
an
integer.
It
happens
to
map.
We
have
an
internal
map.
They
can
go
from
the
DEF
ID
to
what's
called
a
def
path.
A
The
DEF
path
is
kind
of
what
it
sounds
like
it's
a
path
through
the
it's
basically
like
a
module
path,
holding
a
little
more
rich,
they
might
say,
like
create
Foom
I,
struck
and
identifies
this
particular
definition.
Uniquely,
it's
a
little
different
than
a
model
path
you
can
actually
use
in
rust
because
you
know
it
might,
for
example,
include
like
the
type
parameter.
T
has
a
path
like
this
and
you
could
not
I
mean
the
type
parameter
T
from
rust
and
nonsense.
A
A
So
that's
that's
what
the
def
idea
of
a
struct
is,
but
now
when
we
have
an
actual
type
like
when
we
use
my
struct
as
the
type
it's
never
by
itself,
it's
not
just
my
structure.
It
also
has,
together
with
it,
a
set
of
type
parameters
right
the
value
so
in
this
basically
the
value
for
T,
and
if
you
look
at
the
definition
of
a
DT-
and
we
saw
earlier,
you.
B
D
A
You
still
see
my
Dropbox
paper
here.
Not
only
did
some
dragging
so
anyway.
Here's
the
two
parts.
Actually,
so
what
these
two
parts
are
the
ADT
def,
that's
like
algebraic.
A
type
definition
basically
specifies
the
struct,
but
without
the
type
parameters,
it's
essentially
a
def
ID,
there's
a
one
to
one
relationship
between
these
and
DEF
IDs.
But
what
it
actually
is
is
this
an
intern
struct
interned
in
the
same
sense
as
the
types
of
interns
are
allocated
in
the
global
arena,
and
here
we
have
a
reference
to
it.
A
You
can
the
t
CX
lifetime
is
kind,
the
tell-tale
something
has
that
lifetime
it's
it
must
be
allocated
in
the
arena,
because
that's
what
that's
for-
and
it
has
some
helper
methods
and
some
other
things.
So
when
you
have
one
of
these
struts,
you
can
ask
things
like.
Is
this
a
whatever
a
lot
of
annoying
stuff?
Let
me
scroll
up
actually,
oh
wait.
What.
A
Okay,
that
link
is
wrong.
Sorry,
what
that
ADT
death
does
so
I
mentioned
that
here
we're
we
were
looking
at
us
struct,
but
I
mentioned
at
some
point
that
the
ADT
type
is
used
for
structs
enums
am
unions,
so
we
kind
of
in
the
compiler
have
a
sort
of
unified
view
of
things
you
can
think
of
a
struct
as
being
a
lot
like
a
one
variant
email.
A
You
know
that's
just
like
an
enum.
It
has
fields,
it's
just
that
there's
only
one
possibility,
and
so
the
ADT
deaf
and
cup
lets
you
view
all
of
those
distinct
things
more
uniformly.
So
it
has
a
def
ID,
but
then
it
has
a
list
of
variants
and
for
our
struct
this
will
always
be
of
length
one
and
for
each
one
within
the
variant.
A
D
A
A
A
So
these
are
the
replacements
for
these
generic
types,
and
actually
it's
not
just
types
because
it
could
be
reached,
it
could
be
lifetimes
or
regions,
but
for
now
we'll
just
talk
about
so
in
this
case
it
would
be
a
list
like
you
32,
and
if
you
follow
through
this
definition,
you'll
see
it's
got
a
certain
amount
of
complexity.
It's
an
internal
sub
switches,
an
alias
for
a
list
of
a
kind,
a
kind
is
either
a
type
or
a
region
defined
in
a
weird
way,
but
this
list
what
is
list
so
a
list?
A
B
B
A
A
Okay,
these
could
be
two
different
lists
list
a
and
this
B,
but
if
we
and
now,
if
we
want
to
compare
them
for
equality,
because
we
know
that
they're
the
complete
list-
and
we
we
in
turned
it
and
hashed
it-
and
we
have
these
unique
pointers,
we
can
actually
compare
the
pointers
for
equality.
We
don't
have
to
dive
in
and
iterate
over
the
contents.
But
if
we
had
just
slices,
I
might
take
a
sub
slice
of
a
I.
A
May
have
a
sub
slice
of
a
and
the
full
list.
B
and
I
might
want
to
compare
them
for
equality
and,
if
I
just
compared
the
pointers,
it
would
tell
me
that
they're
unequal
but
actually
they're
equivalent.
So
that's
why
we
use
this
other
type
because
it
can't
be
sub
sliced,
which
is
a
win,
because
we
can
have
more
efficient
pointer
operations,
but
also
a
loss,
because
we
cancel,
which
means
that
if
we
want
to
have
a
sub
list,
you
have
to
like
allocated.
C
Slightly
off-topic
question:
you
mentioned
that
the
compiler
of
ATT
represents
like
a
global
view
of,
is
that
reflected
in
the
parts
for
grammar.
Since
then,
it
distinguishes
between
them
and
then
generates
like
this
kind
of
structure.
Or
is
it
the
other
way
around
the
grammar?
Just
it's
okay,
I
hope
after
we
do.
A
So
in
rust
grammar
we
treat
those
three
things
very
differently
all
right
and
if
you
look
at
the
here,
this
is
another
difference
between
here
types
and
well,
not
quite,
but
it's
difference
between
the
here
and
the
later
phases
in
the
compiler
right.
The
here
is
more
like
this
is
a
struct
definition.
This
is
an
enum
definition.
A
A
Okay,
so
I
want
to
talk
a
bit
about
this.
A
little
more
I
talked
about.
I
said
that
these
are
the
substitutions
if
you're
familiar
with
like
play
the
type
systems
that
might
be
familiar
to
you,
but
if
not
it's
worth
discussing
so
the
we
have
a
notion
of
sort
of
substituted
and
unsubstituted
generics.
A
So
here
I
talked
about
the
type
you
32
as
the
value
for
T,
but
inside
the
definition
of
my
struct
I
might
reference
T
directly
right
and
when
I'm
inside
this
definition,
I
don't
really
know
what
T
is
I'd
have
to
treat
it
like
it's
a
placeholder
right
for
any
type.
So
we
need
a
way
just
to
talk
about
these,
these
generic
types
that
are
not
yet
known,
and
there
is
indeed
a
variant
for
that.
So,
if
you
go
to
this,
this
list
of
variants
called
kind
yep.
A
B
A
Xy
and
z
are
all
in
scope.
So
what
will
happen?
Is
that
exercise
index
0
Y
has
index
1
and
Z
has
indexed
two,
even
though
it's
the
first
one
in
this
list.
So
the
list
of
when
you,
when
you
actually
look
at
the
generics
of
a
particular
item
like
the
generic
things
that
are
generic
parameters,
defined
on
a
particular
item
like
to
this
method,
you'll.
A
A
Well,
so,
when
we're
inside
the
definition
will
actually
just
work
with
these
parameters,
types
as
if
they
were
real
types
right,
we'll
treat
them
like
any
other
type.
But
when
we
come
well
when
we
want
to
pull
something
that
was
inside
a
definition
out
and
use
it
from
the
outside,
we
have
to
do
what's
called
a
substitution.
So
let
me
give
an
example,
so
imagine
that
we
had
this
struct
foo
when
it
has
a
field
of
type
Becker
day
and.
B
A
A
That's
because
it's
a
reference
to
a
vector
and
that's
the
ADT
death
is
vector,
and
then
the
list
of
substituted
types
is
going
to
be
the
first
parameter,
which
corresponds
to
a
right,
but
now
imagine
that
we
were
accessing
that
field
from
well
actually
even
from
here.
But
let's,
let's
make
a
separate
example,
make
a
little
here.
A
Imagine
we
were
accessing,
we
want
to
know
what
we're
trying
to
figure
out
is:
what
is
the
type
of
this
expression,
food
X,
and
if
we
just
read
the
type
of
that
field,
we
would
get
sort
of
that
directly
and
that
doesn't
make
sense,
because
this
parameter
isn't
even
we
don't
have
any
generic
parameters
in
our
current
scope,
it's
like
a
namespacing
violation.
So
what
we
want
to
do
is
we
want
to
take
the
type
of
foo
you
see
here.
A
The
type
of
foo
is
gonna,
be
this,
which
is
to
say
it
has
a
slice
with
u-32
as
the
substitution,
and
we
want
to
replace
the
corresponding
indices.
Actually,
foo
had
two
arguments,
so
let's
add
that
in
there.
So
basically
we
want
to
walk
down
this.
We
want
to
get
the
type
of
the
field
like
from
here:
walk
down
and
each
place.
We
see
a
parameter,
take
the
index
index
into
that
list
of
substitutions
and
replace
it
all
right.
A
B
A
Can
say
you
can
use
this
type
of
query
to
say,
give
me
the
type
of
this
field
and
that's
how
I
would
actually
get
this
type,
and
it's
gonna.
That
type
of
query
is
quite
flexible.
You
can
use
it
on
any
any
def
ID
that
has
a
type
associated
with
it.
So,
for
example,
I
could
even
add
I
could
ask
for
what
is
the
type
of
the
struct,
and
that
would
give
me.
A
It
kind
of
gives
me
the
like
identity
type
of
the
struct.
That's
just
by
definition.
You
just
decided
it's
just
convenient,
as
it
happens
that
you
can
ask
a
struct
for
its
type
and
you'll
get
back
this
identity
sort
of
the
internal
view
of
the
declarations
those
week
and
so
forth.
But
one
of
the
things
you
can
ask
for
the
type
of
is
a
field
and
in
all
cases,
when
you
do
that,
you
get
this
view
with
using.
A
A
A
A
So
so
what
is
happening
here
so
this
is
this
is
not
two
of
what
this
code
is
actually
doing
is
converting,
as
it
happens
from
the
here,
the
syntax
of
the
type
to
the
semantic
view
of
the
type.
So
it's
kind
of
doing
this
translation-
that's
not
so
important,
but
suffice
to
say
it
gets
somehow
a
list
of
substitutions
that
are
to
be
applied,
and
then
you
can
see
it
calls
type
of
just
like
I
said
for
a
given
def
ID
and
that's
going
to
give
us
the
self
view,
and
then
it
applies.
A
A
You
want
a
sort
of
map
operation
where
you
can
find
all
the
types
that
appear
inside
of
some
thing
and
the
compiler
and
substitute
them
and
change
their
view,
and
we
have
a.
We
have
a
treat
for
that.
It's
called
type
foldable,
even
though
this
is
sort
of
a
map
we
call
it
type.
Foldable
feels
like
the
right
name,
but
what
it
means
is
it's
any
type
that
implements
type
foldable
is
basically
something
that
embeds
types
or
regions
and
it
allows
you
to
walk
itself
and
translate
them
right.
A
So
let
me
jump
back
to
my
anything.
So
this
is
the
type
foldable
section.
So
the
idea
is,
there's
actually
two
parts
to
the
way
type
foldable
words
there's
something
called
a
type
folder
and
the
type
folder
is
defines
what
you
want
to
do
to
every
type.
It's
like
the
closure
that
you
might
give
to
a
map.
If
you
were
using.
A
A
A
And
this
the
definition
of
map
is
sort
of
analogous
to
the
type
fool.
So
the
folder
has
a
few
methods.
You
can
see
here
too
many
there's
kind
of
one
for
every
core
sort
of
thing.
It's
basically
every
kind
of
generic
parameter
that
rusts
the
language
defines
and
some
that
it
doesn't
defined
yet
so
there
there
are
types
regions
which
is
another
name
for
a
lifetime
and
constants
for
when
we
support
constant
arcs.
A
That
just
looks
like
the
place:
I
want
to
click.
The
actual
folder
is
just
going
to
be
doing
that
indexing
that
I
talked
about.
You
can
actually
see
it
here,
so
we
define
the
folder
here.
It's
a
struct,
it's
called
a
sub
stoller.
We
we
call
it
a
fold
width
which
means
process
might
basically
the
map
operation
process
myself
and.
A
And
invoke
the
folder
methods
as
appropriate
and
if
you
skim
down
to
like
fold
tie
this
is
the
method
that
that
process
is
each
title.
You
see
that
it
looks.
It
says
AHA.
This
is
a
parameter
type
in
that
case,
I'm,
going
to
replace
it
with
something
from
the
list
of
substitutions
and
otherwise
I'm
going
to
recursively
process
the
typo.
So
I'll
come
back
to
this
in
a
second.
B
A
The
replacing
it
this
is
calling
this
tie
for
per
a
method,
and
all
that
does
is
to
basically
index
into
the
list
of
substitutions
with
the
index
of
the
parameter.
The
rest
of
this
stuff
is
basically
all
error
recovery,
so
that,
in
case
something
goes
wrong.
We
get
a
nice
message
that
can
help
us
figure
out
what
the
heck
happened.
B
A
A
This
is
what
a
typical
type
foldable
might
look
like
and
actually
there's
a
shorthand
that
we
can
use
to
sort
of
derive
it
so
likes.
Imagine
I
have
a
struct.
It
has
a
def
idea
of
something
and
of
type
in
it
and
I
want
to
make
it
tight
foldable,
and
that
would
mean
that
if
I
had
a
my
struct
instance,
I
would
be
able
to
do
my
struct
ops,
for
example,
and
apply
a
substitution
I.
There's
a
whole
bunch
of
stuff
and
I
can
find
out.
A
It
just
works
on
any
type
foldable
thing,
so
it
would
be
compatible
with
all
that.
What
I
really
do
is
I
just
define
actually
there's
two
methods:
I
left
off,
one
of
them
I
defined
this
Super
fold
with
and
we're
kind
of
emulating
an
oo
set
up
to
certain
extent.
A
So
there's
a
fold
with
the
actual
trait
has
a
fold
width
method
and
the
default
thing
that
it
does
I'm
not
mistaken
is
to
call
super
fold
with
immediately
and
so
you're
normally
you're
just
defined
super
fold
with,
but
you
don't
normally
invoke
it
most
of
the
time
and
what
it
was
super
fold
with
will
do
is
recursively
descend
through
your
fields
and
process
and
recursively
process
them.
A
So
this
this
split
gives
you
some
ability
to
say
like
maybe
I
want
to
do
something
at
the
struct
level,
like
maybe
I
can
replace
the
entire
struct
without
substituting
its
fields
individually,
in
which
case
I.
That's
what
fold
with
the
top-level
method
would
do,
but
otherwise
the
Super
fold
with
says
no
I
just
want
to
replace
I
want
to
go
and
replace
my
fields,
but
the
structure
I
just
want
to
build
back
up
from
the
replaced
version
of
each
field
and
then
for
almost
all
types.
A
These
are
the
same
because
you
don't
want
to
intercept
at
the
top
level.
The
main
difference,
the
only
real
case
where
we
use
the
super
is
types
and
regions
and
basically
the
things
that
the
folder
itself
operates
on,
because
now
the
folder
gets
a
chance
to
intercept
and
replaced
the
type
as
a
whole,
as
in
the
case
of
substitutions
or
as
we
also
saw
in
substations,
it
doesn't
want
to
replace
the
type
as
a
whole.
They
can
go
to
send
into
the
type
and
replace
its
little
pieces.
A
A
Backpack
of
X
this
would
be
like
a
DT
effect,
VDP
Beck,
koream
X,
let's
say
whatever
the
index
of
X
is,
and
so
now,
when
I
substitute
I
have.
This
is
actually
my
entire
type,
and
there
is
no
substitution
to
happen
here,
but
I
want
to
recursively
look
at
this
inner
type.
Still,
no
substitution,
recursively!
Look
at
this
inner
type!
Ok,
the
minister
I'm
gonna,
replace
this
one
with
you
32
or
whatever,
and
then
I'm
gonna
build
the
rest
around
it,
so
that
I
wind
up
with
this.
A
Is
this
I
was
so
this
this
this
file,
structural
imposed
on
our
risk,
happens
to
contain
a
lot
of
type
foldable
definitions,
so
you
can
kind
of
see
how
they
look
sometimes
like
this
one
ADT
def.
This
is
actually
interesting.
Example.
You
can
see
that
fold
with
doesn't
do
anything
at
all.
It's
just
the
identity
function
and
the
reason
for
that
is
essentially,
if
the
intuition
you
should
think
of
is
if
I
were
substituting
things
to
go
from
the
self
view
to
the
outside
view.
A
What
I
want
to
replace
types
that
appear
inside
of
here
or
not
and
an
ADT
def,
is
basically
just
the
name
like
we
said
that
logically,
it
represents
the
name
of
the
struct
like
Veck,
and
you
never
change
that
when
you
substituting,
but
the
vac
is
always
affect
it's
only
these.
So
that's
why
it
doesn't
get
changed
as
you
fold
it,
then
we
have
some
things
like
this
will
fold
a
tuple
of
other
foldable
things
and
it
just
recursively
recurse
is
down
and
these
macros.
A
These
are
what
I
wanted
to
refer
to
make
to
highlight.
So,
for
technical
crappy
reasons
we
can't
use
derive
in
the
compiler
itself,
yet
this
is
because
of
the
bootstrapping
cycle.
We
are
I,
think
actually
maybe
close
to
solving
that
I'm,
not
sure,
but
so
we
end
up
writing
these
macro
rules
definitions.
Instead,
they
are
sort
of
like
derive,
and
this
is
one
that
handles
the
pain
of
implementing
type
foldable
for
some
kind
of
enum.
A
If
it's
a
Sun,
recursively
Boston
all
that
stuff
and
one
annoying
thing,
is
that
often
we
don't
get
all
the
edge
cases
right
when
we
write
these
macro
rules,
because
we're
lazy
so
like
enums
work
for
parenthesized
lists
of
fields,
but
they
might
not
work
for
named
items
with
main
fields
and
so
sometimes
you'll
see
manual
impulse
that
don't
seem
like
it
seems
like
you
should
be
able
to
derive
it,
but
you
can't
because
it
just
doesn't
quite
fit,
but
the
macro
is
made
to
do
and
that's
annoying.
But
here's.
D
A
A
Okay,
so
all
these
types
I
mentioned
that
if
there
is,
if
nothing
needs
to
happen
during
substitution,
if
you
just
want
to
copy
it
over
that's
an
easy
case,
and
all
of
these
types
are
examples
where
there's
really
no
self
substitution
to
be
done.
That's
why
this
clone
thing
just
says
just
clone
it.
It's.
B
A
C
C
A
A
They
might
have
written
like
back
of
today
or
something,
and
that
would
be
just
wrong,
but
what
should
have
happened
is
that
we
should
have
intercepted
that
earlier,
when
we
were
translating
from
syntax
to
semantics
and
substituted
dummy,
something
such
that
it
made
sense
and
we
actually
have
a
special
type
called
error.
For
example,
that
is,
would
be
used
in
situations
like
this,
where
it's
like
I
there
was
a
bug.
A
They
usually
did
something
dumb
and
I'm
just
putting
this
in
them,
and
the
idea
for
that
is
that
then
you
should
suppress
downstream
yours
like
if
you
see
an
error,
you
don't
have
to
report,
you
can
just
pretend
it
was.
Everything
was
good
because
but
right
so
that
should
be
handled
earlier.
So
if
you
see
it
at
this
late
stage,
then
somebody
mixed
up
something.
That's
and.
C
A
The
Impala
is
an
interesting
case
because
it's
an
outside
view
from
the
point
of
view
of
the
fields
of
the
struct
actually,
but
an
inside
view
from
these
generics
here
right.
It's.
Why
I
give
them
different
letters
to
emphasize
that?
Indeed,
although
there
is
a
parameter
with
index,
zero
in
scope
in
both
places,
it's
logically
a
distinct
type,
and
so
a
common
failure
is
to
forget
to
do
substitution.
And
if
you
do
that,
sometimes
they
might
go
unnoticed
for
a
while,
because
you
just
happen
to
have
the
same
set
of
things
in
scope.
A
A
D
You
find
something:
could
you
clarify
when
you're
talking
about
the
type
foldable
and
pulls,
and
he
said
we
treat
abt
deaths
completely
opaquely,
so
when
I'm
confused
by
is
okay,
if
that
were
a
struct,
why
don't
we
recursing
to
all
of
its
fields
so.
A
A
You
don't
you
frankly
cut
into
this
there's
like
a
couple
of
different
directions
to
answer
it.
One
way
to
view
it
is
because
we
don't
and
what
we
do
instead
is
when
you
extract
the
type
of
the
field
you
you
substitute
it
then
alright.
So
I
guess
that
there
will
be
two
possible
options.
You
could
you
could
say
that
the
ADT
death
is
like
a
structural
description
of
the
field
of
the
fields
invariants,
and
so
in
that
case,
it's
not
just
a
name
of
the
struct.
A
It's
like
more,
like
here's,
the
data
of
the
struct,
and
you
would
want
to
substitute
it
then,
because
it
should
represent
the
view.
But
what
we
actually
say
is
that
it's
really
just
the
name
and
that
so
it
goes,
it
never
changes.
The
types
in
there
are
always
with
the
consistent
view
of
being
inside.
They
always
have
the
self
view
so
to
speak,
and
that
the
you
just
that
you
have
to
know
that
and
know
that
when
you
extract
them
out,
they
will
be.
A
You
need
to
apply
substitution,
there's
a
sort
of
deeper
reason
for
that
that
there's,
this
term
nominal
and
structural
type
systems
they're
like
where
this
is
a
nominal
type
system,
which
means
basically
that
exactly
this,
basically,
that
you
pass
around
you
reference
trucks
by
name
and
not
two
strokes
that
have
different
names,
even
if
they
have
the
same
fields,
are
distinct
strokes.
And
so,
when
you
take
that
approach
here
generally,
you
would
not
do
the
substitution
on
the
name
itself.
A
Instead,
you
will
I
guess
one
way
to
think
of
it
is
you
could
think
of
it
as
just
efficiency.
Also,
right,
like
the
only
thing
that
can
change
inside
a
Veck,
is
the
type
parameters
defined
on
the
Veck
right
like
if
we're
substituting.
If
we
have
some
effective
back
of
u-32
and
it
has
all
or
you
if
a
vector
type-
and
it
has
a
bunch
of
references
to
tea
all
throughout-
let's
say
a
whole
bunch
of
fields-
I
mean,
let
me
make
them
work
tying
it
to
vectors
may
be
confusing.
A
If
I
were
to
apply
the
substitution,
deeply
I
would
have
to
replace
the
T
in
all
of
those
fields
eagerly
every
time
but
it,
but
if
I
do
it
lazily
then
I
keep
my
struck
the
same
and
I
just
substitute
once
the
value
like
I
have
a
reference
somewhere
to
my
struct
of
a
so
some
other
generic,
a
and
I
substitute
that
to
my
structure,
be
I'm.
Only
changing
this
one
type
once
right,
and
it's
only
when
I
actually
pull
the
field
out
that
I.
That
I
would
have
to
do
any
work.