diff --git a/book/src/development/trait_checking.md b/book/src/development/trait_checking.md index 99932d345a4..b7d229ccc19 100644 --- a/book/src/development/trait_checking.md +++ b/book/src/development/trait_checking.md @@ -102,10 +102,23 @@ we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose that we would like to find whether our type actually implements `Borrow<[u8]>`. To do so, we can use the same `implements_trait` function as above, and supply -a parameter type that represents `[u8]`. Since `[u8]` is a specialization of +a type parameter that represents `[u8]`. Since `[u8]` is a specialization of `[T]`, we can use the [`Ty::new_slice`][new_slice] method to create a type -that represents `[T]` and supply `u8` as a type parameter. The following code -demonstrates how to do this: +that represents `[T]` and supply `u8` as a type parameter. +To create a `ty::Ty` programmatically, we rely on `Ty::new_*` methods. These +methods create a `TyKind` and then wrap it in a `Ty` struct. This means we +have access to all the primitive types, such as `Ty::new_char`, +`Ty::new_bool`, `Ty::new_int`, etc. We can also create more complex types, +such as slices, tuples, and references out of these basic building blocks. + +For trait checking, it is not enough to create the types, we need to convert +them into [GenericArg]. In rustc, a generic is an entity that the compiler +understands and has three kinds, type, const and lifetime. By calling +`.into()` on a constructed [Ty], we wrap the type into a generic which can +then be used by the query system to decide whether the specialized trait +is implemented. + +The following code demonstrates how to do this: ```rust @@ -115,14 +128,14 @@ use rustc_span::symbol::sym; let ty = todo!("Get the `Foo` type to check for a trait implementation"); let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code -let slice_bytes = Ty::new_slice(cx.tcx, cx.tcx.types.u8); -let generic_param = slice_bytes.into(); +let slice_of_bytes_t = Ty::new_slice(cx.tcx, cx.tcx.types.u8); +let generic_param = slice_of_bytes_t.into(); if implements_trait(cx, ty, borrow_id, &[generic_param]) { todo!("Rest of lint implementation") } ``` -In essence, the [`Ty`] struct allows us to create types programmatically in a +In essence, the [Ty] struct allows us to create types programmatically in a representation that can be used by the compiler and the query engine. We then use the `rustc_middle::Ty` of the type we are interested in, and query the 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. [symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html [symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html [TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html -[`Ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html +[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html [rust]: https://github.com/rust-lang/rust [new_slice]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.new_slice +[GenericArg]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.GenericArg.html diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index 42e84a3d0f5..136b3fd0270 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -125,15 +125,8 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies. ## Creating Types programmatically -A common usecase for creating types programmatically is when we want to check if a type implements a trait. We have -a section on this in the [Trait Checking](trait_checking.md) chapter, but given the importance of this topic, we will -also cover it a bit here. - -When we refer to "type" in this context, we refer to `ty::Ty`. To create a `ty::Ty` programmatically, we rely on -`Ty::new_*` methods. These methods create a `TyKind` and then wrap it in a `Ty` struct. - -This means we have access to all the primitive types, such as `Ty::new_char`, `Ty::new_bool`, `Ty::new_int`, etc. -We can also create more complex types, such as slices, tuples, and references. +A common usecase for creating types programmatically is when we want to check if a type implements a trait (see +[Trait Checking](trait_checking.md)). Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]` @@ -143,6 +136,9 @@ use rustc_middle::ty::Ty; let ty = Ty::new_slice(cx.tcx, Ty::new_u8()); ``` +In general, we rely on `Ty::new_*` methods. These methods define the basic building-blocks that the +type-system and trait-system use to define and understand the written code. + ## Useful Links Below are some useful links to further explore the concepts covered