►
From YouTube: blitzerr closure upvar tys
Description
Discussing how to refactor the way closure upvar types are represented with @blitzerr.
C
C
B
B
C
So,
just
to
make
sure
we're
on
the
same
page
the
why
we're
doing
this
is
that
we're
not?
We
want
to
change
it
so
that,
in
order
to
figure
out
how
many
type
parameters
a
closure
type
has,
we
don't
have
to
know
how
many
things
it
captures,
because
we
want
to
figure
out
how
many
things
it
captures
during
type
checking
and
not
before
here
I
see
yeah.
C
The
reason
I
mean
that
lets
us
construct
closure
types
and
wait.
Now
this
is
sort
of
a
closure.
Type
is
sort
of
conceptually
a
struct
like
this,
and
so
we're
basically
talking
about
doing
is
changing
this
like
so
so
now.
You
still
have
this,
basically
all
the
same
information,
but
the
number
of
type
renders
it's
not
dependent,
and
the
number
of
our
parties
will
always
be
the
same,
but
the
arity
of
this
tuple
is
dependent,
but
you
think
it's
not
a
problem.
C
Struct
definition
rust
because,
like
these,
this
is
really
a
type
parameter
like
yeah,
so
one
of
the
things
I
was
saying:
I
think
we
can
maybe
just
cheap.
This
is
not
really
a
struct
and
a
compiler,
so
I
think
we
can
actually
cheat.
But
if
we
didn't
want
to
cheat
I
think
we
could
also
do
this,
that
is
to
say,
we
could
sort
of
change
it.
C
So
they've
had
a
single
field
of
type
tuple
and
then
everywhere
there
are
parts
in
the
compiler
which
refer
to
fields
of
the
closure
to
mean
the
up
bar,
so
might
be,
like
Clojure
dot,
zero
to
get
the
zero
or
not
one
to
get
the
zero
apart
and
they
would
become
closure
dot,
zero
dot
one
you
know
so
that
we
go
through
the
tuple
and
go
to
the
first
field
of
the
tuple
I
think
we
can
avoid
doing
that
and
if
we
can
I
would
at
least
for
the
first
round
prefer
to
do
so.
A
C
B
C
B
C
Well,
basically,
we
could,
you
could
start
by
leaving
this
part
as
it
is,
and
just
we
factor
this
to
be
up
for
people.
C
Okay,
I'm,
not
sure.
The
only
reason
I'm
hesitant
is
that
maybe
it's
not
so
bad
I
think
most
code
sort
of
doesn't
tear
like
it,
wouldn't
be
so
hard
to
introduce
this
field.
It's
mostly
I
think
the
mirror
there's
some
special
taste
code
in
the
borrow
checker,
especially
for
Diagnostics
it
tries
to
identify
access,
needs
to
up
bars
and
bad
code
would
have
to
be
adjusted
I'm,
not
so
bad
I.
C
A
B
C
C
Which
gives
which
basically
takes
the
so
split,
takes
the
list
of
type
parameters
and
breaks
it
up
into
categories
right.
The
closure
kind.
This
is
that
seek
a
upload,
your
signature
and
on
a
verbal
length
list
of
up
bars,
and
then
we
just
iterate
through
that
list
to
get
the
list,
then
of
all
the
upper
are
types
you
iterate
through
that
list
and
down
castes.
So
have
you
seen
this
type
kind
of
work.
B
C
C
C
C
It
checks.
It
says.
Yes,
this
is
basically
saying
see
us
must
be
a
function
type,
so
fun,
okay
and
then
it
extracts
the
signature
from
there
and
returned
it,
and
otherwise
he
points
and
we're
gonna
do
something
we
would
do
something
similar
like
here.
We
say,
match
up
our
minds,
not
sty,
and
you
would
expect
ID
to
pull.
C
C
B
C
So
actually
like
this
is
true
also
for
the
closure
sig.
So
you
can
see
here
there's
some
comments
that
says
only
usable
outside
of
an
inference
context,
and
we
enforce
that
by
taking
this,
as
it
happened
like
by
taking
it
using
some
lifetime
trip
sizing.
But
the
reason
for
that
is
because
of
this
problem
of
we
only
you
may
not
if
you're,
if
you
haven't
fully
completed
typing.
B
C
So
inference
is
where
we
figure
out
types
and
they're
not
explicitly
written.
The
way
it
basically
works
is
that
you
make
these
things
called
variables
represent
some
type,
not
yet
known
and
in
some
point
of
another
of
those
variables
get
bound,
which
means
that
basically,
we
assignment
number
valor
Knights
would
say
this
is
the
type
that
the
you
figured
out
the
type
now,
but
in
the
meantime
you
can
use
these
verbal,
so
you
might
make
a
variable.
C
C
Well,
it's
question
mark
X,
you
know
it's
something,
I
don't
know
yet,
but
then
somewhere
along
the
line
that
will
get
unified
or
bound
with
you
32
and
now
we
can
resolve
it
and
find
out
what
did
it
get
down
to
and
that's
that
right,
back
phase
that
you
modified.
That's
exactly
what
he
does.
Oh
those
two
and
takes
all
the
typer
won't
replaces
them
their
ultimate
value.
C
C
Right
so
basically,
this
method,
apartheid,
some
reason
I'm
talking
about
all
this
is
if
it's
getting
called
during
type
checking
before
we
have
inferred
everything
that
could
be
a
problem,
so
I
wanted
to
look
over
these
fall
sites
and
see
whether
whether
they
fall
into
that
like
where
they
happen
in
the
pipeline.
So
this
one
is
mere
construction
that
comes
way
after
ten
shipping.
That's
fine.
C
So
this
some
of
these
uses-
this
is
part
of
trait
and
type
check.
This
actually
occurs
during
type
checking,
although
it
occurs
very
lazy
to
type
checking
so
I
think
all
types
have
been
resolved
by
this
period,
but
there's
something
interesting
about
this,
which
is
that
a
lot
of
the
uses
of
up
far
ties
would
actually
be
fine
to
operate
on
a
tuple
like
what
this
is
doing.
This
particular
function
is
walking
down,
but
basically
examining
all
the
data
that's
inside
of
something
right,
so
if
you're
in
it
too.
C
C
No
matter
what
right,
so,
the
problem,
the
reason
that
the
infant
variable
causes
a
problem
for
the
current
signature
is
that
we
would
have
to
sort
of
open
up
the
to
bulletin
sense
and
we
have
to
know
what
it's
bound
to.
But
if,
if
we
just
have
something
that
says,
give
me
well
what
is
now
or
will
eventually
become
the
tuple
of
all
of
our
types
we
could
use
that
here
and
in
a
lot
of
other
places
yeah.
C
I
think
that
here
yeah
we
could
also
this
could
be
as
well
the
tuple
this
debug
info.
This
is
way
after
typing
friends
way
after
similarly,
this
all
this
all
this
code
comes
way
after
tightening
friends,
layout,
also
I,
believe
layout,
already
sort
of
so
so
layout
is
what
computes
like
what
fields
of
a
struct
occur
which
offset
and
so
on,
yeah.
B
C
And
you
can
see
here
that
layout
already
fails
if
it
encounters
the
type
inference,
Mayer,
ball
and
fog,
so
this
must
be
after
detecting
prints
as
well
about
that
now,
trait
selection.
This
is
a
little
bit
different,
but
this
is
another.
So
this
this
code
is
saying:
when
is
a
closure
copy
or
clone
and
a
closure?
Basically,
some
closure
type
C
implements
clone.
If
all
the
up
flower
types
are
cloneable,
but
we
could
again
use
the
tuple
type
right
today
we
sort
of
do
that,
but
we
could
instead
do
something
like.
C
A
C
What
you
know
like
well
forming
this
conditions,
so
if
you
have
types
they
have
criteria
for
them
to
be
valid,
but
like
maybe
this
something
like
this,
this
is
not
actually
true,
but
it
might
need
it
for
this
to
be
valid.
Okay,
hash
must
be
true,
I
think
the
actual
hash
set
does
not
require
this,
but
this
is
the
code
that
we
computed
if
they
do
and.
C
C
Don't
know
this
one's
a
little
tricky
because
pretty
printing
happens
at
any
time,
so
we
have
to,
like
you,
probably
have
to
adjust
this
code
to
be
to
account
for
the
possibility
that
it
doesn't
know
how
many
hours
it
has.
Yet.
The
point
where
we
are
pretty
printing
is
PPA
us,
it's
the
pretty
print
auxilary
horrible.
C
C
B
B
B
C
C
C
A
C
C
C
Let's
do
this:
let's
do
this
in
somewhat
smaller
steps.
Sorry,
what
I'm
doing
here
is
reviewing
my
kit,
mystery
I'm,
gonna
leave
this
comment
alone,
we'll
hold
off
on
editing
that
comment
until
we
actually
know
what
a
birth
you
doing,
but
what
I'm
thinking
is
what,
if
we
leave
everything
the
same
but
we'll
just
introduce
the
four
tuple
type
helper.
C
C
A
C
C
B
C
C
B
C
C
C
C
C
C
C
So
one
way
to
solve
that
is,
you
can
use
this
either
type
which
basically
it's
it's
kind
of
exactly
this.
To
be
honest,
it's
like
exactly
the
same
as
this
up
fire
subtype,
it's
just
an
enum
with
left
and
right
and
it
implements
iterator
if
left
and
right,
both
implement
iterator
and
it
does
whatever
dispatch
is
appropriately.
B
C
Okay,
so
now
that
code
is
all
building
but
we're
getting
errors
because
I
made
this
I
made
it
so
that
the
up
fart
eyes
helper
method
can
only
be
called
if
you
know
they
had
that
enduring
influence
which
right
it's
getting
us.
Some
compilation
errors
we're
about
to
see,
which
I
think
is
okay,
because
these
are
exactly
the
cases
where
you
can
try
to
use
the
tuple
type
instead,.
C
Drops
calculus
yeah.
So
if
you
look
at
this
code,
what
it's
doing
is
it's
going
through
each
of
the
upper
ties
and
for
each
man
it's
calling
trivial
drop
check
out,
lives,
okay,
so
what
I'm
doing
instead
is
I'm
calling
trivial
drop
check
out
lives
on
the
tuple
and
then
that
will
cause
it
to
be
the
rate
that
make
sense.
Yeah.
B
C
It
so
happened.
The
last
one
in
the
list
is
sort
of
the
lifetime
of
the
shortest,
like.
Basically,
the
lifetime
of
the
innermost
enclosing
inference
context
and
it's
kind
of
the
the
lifetime
of
types
that
you're
working
with
physically,
and
it
so
happens
that
those
functions
didn't
need
to
constrain
it
before
because
they
weren't
making
types.
So
when
you
make
a
new
type
that
gets
interns,
it
gets
stored
into
out
in
the
arena
and
it
gets
that
lifetime
the
shortest
one,
but
they
weren't
making
new
types.
But
now
we
are
so
I
had
indicate.
C
C
A
C
C
I'm
going
to
change
this,
so
I
think
I'm
gonna
have
just
looking
at
the
time.
I'm
gonna
have
to
go
soon,
but
what
I
was
thinking
is
once
we
get.
Hopefully
we
can
get
this
building
and
I'll
push
it
to
a
branch,
and
then
maybe
you
can
try
to
we'll
have
to
discuss
this.
She
Bella
sort
of
come
up
with
some
next
steps.
C
C
But
in
the
case
of
the
preprinting
code,
we
can't
do
that
because
we
get
invoked
from
a
debug
imple.
So
what
we
do
is
we
grab
the
type
context
from
we
use
like
thread-local
storage,
and
then
we
have
to
do
some
horrible
things
because
the
because
we
weren't
giving
it
as
a
type
parameter.
The
compiler
doesn't
really
know
like
what
is
lifetimes
over
and
so
forth.
It
doesn't
know
kind
of
what
its
full
type
is
it
so
we're
sort
of
doing
some
hacks
and
that's
what
I'm
trying
to
solve
here.
C
So
what
happens
is
this
this
tie
TLS,
which
says,
give
me
the
tight
context,
it's
in
scope
and
you
wind
up
having
to
give
it
a
closure
which
works
sort
of
for
any
lifetimes.
And
now
it's
getting
unhappy
because.
C
C
If
you
see
this
so
here
where
I
call
T
CX
dot
lift
what
that
does
is
actually
uses
a
little
bit
of
unsafe
code,
but
it
basically
checks
dynamically
that
the
data
that
we're
lifting
was
allocated
in
the
right
arena
and
it
will
return
none
if
not,
and
so
it
kind
of
lets
you
bridge
this,
where
a
compiler
doesn't
know
that
these
two
things
are
the
same.
This
kind
of
dynamically
checks
it
and
lets
you
assert
to
do
the
same
by
unwrapping.
C
C
C
More
or
less
everywhere
that
we
want
to
be
calling
it
I
think
all
the
rest
of
these
locations,
almost
with
one
exception,
this
yep,
so,
okay,
there's
all
the
rest
of
these
locations
that
call
up
for
our
ties
are
fine,
except
for
two
things,
and
by
fine
I
mean
they
come
after
typing
things,
I
see,
except
for
two
things.
First,
some
of
them
are
calling
on
a
generator
and
I
didn't
convert
I,
converted
the
closure,
but
not
the
generating.
So
that
needs
to
be
changed.
C
We
probably
just
need
to
change
the
tenor
ago,
the
same
way,
and
that
might
be
a
good
next
step
to
like
we
played
these
steps
that
we
did
that
I
just
did
real
fast,
and
you
can
try
to
do
it
yourself,
but
the
other
thing
is
this
particular
usage
here
is
in.
This
is
actually
in
the
type
checker
in
the
very
last
phase,
where
it
it's
exactly
the
phase
where
it
figures
out
the
kinds
of
like
they
see
where
it
infers
all
the
upper
part
types
in
it.
C
C
What
we
did
today
was
we
changed.
The
closure
subs
introduced
this
code
to
make
a
coupon
right
right.
We
do
the
same
thing
here
in
the
generator.
Self
split
basically
wants
the
same
codes
a
little
bit
different,
because
the
numbers
are
different.
Things
are
a
little
different
but
same
idea,
and
then
once
that's
done,
we
might
want
to
change
the
the
pretty
printing
code-
okay,
because
I,
because
right
now,
it's
assuming
that
you
know
how
many
first
there
are,
and
we
want
it
to
basically
want
to
rewrite
this
code
to.