Repository navigation
Value mangling #61486
Description
Activity
- addedA-const-genericsArea: const generics (parameters and arguments)Area: const generics (parameters and arguments)
on Jun 3, 2019 cc #60705
At the moment, only unsigned integers are supported.
bools work too, don't they? #61383 (comment)
@est31: the current implementation of const generics supports more types than the mangle supports, which is something we need to address.
It's unclear what "initial version of const generics" means at this point. We're not ready to talk about stabilisation yet. Hopefully we'll be able to discuss proper mangling soon. I know @eddyb already has some ideas.
Quoting @eddyb from Discord channel #compiler for my own benefit if nothing else:
unsigned integers is really what people want, IMO. but I have an idea of how to encode arbitrary ADTs into the symbol mangling, so it shouldn't be too bad
(basically something like
std::fmt::Formatter::debug_{list,struct,tuple}, and the struct/tuple forms can take a path that's the path of the variant in an enum, for enum values)lol I didn't finish my thought: you'd encode
Some(0i32)as something likeTNvINt...6OptioniE4Somei0_E
that is,...::Option<i32>::Some(0i32)Reacted by Hadrien G. and tema3210- addedC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
on Jun 9, 2019 - addedF-const_generics`#![feature(const_generics)]``#![feature(const_generics)]`requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
on Aug 6, 2019 Such printing should probably share the walking logic with the const validator (https://github.com/rust-lang/rust/blob/master/src/librustc_mir/interpret/validity.rs), because both need to do the same thing.
These tests fail with
-Zsymbol-mangling-version=v0:[ui] ui/const-generics/fn-const-param-call.rs [ui] ui/const-generics/issues/issue-61432.rs [ui] ui/const-generics/issues/issue-62579-no-match.rs [ui] ui/const-generics/raw-ptr-const-param-deref.rs [ui] ui/const-generics/slice-const-param.rsMaybe we should start adding revisions that use
-Zsymbol-mangling-version=v0to all const generic tests and FIXMEs pointing to this issue for the ones that don't work?
More specifically, what I did to test this was replace
LegacywithV0here:rust/src/librustc_session/options.rs
Line 953 in 42ce9b4
symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy, I've just noticed a potential issue with the syntax:
We supportpafter the "basic type" (currently only unsigned integers).As a type,
pmeans "placeholder" and is printed as_.
This is useful for e.g. astaticinside animplmethod, because it doesn't depend on theimpls's parameters, so we end up with e.g.<Foo<_>>::foo::BAR.But for a constant integer, we encode a similar situation (e.g.
<ArrayVec<_, _>>::foo::BAR) using, for the const generic arg,jp(jis the typeusize) - so more like_: usizethan just_.
(For completeness,42: usizeis encoded asj2a_- i.e. we use the value in hex)Now,
jpvs justp(which is not supported as a constant right now) is harmless, even if a bit longer, and the ability to print_: usizein verbose mode is neat.But if we start including ADTs, we might need, for const generics of type
(usize, usize), to encodeTjpjpE, i.e.(_: usize, _: usize), printed as(_, _)by default.
This is starting to get weird, but it's still manageable, the real problem is enums.How would you encode an erased
Option<usize>? Normal values of that type would be rely on eitherOption::<usize>::SomeorOption::<usize>::None, but for placeholders we can't choose.
The good news is we can still add a general placeholder, either just
pas a constant, orpfollowed by its type (if we want to be able to print a type).
However, since the type of a constant must be monomorphic (or maybe in the future, determined by type parameters in scope), we don't have to encode it.Speaking of which, the current syntax is also redundant in that we print all the integers the same, so we don't really need to encode which one it is, just that the hex nibbles should be printed as an integer.
- added a commit that references this issue
on Apr 20, 2020 1 remaining item
Signed integers and
charare now supported: #77554, so marking this as unblocking.Reacted by est31, Muhammad Mominul Huque and Michael Woerister@michaelwoerister It's been resolved already (as part of #77554):
rust/compiler/rustc_symbol_mangling/src/v0.rs
Lines 541 to 550 in bcd696d
if let Some(bits) = val { // We only print the type if the const can be evaluated. self = ct.ty.print(self)?; let _ = write!(self.out, "{}{:x}_", if neg { "n" } else { "" }, bits); } else { // NOTE(eddyb) despite having the path, we need to // encode a placeholder, as the path could refer // back to e.g. an `impl` using the constant. self.push("p"); } That
pdoesn't have a type before it. So we're now using the "improved" approach I was describing in that comment.EDIT: the grammar should be updated too.
Reacted by Michael Woerister@michaelwoerister Actually, to answer the more interesting question:
<const> = <type> "p"is wrong and largely unworkable -<const>cannot start with<type>without severely overcomplicating the encoding of ADT constants.So the current implementation only supports
<const>starting with<basic-type>. And ideally we'd reuse the non-basic type constructor letters for values. Say,Ai1_i2_i3_Efor[1, 2, 3].Before I realized we'd more or less have to encode "a tree of ADT constructors" for more interesting values, I still thought we could generally do
<type> {<hex-nibble>} "_"to encode arbitrary data, but that's flawed.There are too many factors that make it almost impossible, and also quite undesireable, to have demanglers understand how data is laid out. So only
bool,char& integers (and maybestrs in the future) can use raw bytes.In #87082 (comment) I wrote this, which seems like it would be useful to have in this thread:
We only want to ever allow type-level constants (such as those passed to
constparams) to be one of:- integer leaves (
iN,uN, and alsoboolandchar)
- if we allow raw pointers, they would only be allowed here, with integer addresses
- maybe
strand[u8]would also go in here for efficiency, unsure yet about that
- ADTs of other type-level constants (
struct,enum, tuples, arrays, slices, etc.)
- no C
unions, since we can't guarantee we can describe them as pure values - any user-defined ADTs have to have be "structurally matchable" (i.e. auto-derived
PartialEq+Eq) - arguably this includes
&Ttoo - even if they are normally thought of as indirection, at the type-level&valueacts as a newtype ofvalue, as&Thas structural equality that makes it isomorphic toT
(cc @oli-obk - did I miss anything?)
We already have the leaves, what's lacking in the mangling is the second part (the ADTs) - it's not that much design space, since e.g.
enumvariants can be treated as juststructs (i.e. we encode the path to the variant and pretend it's astructpath) - the tricky parts how much aesthetic detail we put in, like whether we encode field names, how differently to encode tuplestructs (make them like regularstructs or like tuples?), whether we add a special case forstrto avoid encoding it as an array, etc. etc.- integer leaves (
First attempt at previously suggested constant value mangling approaches, is now up at #87194 (including grammar).
to my knowledge this is now integrated in v0 mangling? @eddyb can this be closed?
- addedF-adt_const_params`#![feature(adt_const_params)]``#![feature(adt_const_params)]`and removedF-const_generics`#![feature(const_generics)]``#![feature(const_generics)]`
on Jun 24, 2022 An implementation is complete, but I would block this on the RFC PR getting merged (see its discussion):
For const generics, we will eventually allow arbitrary
structural_matchvalues as generic arguments. Thus, we need to figure out how to mangle them. At the moment, only unsigned integers are supported.min_const_genericsbool(Permit ty::Bool in const generics for v0 mangling #77452)charadt_const_paramscc @eddyb @yodaldevoid