mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
address review comments
This commit is contained in:
parent
8c5afd496b
commit
19c2aba3e9
2 changed files with 26 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue