Edit ty.md
Makes various edits throughout for formatting, punctuation, and typo fixes. Also makes some edits and re-wording for clarity.
This commit is contained in:
parent
089dd18f03
commit
d18ab7154a
83
src/ty.md
83
src/ty.md
|
|
@ -63,10 +63,10 @@ Here is a summary:
|
||||||
HIR is built, some basic type inference and type checking is done. During the type inference, we
|
HIR is built, some basic type inference and type checking is done. During the type inference, we
|
||||||
figure out what the `ty::Ty` of everything is and we also check if the type of something is
|
figure out what the `ty::Ty` of everything is and we also check if the type of something is
|
||||||
ambiguous. The `ty::Ty` then, is used for type checking while making sure everything has the
|
ambiguous. The `ty::Ty` then, is used for type checking while making sure everything has the
|
||||||
expected type. The [`astconv` module][astconv], is where the code responsible for converting a
|
expected type. The [`astconv` module][astconv] is where the code responsible for converting a
|
||||||
`rustc_hir::Ty` into a `ty::Ty` is located. This occurs during the type-checking phase,
|
`rustc_hir::Ty` into a `ty::Ty` is located. This occurs during the type-checking phase,
|
||||||
but also in other parts of the compiler that want to ask questions like "what argument types does
|
but also in other parts of the compiler that want to ask questions like "what argument types does
|
||||||
this function expect"?.
|
this function expect?"
|
||||||
|
|
||||||
[astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/astconv/index.html
|
[astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/astconv/index.html
|
||||||
|
|
||||||
|
|
@ -79,13 +79,13 @@ They are syntactically two strings: `"u32"` at line N column 20 and `"u32"` at l
|
||||||
don’t know that they are the same yet. So, in the HIR we treat them as if they are different. Later,
|
don’t know that they are the same yet. So, in the HIR we treat them as if they are different. Later,
|
||||||
we determine that they semantically are the same type and that’s the `ty::Ty` we use.
|
we determine that they semantically are the same type and that’s the `ty::Ty` we use.
|
||||||
|
|
||||||
Consider another example: `fn foo<T>(x: T) -> u32` and suppose that someone invokes `foo::<u32>(0)`.
|
Consider another example: `fn foo<T>(x: T) -> u32`. Suppose that someone invokes `foo::<u32>(0)`.
|
||||||
This means that `T` and `u32` (in this invocation) actually turns out to be the same type, so we
|
This means that `T` and `u32` (in this invocation) actually turns out to be the same type, so we
|
||||||
would eventually end up with the same `ty::Ty` in the end, but we have distinct `rustc_hir::Ty`.
|
would eventually end up with the same `ty::Ty` in the end, but we have distinct `rustc_hir::Ty`.
|
||||||
(This is a bit over-simplified, though, since during type checking, we would check the function
|
(This is a bit over-simplified, though, since during type checking, we would check the function
|
||||||
generically and would still have a `T` distinct from `u32`. Later, when doing code generation,
|
generically and would still have a `T` distinct from `u32`. Later, when doing code generation,
|
||||||
we would always be handling "monomorphized" (fully substituted) versions of each function,
|
we would always be handling "monomorphized" (fully substituted) versions of each function,
|
||||||
and hence we would know what `T` represents (and specifically that it is `u32`).
|
and hence we would know what `T` represents (and specifically that it is `u32`).)
|
||||||
|
|
||||||
Here is one more example:
|
Here is one more example:
|
||||||
|
|
||||||
|
|
@ -107,13 +107,15 @@ or `fn(i32) -> i32` (with type aliases fully expanded).
|
||||||
|
|
||||||
## `ty::Ty` implementation
|
## `ty::Ty` implementation
|
||||||
|
|
||||||
[`rustc::ty::Ty`][ty_ty] is actually a type alias to [`&TyS`][tys] (more about that later). `TyS`
|
[`rustc::ty::Ty`][ty_ty] is actually a type alias to [`&TyS`][tys].
|
||||||
(Type Structure) is where the main functionality is located. You can ignore `TyS` struct in general;
|
This type, which is short for "Type Structure", is where the main functionality is located.
|
||||||
you will basically never access it explicitly. We always pass it by reference using the `Ty` alias.
|
You can ignore `TyS` struct in general; you will basically never access it explicitly.
|
||||||
|
We always pass it by reference using the `Ty` alias.
|
||||||
The only exception is to define inherent methods on types. In particular, `TyS` has a [`kind`][kind]
|
The only exception is to define inherent methods on types. In particular, `TyS` has a [`kind`][kind]
|
||||||
field of type [`TyKind`][tykind], which represents the key type information. `TyKind` is a big enum
|
field of type [`TyKind`][tykind], which represents the key type information. `TyKind` is a big enum
|
||||||
which represents different kinds of types (e.g. primitives, references, abstract data types,
|
with variants to represent many different Rust types
|
||||||
generics, lifetimes, etc). `TyS` also has 2 more fields, `flags` and `outer_exclusive_binder`. They
|
(e.g. primitives, references, abstract data types, generics, lifetimes, etc).
|
||||||
|
`TyS` also has 2 more fields, `flags` and `outer_exclusive_binder`. They
|
||||||
are convenient hacks for efficiency and summarize information about the type that we may want to
|
are convenient hacks for efficiency and summarize information about the type that we may want to
|
||||||
know, but they don’t come into the picture as much here. Finally, `ty::TyS`s
|
know, but they don’t come into the picture as much here. Finally, `ty::TyS`s
|
||||||
are [interned](./memory.md), so that the `ty::Ty` can be a thin pointer-like
|
are [interned](./memory.md), so that the `ty::Ty` can be a thin pointer-like
|
||||||
|
|
@ -137,14 +139,15 @@ These methods all return a `Ty<'tcx>` – note that the lifetime you get back is
|
||||||
arena that this `tcx` has access to. Types are always canonicalized and interned (so we never
|
arena that this `tcx` has access to. Types are always canonicalized and interned (so we never
|
||||||
allocate exactly the same type twice).
|
allocate exactly the same type twice).
|
||||||
|
|
||||||
> NB. Because types are interned, it is possible to compare them for equality efficiently using `==`
|
> N.B.
|
||||||
|
> Because types are interned, it is possible to compare them for equality efficiently using `==`
|
||||||
> – however, this is almost never what you want to do unless you happen to be hashing and looking
|
> – however, this is almost never what you want to do unless you happen to be hashing and looking
|
||||||
> for duplicates. This is because often in Rust there are multiple ways to represent the same type,
|
> for duplicates. This is because often in Rust there are multiple ways to represent the same type,
|
||||||
> particularly once inference is involved. If you are going to be testing for type equality, you
|
> particularly once inference is involved. If you are going to be testing for type equality, you
|
||||||
> probably need to start looking into the inference code to do it right.
|
> probably need to start looking into the inference code to do it right.
|
||||||
|
|
||||||
You can also find various common types in the `tcx` itself by accessing `tcx.types.bool`,
|
You can also find various common types in the `tcx` itself by accessing its fields:
|
||||||
`tcx.types.char`, etc (see [`CommonTypes`] for more).
|
`tcx.types.bool`, `tcx.types.char`, etc. (See [`CommonTypes`] for more.)
|
||||||
|
|
||||||
[`CommonTypes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.CommonTypes.html
|
[`CommonTypes`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.CommonTypes.html
|
||||||
|
|
||||||
|
|
@ -172,35 +175,27 @@ types in the compiler.
|
||||||
There are a lot of related types, and we’ll cover them in time (e.g regions/lifetimes,
|
There are a lot of related types, and we’ll cover them in time (e.g regions/lifetimes,
|
||||||
“substitutions”, etc).
|
“substitutions”, etc).
|
||||||
|
|
||||||
There are a bunch of variants on the `TyKind` enum, which you can see by looking at the rustdocs.
|
There are many variants on the `TyKind` enum, which you can see by looking at its
|
||||||
Here is a sampling:
|
[documentation][tykind]. Here is a sampling:
|
||||||
|
|
||||||
[**Algebraic Data Types (ADTs)**][kindadt] An [*algebraic Data Type*][wikiadt] is a `struct`,
|
- [**Algebraic Data Types (ADTs)**][kindadt] An [*algebraic data type*][wikiadt] is a `struct`,
|
||||||
`enum` or `union`. Under the hood, `struct`, `enum` and `union` are actually implemented
|
`enum` or `union`. Under the hood, `struct`, `enum` and `union` are actually implemented
|
||||||
the same way: they are all [`ty::TyKind::Adt`][kindadt]. It’s basically a user defined type.
|
the same way: they are all [`ty::TyKind::Adt`][kindadt]. It’s basically a user defined type.
|
||||||
We will talk more about these later.
|
We will talk more about these later.
|
||||||
|
- [**Foreign**][kindforeign] Corresponds to `extern type T`.
|
||||||
[**Foreign**][kindforeign] Corresponds to `extern type T`.
|
- [**Str**][kindstr] Is the type str. When the user writes `&str`, `Str` is the how we represent the
|
||||||
|
`str` part of that type.
|
||||||
[**Str**][kindstr] Is the type str. When the user writes `&str`, `Str` is the how we represent the
|
- [**Slice**][kindslice] Corresponds to `[T]`.
|
||||||
`str` part of that type.
|
- [**Array**][kindarray] Corresponds to `[T; n]`.
|
||||||
|
- [**RawPtr**][kindrawptr] Corresponds to `*mut T` or `*const T`.
|
||||||
[**Slice**][kindslice] Corresponds to `[T]`.
|
- [**Ref**][kindref] `Ref` stands for safe references, `&'a mut T` or `&'a T`. `Ref` has some
|
||||||
|
associated parts, like `Ty<'tcx>` which is the type that the reference references.
|
||||||
[**Array**][kindarray] Corresponds to `[T; n]`.
|
`Region<'tcx>` is the lifetime or region of the reference and `Mutability` if the reference
|
||||||
|
is mutable or not.
|
||||||
[**RawPtr**][kindrawptr] Corresponds to `*mut T` or `*const T`
|
- [**Param**][kindparam] Represents a type parameter (e.g. the `T` in `Vec<T>`).
|
||||||
|
- [**Error**][kinderr] Represents a type error somewhere so that we can print better diagnostics. We
|
||||||
[**Ref**][kindref] `Ref` stands for safe references, `&'a mut T` or `&'a T`. `Ref` has some
|
will discuss this more later.
|
||||||
associated parts, like `Ty<'tcx>` which is the type that the reference references, `Region<'tcx>` is
|
- [**And many more**...][kindvars]
|
||||||
the lifetime or region of the reference and `Mutability` if the reference is mutable or not.
|
|
||||||
|
|
||||||
[**Param**][kindparam] Represents a type parameter (e.g. the `T` in `Vec<T>`).
|
|
||||||
|
|
||||||
[**Error**][kinderr] Represents a type error somewhere so that we can print better diagnostics. We
|
|
||||||
will discuss this more later.
|
|
||||||
|
|
||||||
[**And Many More**...][kindvars]
|
|
||||||
|
|
||||||
[wikiadt]: https://en.wikipedia.org/wiki/Algebraic_data_type
|
[wikiadt]: https://en.wikipedia.org/wiki/Algebraic_data_type
|
||||||
[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
|
[kindadt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
|
||||||
|
|
@ -249,8 +244,8 @@ There are two parts:
|
||||||
|
|
||||||
- The [`AdtDef`][adtdef] references the struct/enum/union but without the values for its type
|
- The [`AdtDef`][adtdef] references the struct/enum/union but without the values for its type
|
||||||
parameters. In our example, this is the `MyStruct` part *without* the argument `u32`.
|
parameters. In our example, this is the `MyStruct` part *without* the argument `u32`.
|
||||||
- Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`,
|
(Note that in the HIR, structs, enums and unions are represented differently, but in `ty::Ty`,
|
||||||
they are all represented using `TyKind::Adt`.
|
they are all represented using `TyKind::Adt`.)
|
||||||
- The [`SubstsRef`][substsref] is an interned list of values that are to be substituted for the
|
- The [`SubstsRef`][substsref] is an interned list of values that are to be substituted for the
|
||||||
generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like `[u32]`.
|
generic parameters. In our example of `MyStruct<u32>`, we would end up with a list like `[u32]`.
|
||||||
We’ll dig more into generics and substitutions in a little bit.
|
We’ll dig more into generics and substitutions in a little bit.
|
||||||
|
|
@ -268,8 +263,8 @@ is only referenced).
|
||||||
|
|
||||||
`AdtDef` is more or less a wrapper around `DefId` with lots of useful helper methods. There is
|
`AdtDef` is more or less a wrapper around `DefId` with lots of useful helper methods. There is
|
||||||
essentially a one-to-one relationship between `AdtDef` and `DefId`. You can get the `AdtDef` for a
|
essentially a one-to-one relationship between `AdtDef` and `DefId`. You can get the `AdtDef` for a
|
||||||
`DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. The `AdtDef`s are all interned (as you can
|
`DefId` with the [`tcx.adt_def(def_id)` query][adtdefq]. `AdtDef`s are all interned, as shown
|
||||||
see `'tcx` lifetime on it).
|
by the `'tcx` lifetime.
|
||||||
|
|
||||||
[adtdefq]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.adt_def
|
[adtdefq]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.adt_def
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue