Skip to content

Conversation

tall-vase
Copy link
Collaborator

Materials on "token types."

The "Branded tokens" section of this one requires a little extra scrutiny. It may be the case it is too complex for this stage, or that the explanation isn't suitable for the audience/instructors. Either way, I'm eager for input.

Copy link

google-cla bot commented Sep 22, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

gribozavr and others added 6 commits September 22, 2025 11:44
The previous STYLE.md advised against using speaker notes as a 'script'
but didn't provide clear examples of what that meant. This could be
interpreted by LLMs as disallowing any kind of instructor prompt.

This change clarifies the guideline by:

1. Distinguishing between long-form, verbatim 'scripts' (bad) and short,
actionable 'teaching prompts' (good).

2. Providing concrete 'good' and 'bad' examples to make the distinction
unambiguous for future contributors.
@gribozavr gribozavr self-requested a review September 28, 2025 19:11
>
> - Note: The `Ext` suffix is a common convention.
> - Ask: What happens if the `use` statement is removed?
> - Demo: Comment out the `use` statement to show the compiler error.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this content already exists in the main branch? Please rebase to hide the spurious diff.


<details>

- Token types let us use the privacy tools of types and modules to control when
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This explanation is a bit too abstract and sounds very similar to how we introduce the typestate pattern, "How can we ensure that only valid operations are allowed on a value based on its current state?", except that we're not talking about a specific state. Could we make it more concrete? Should we merge the two sections? Should this section be ordered before typestate but after newtype?

My thinking is that newtype wraps a concrete piece of data, and represents a proof that the data satisfies a predicate.

What I see in the token types section suggests that a token type represents a proof that some data elsewhere, or the program control flow, satisfies a certain predicate.

The current progression seems to be newtype -> typestate -> token types.

This does not seem ideal. First we introduce a foundational concept (Newtype), then jump to a complex application (the generic serializer in Typestate), and then present a simpler concept (token types). It seems to me that token types are a more straightforward extension of the initial newtype pattern.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't quite do that if we're covering branded types, as that depends on the Borrowck invariants work (introduction of PhantomData, use of Lifetimes to enforce invariants). If we cut the Branded types content, then this re-ordering would be feasible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I tried referencing those sections, but I don't understand. The token types slide does not depend on PhantomData or complex use of lifetimes. Could you explain this issue in more detail?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, I don't mean moving the entirety of this PR between newtype and typestate. Only this slide.

make sure cells can't "escape" a context where we know where cyclic operations
are safe.

</details>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all technically correct, but too dense for a slide. I think we need to have a more gentle flow, broken down into multiple slides, starting with motivation (in this example it is not clear what the token is achieving). When we move on to explain the implementation, we should first start with a sketch that has the right structure but omits some of the details that make the code correct for the sake of brevity (e.g., the variance mechanics).


Here's an idea, but you can of course come up with your own.

Motivation: if you decide to use the AdminToken example in the previous slide, you can build a segue to this idea. Remind the students that the web server processes multiple requests, but only one at a time. We could use one user's credentials to log in and get an AdminToken, stash it in a global variable somewhere, and then process other user's message deletion request using that token.

=> Idea for a solution: the Board::delete_message() function should only accept a token that was returned by Board::login() by the same object.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You made great improvements, but the example is still abstract.

@gribozavr gribozavr added the waiting for author Waiting on the issue author to reply label Sep 28, 2025

# Permission Tokens

Token types work well as a trivial "proof of checked permission."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Token types work well as a trivial "proof of checked permission."
Token types work well as a proof of checked permission.

- Ask: What is the purpose of the `proof: ()` field here?

Without `proof: ()`, `Token` would have no private fields and users would be
able to construct values of `Token` arbitrarily.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to prompt the instructor to try to construct the token in main and show that the compiler does not allow doing that.

until they've performed a specific task.

We can do this by defining a type the API consumer cannot construct on their
own, through privacy tools of structs and modules.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice remind students that the newtype pattern is based on the same idea.

# Token Types with Data: Mutex Guards

Sometimes, a token type needs additional data. A mutex guard is an example of
permission + data.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
permission + data.
a permission + data.

`Mutex` while the underlying `Mutex` keeps that data private from the user.

- If `mutex.lock()` does not return a `MutexGuard`, you don't have permission to
change the value within the mutex.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's important to emphasize here is that not only the user does not have permission (which is also true, e.g., for C++ mutexes), the user does not have a way to access the data (which sets Rust mutexes apart).

Comment on lines +22 to +23
// We want a function whose lifetime is specific to each time
// `new` is called, not tied to any one data structure other than
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We want a function whose lifetime is specific to each time
// `new` is called, not tied to any one data structure other than
// We want a function whose lifetime is specific to each call to
// `new`, not tied to any one data structure other than

make sure cells can't "escape" a context where we know where cyclic operations
are safe.

</details>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You made great improvements, but the example is still abstract.

- [`GhostCell`](https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf) is a
prominent user of this, later slides will touch on it.

</details>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Next, once we have shown the general idea, I'd suggest transitioning to a concrete API design problem (not an abstract one like here).

- The underlying Branded Data Structure we're going to use here is just a
`Vec<u8>` (the data) and an `InvariantLifetime`.

- The constructor for this type will take **data for the `Vec<u8`** plus a
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- The constructor for this type will take **data for the `Vec<u8`** plus a
- The constructor for this type will take **data for the `Vec<u8>`** plus a

Expect not much, it's "for" in the sense of "forall" from mathematics.

- The `for<'a> [trait bound that uses 'a]` binding of `'a` means the lifetime is
"self contained."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can explain this in more depth, rather than through an analogy.

get a `AdminToken` to perform administrator actions within a specific
environment (here, a chat client).

Once the permissions are gained, we can call a `add_moderator` function.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Once the permissions are gained, we can call a `add_moderator` function.
Once the permissions are gained, we can call the `add_moderator` function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
deep_dives/idiomatic waiting for author Waiting on the issue author to reply
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants