Skip to content

Commit 19c2aba

Browse files
address review comments
1 parent 8c5afd4 commit 19c2aba

File tree

2 files changed

+26
-16
lines changed

2 files changed

+26
-16
lines changed

book/src/development/trait_checking.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,23 @@ we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose
102102
that we would like to find whether our type actually implements `Borrow<[u8]>`.
103103

104104
To do so, we can use the same `implements_trait` function as above, and supply
105-
a parameter type that represents `[u8]`. Since `[u8]` is a specialization of
105+
a type parameter that represents `[u8]`. Since `[u8]` is a specialization of
106106
`[T]`, we can use the [`Ty::new_slice`][new_slice] method to create a type
107-
that represents `[T]` and supply `u8` as a type parameter. The following code
108-
demonstrates how to do this:
107+
that represents `[T]` and supply `u8` as a type parameter.
108+
To create a `ty::Ty` programmatically, we rely on `Ty::new_*` methods. These
109+
methods create a `TyKind` and then wrap it in a `Ty` struct. This means we
110+
have access to all the primitive types, such as `Ty::new_char`,
111+
`Ty::new_bool`, `Ty::new_int`, etc. We can also create more complex types,
112+
such as slices, tuples, and references out of these basic building blocks.
113+
114+
For trait checking, it is not enough to create the types, we need to convert
115+
them into [GenericArg]. In rustc, a generic is an entity that the compiler
116+
understands and has three kinds, type, const and lifetime. By calling
117+
`.into()` on a constructed [Ty], we wrap the type into a generic which can
118+
then be used by the query system to decide whether the specialized trait
119+
is implemented.
120+
121+
The following code demonstrates how to do this:
109122

110123
```rust
111124

@@ -115,14 +128,14 @@ use rustc_span::symbol::sym;
115128

116129
let ty = todo!("Get the `Foo` type to check for a trait implementation");
117130
let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code
118-
let slice_bytes = Ty::new_slice(cx.tcx, cx.tcx.types.u8);
119-
let generic_param = slice_bytes.into();
131+
let slice_of_bytes_t = Ty::new_slice(cx.tcx, cx.tcx.types.u8);
132+
let generic_param = slice_of_bytes_t.into();
120133
if implements_trait(cx, ty, borrow_id, &[generic_param]) {
121134
todo!("Rest of lint implementation")
122135
}
123136
```
124137

125-
In essence, the [`Ty`] struct allows us to create types programmatically in a
138+
In essence, the [Ty] struct allows us to create types programmatically in a
126139
representation that can be used by the compiler and the query engine. We then
127140
use the `rustc_middle::Ty` of the type we are interested in, and query the
128141
compiler to see if it indeed implements the trait we are interested in.
@@ -136,6 +149,7 @@ compiler to see if it indeed implements the trait we are interested in.
136149
[symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
137150
[symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
138151
[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
139-
[`Ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
152+
[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
140153
[rust]: https://github.com/rust-lang/rust
141154
[new_slice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.new_slice
155+
[GenericArg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html

book/src/development/type_checking.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,8 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies.
125125
126126
## Creating Types programmatically
127127

128-
A common usecase for creating types programmatically is when we want to check if a type implements a trait. We have
129-
a section on this in the [Trait Checking](trait_checking.md) chapter, but given the importance of this topic, we will
130-
also cover it a bit here.
131-
132-
When we refer to "type" in this context, we refer to `ty::Ty`. To create a `ty::Ty` programmatically, we rely on
133-
`Ty::new_*` methods. These methods create a `TyKind` and then wrap it in a `Ty` struct.
134-
135-
This means we have access to all the primitive types, such as `Ty::new_char`, `Ty::new_bool`, `Ty::new_int`, etc.
136-
We can also create more complex types, such as slices, tuples, and references.
128+
A common usecase for creating types programmatically is when we want to check if a type implements a trait (see
129+
[Trait Checking](trait_checking.md)).
137130

138131
Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]`
139132

@@ -143,6 +136,9 @@ use rustc_middle::ty::Ty;
143136
let ty = Ty::new_slice(cx.tcx, Ty::new_u8());
144137
```
145138

139+
In general, we rely on `Ty::new_*` methods. These methods define the basic building-blocks that the
140+
type-system and trait-system use to define and understand the written code.
141+
146142
## Useful Links
147143

148144
Below are some useful links to further explore the concepts covered

0 commit comments

Comments
 (0)