PSA: Debugging rustc type layouts

This post is a “public service announcement” for people working on the guts of rustc. I wish I had known about this a year ago, so I hope this post can make this feature more widely known.

Debugging layouts recently became a lot easier:

#![feature(rustc_attrs)]

#[rustc_layout(debug)]
type T = (u8, u16);

https://www.ralfj.de/blog/2020/04/04/layout-debugging.html

14 Likes

Nice to see this!

Unfortunately it doesn't seem to work with impl Trait in the type alias, so I don't think it helps with debugging generator layout.

#![feature(rustc_attrs, generators, generator_trait, type_alias_impl_trait)]

use std::ops::Generator;

#[rustc_layout(debug)]
type T = impl Generator<u8>;

fn f() -> T {
    |mut r: u8| {
        r = yield "hi";
        123
    }
}
warning: unused attribute
 --> src/lib.rs:5:1
  |
5 | #[rustc_layout(debug)]
  | ^^^^^^^^^^^^^^^^^^^^^^

Interesting. My first suspicion would be that this call fails, i.e., that the type does not yet have a layout when the attribute gets processed. @eddyb might be able to confirm or reject that hypothesis.

Looks like this match needs to handle OpaqueTy

That's not really a thing nowadays, you can't observe something like that without it being unsound for the query system and incremental - what would happen is that the necessary queries would be triggered and the type computed on-demand (this is similar to CTFE triggering type-checking, borrow-checking and only then running the MIR through miri).

It works with this tweak, which means @jschievink is right:

#[rustc_layout(debug)]
type X = T;
type T = impl Generator<u8>;

This is somewhat surprising to me, as I expected impl Trait to be allowed anywhere inside the RHS of a type alias, but apparently the feature is limited to type Foo = impl Bar;.

So type T = impl X is not a TyAlias? It syntactically looks like one.^^ Interesting.

EDIT: I am working on a PR for this, but LLVM takes 1h to rebuild, so it'll be a bit until I can push.

It's the new syntax for existential types.

This used to be spelled as

existential type Foo: Trait;

But was changed to

type Foo = impl Trait;

To leverage the existing impl Trait syntax instead of a completely new syntax.

I find it somewhat confusing to get entirely different AST nodes for very similar surface syntax -- naively I would have expected that TyAlias then has two kind of "child nodes", one for normal aliases and one for impl. But well, I probably should just have read the docs. :wink:

The PR is up:

3 Likes

It should be but it's not fully implemented yet (see https://github.com/rust-lang/rust/pull/66197, we still have those hacks in lowering, sadly).

It is in the AST (see PR above) but not in HIR.

Yeah that's how it should work, but... TODO :stuck_out_tongue:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.