You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It feels to me like we have a lot of different "transition" and a whole bunch of supporting code, but we should use a small number of toolchain name types throughout the codebase and proactively resolve to these early/upfront.
It would be good to summarize the design of these and see if some of it can be flattened.
Below is a short summary of rustup's toolchain hierarchy at the time of writing. Type declarations are intentionally written in TypeScript style since the focus is really the data each type contains, rather than the variants of each tag union as implemented in Rust.
When converting the former to the latter via .resolve() , the host tuple will be passed in to fill in the blanks.
[Resolvable][Local]ToolchainName
Describes a local or an official toolchain name.
This family has two variants, and the latter adds the possibility of a "path-based toolchain name" onto the former.
// A partial official toolchain name, or a custom toolchain name (like 'system')typeResolvableToolchainName=PartialToolchainDesc|CustomToolchainName// A partial official toolchain name, or a custom toolchain name, or a pathtypeResolvableLocalToolchainName=ResolvableToolchainName|PathBasedToolchainName
Their respective fully resolved forms are ToolchainName and LocalToolchainName:
// A _full_ official toolchain name, or a custom toolchain nametypeToolchainName=ToolchainDesc|CustomToolchainName// A _full_ official toolchain name, a custom toolchain name, or a pathtypeLocalToolchainName=ToolchainName|PathBasedToolchainName
The final authoritative result type is LocalToolchainName, which will be used later in the toolchain types.
Toolchain name wrappers
Maybe(Official|Resolvable)ToolchainName
Non-generic wrappers over the underlying type and the reserved name none.
This family has two variants:
// 'none', or a partial official toolchain name// Used in `rustup-init --default-toolchain=xxx`typeMaybeOfficialToolchainName='none'|PartialToolchainDesc// 'none', or a partial official toolchain name, or a custom toolchain name// Used in `rustup default yyy` in conjunction with `Override<>`, see below.typeMaybeResolvableToolchainName='none'|ResolvableToolchainName
The naming here is really not consistent and very confusing.
Override<T>
Generic wrappers over the underlying type and the reserved name default (which can later be extended to env etc.).
This family current has three instances (note that T is always unresolved):
// An alias, a partial official toolchain name, or a custom toolchain name// Used in `rustup override set xxx`Override<ResolvableToolchainName>;// An alias, a partial official toolchain name, or a custom toolchain name, or a path// Used in `rustup +yyy`Override<ResolvableLocalToolchainName>;// An alias, 'none', a partial official toolchain name, or a custom toolchain name// Used in `rustup default yyy`Override<MaybeResolvableToolchainName>;
I feel like it might be interesting to fold all layers with potential reserved names into a single wrapper type or a clear hierarchy, if possible.
Toolchain types
There are two variants:
typeToolchain={cfg: Cfg;name: LocalToolchainName;path: PathBuf}// Inherits `Toolchain` but is de facto limited to official ones as enforced by the constructor.// It has special methods specific to official toolchains.// `desc` is cloned from `.toolchain.name`'s `ToolchainDesc` variant, looks redundant.typeDistributableToolchain={toolchain: Toolchain;desc: ToolchainDesc}
Maybe this can also be a generic type among the lines of Toolchain<OfficialToolchainName> and Toolchain<LocalToolchainName>, with particular implementations just for the former case.
We still need to design the verb to be used when converting from PartialFooName to FooName, and from Override<Foo> to Foo. Currently, both are called .resolve(), but actually I would prefer going with #5041's naming and rename the first to .qualify().
@djc I'd say the core types are (in their current names) LocalToolchainName in the toolchain name layer, and Toolchain and DistributableToolchain in the toolchain layer.
Official toolchains and have a special toolchain type DistributableToolchain, which is the more capable of the two toolchain types (because it has a manifest file and can install components, targets, etc.). However the DistributableToolchain case is more independent from that of other types, so its redesign can probably be postponed.
Other types are really mostly FromStr adapters for one or more of the 3 cases of LocalToolchainName: the official toolchain name, the custom toolchain name, and the toolchain path. This means that they are also considered to be a part of the toolchain name layer. The only differences are: some of them are unqualified (with a partial target tuple), some aliased (with an alias), some optional (with a possible 'none').
In conclusion: the data flows from the toolchain name layer to the toolchain layer, as rustup generally first converts a toolchain string from those FromStr adapters to LocalToolchainName, and then construct Toolchain and/or DistributableToolchain from it.
So then it feels like we should take all types that are not LocalToolchainName, Toolchain, DistributableToolchain and ToolchainDesc and make it easy to convert them into one of those, right?
@djc Yes, and I believe that is globally already the case, although the conversion inside the toolchain name layer is a mess when looking pretty close.
Personally, if I were new to the codebase, I want the names of the types to look closely related to LocalToolchainName and ToolchainDesc as much as possible so that I know immediately which types are from which of the 2 layers and may correspond to which of the 3 cases above. I'm looking into just that.
Activity
rami3l commentedon Sep 23, 2026
Below is a short summary of rustup's toolchain hierarchy at the time of writing. Type declarations are intentionally written in TypeScript style since the focus is really the data each type contains, rather than the variants of each tag union as implemented in Rust.
Toolchain name abstraction
[Partial]ToolchainDescDescribes an official toolchain name.
This family has two variants:
... where:
Note that in a
PartialTargetTuple, blanks are allowed. In other words, the below are all valid partial tuples:When converting the former to the latter via
.resolve(), the host tuple will be passed in to fill in the blanks.[Resolvable][Local]ToolchainNameDescribes a local or an official toolchain name.
This family has two variants, and the latter adds the possibility of a "path-based toolchain name" onto the former.
Their respective fully resolved forms are
ToolchainNameandLocalToolchainName:The final authoritative result type is
LocalToolchainName, which will be used later in the toolchain types.Toolchain name wrappers
Maybe(Official|Resolvable)ToolchainNameNon-generic wrappers over the underlying type and the reserved name
none.This family has two variants:
Override<T>Generic wrappers over the underlying type and the reserved name
default(which can later be extended toenvetc.).This family current has three instances (note that
Tis always unresolved):Toolchain types
There are two variants:
rami3l commentedon Sep 23, 2026
Regarding the toolchain names, I feel like we should do the following renames:
[Partial]ToolchainDesc->[Partial]OfficialToolchainName: to align withCustomToolchainName[Resolvable]ToolchainName->[Partial]ToolchainNamePathBasedToolchainName->ToolchainPath[Resolvable]LocalToolchainName->[Partial]ToolchainNameOrPathWe still need to design the verb to be used when converting from
PartialFooNametoFooName, and fromOverride<Foo>toFoo. Currently, both are called.resolve(), but actually I would prefer going with #5041's naming and rename the first to.qualify().djc commentedon Sep 23, 2026
Which toolchain names/types do we actually end up using deeper in callgraphs?
rami3l commentedon Sep 23, 2026
@djc I'd say the core types are (in their current names)
LocalToolchainNamein the toolchain name layer, andToolchainandDistributableToolchainin the toolchain layer.Official toolchains and have a special toolchain type
DistributableToolchain, which is the more capable of the two toolchain types (because it has a manifest file and can install components, targets, etc.). However theDistributableToolchaincase is more independent from that of other types, so its redesign can probably be postponed.Other types are really mostly
FromStradapters for one or more of the 3 cases ofLocalToolchainName: the official toolchain name, the custom toolchain name, and the toolchain path. This means that they are also considered to be a part of the toolchain name layer. The only differences are: some of them are unqualified (with a partial target tuple), some aliased (with an alias), some optional (with a possible 'none').In conclusion: the data flows from the toolchain name layer to the toolchain layer, as rustup generally first converts a toolchain string from those
FromStradapters toLocalToolchainName, and then constructToolchainand/orDistributableToolchainfrom it.djc commentedon Sep 23, 2026
So then it feels like we should take all types that are not
LocalToolchainName,Toolchain,DistributableToolchainandToolchainDescand make it easy to convert them into one of those, right?rami3l commentedon Sep 23, 2026
@djc Yes, and I believe that is globally already the case, although the conversion inside the toolchain name layer is a mess when looking pretty close.
Personally, if I were new to the codebase, I want the names of the types to look closely related to
LocalToolchainNameandToolchainDescas much as possible so that I know immediately which types are from which of the 2 layers and may correspond to which of the 3 cases above. I'm looking into just that.rami3l commentedon Sep 25, 2026
So I did a quick test with GPT in rami3l@f6cdfdb and found out that
ToolchainandDistributableToolchaincan indeed be unified as:Although perfect naming would be
ToolchainNameinstead ofGenericToolchainName, which would require renamingToolchainNameto something else.I think that would be a very good starting point.
djc commentedon Sep 25, 2026
Does look like an improvement!