about summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuinn Sinclair <me@partiallytyped.dev>2024-02-13 01:25:36 +0100
committerQuinn Sinclair <me@partiallytyped.dev>2024-03-03 18:12:41 +0100
commita6fc64bb7b4c2bda431a95af25b8c380a1c78575 (patch)
tree7efbf543dc0c02b143640ce5b2b3e09fc71c216d
parent28e11b31deef5fd0f59a1e289f8f2173ed6e5944 (diff)
downloadrust-a6fc64bb7b4c2bda431a95af25b8c380a1c78575.tar.gz
rust-a6fc64bb7b4c2bda431a95af25b8c380a1c78575.zip
Trait checking and type construction
-rw-r--r--book/src/development/trait_checking.md22
-rw-r--r--book/src/development/type_checking.md16
2 files changed, 38 insertions, 0 deletions
diff --git a/book/src/development/trait_checking.md b/book/src/development/trait_checking.md
index fb263922cf8..4944970dd55 100644
--- a/book/src/development/trait_checking.md
+++ b/book/src/development/trait_checking.md
@@ -94,6 +94,27 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
 }
 ```
 
+## Creating traits programmatically
+
+Traits are often generic over a type e.g. `Borrow<T>` is generic over `T`, and rust allows us to implement a trait for a specific type. For example, we can implement `Borrow<str>` 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 need to supply a type that represents `[u8]`, but `[u8]` is also a generic, it's a slice over `u8`. We can create this type using Ty::new_slice method. The following code demonstrates how to do this:
+
+```rust
+
+use rustc_middle::ty::Ty;
+use clippy_utils::ty::implements_trait;
+use rustc_span::symbol::sym;
+
+let ty = todo!();
+let borrow_id = cx.tcx.get_diagnostic_item(sym::Borrow).unwrap(); // avoid unwrap in real code
+if implements_trait(cx, ty, borrow_id, &[Ty::new_slice(cx.tcx, cx.tcx.types.u8).into()]) {
+    todo!()
+}
+```
+
+Here, we use `Ty::new_slice` to create a type that represents `[T]` and supply `u8` as a type parameter, and then we go on normally with `implements_trait` function. The [Ty] struct allows us to create types programmatically, and it's useful when we need to create types that we can't obtain through the usual means.
+
+
+
 [DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
 [diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
 [lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html
@@ -102,4 +123,5 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
 [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
 [rust]: https://github.com/rust-lang/rust
diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md
index dc29ab5d08d..ed85e416475 100644
--- a/book/src/development/type_checking.md
+++ b/book/src/development/type_checking.md
@@ -123,6 +123,22 @@ the [`TypeckResults::node_type()`][node_type] method inside of bodies.
 
 > **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
 
+## 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 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.
+
+Here's an example of how to create a `Ty` for a slice of `u8`, i.e. `[u8]`
+
+```rust
+use rustc_middle::ty::Ty;
+// assume we have access to a LateContext
+let ty = Ty::new_slice(cx.tcx, Ty::new_u8());
+```
+
 ## Useful Links
 
 Below are some useful links to further explore the concepts covered