address review comments

This commit is contained in:
Quinn Sinclair 2024-02-13 23:48:14 +01:00
parent ca8f03fb93
commit 8c5afd496b

View file

@ -96,11 +96,16 @@ impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
## Creating Types Programmatically ## Creating Types 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 Traits are often generic over a type parameter, e.g. `Borrow<T>` is generic
a specific type. For example, we can implement `Borrow<str>` for a hypothetical type `Foo`. Let's suppose that we over `T`. Rust allows us to implement a trait for a specific type. For example,
would like to find whether our type actually implements `Borrow<[u8]>`. To do so, we need to supply a type that we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose
represents `[u8]`, but `[u8]` is also a generic, it's a slice over `u8`. We can create this type using Ty::new_slice that we would like to find whether our type actually implements `Borrow<[u8]>`.
method. The following code demonstrates how to do this:
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
`[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:
```rust ```rust
@ -108,17 +113,19 @@ use rustc_middle::ty::Ty;
use clippy_utils::ty::implements_trait; use clippy_utils::ty::implements_trait;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
let ty = todo!(); 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 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()]) { let slice_bytes = Ty::new_slice(cx.tcx, cx.tcx.types.u8);
todo!() let generic_param = slice_bytes.into();
if implements_trait(cx, ty, borrow_id, &[generic_param]) {
todo!("Rest of lint implementation")
} }
``` ```
Here, we use `Ty::new_slice` to create a type that represents `[T]` and supply `u8` as a type parameter, and then we go In essence, the [`Ty`] struct allows us to create types programmatically in a
on normally with `implements_trait` function. The [Ty] struct allows us to create types programmatically, and it's representation that can be used by the compiler and the query engine. We then
useful when we need to create types that we can't obtain through the usual means. 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.
[DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html [DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
@ -129,5 +136,6 @@ useful when we need to create types that we can't obtain through the usual means
[symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html [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 [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 [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 [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