@@ -102,10 +102,23 @@ we can implement `Borrow<[u8]>` for a hypothetical type `Foo`. Let's suppose
102
102
that we would like to find whether our type actually implements ` Borrow<[u8]> ` .
103
103
104
104
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
106
106
` [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:
109
122
110
123
``` rust
111
124
@@ -115,14 +128,14 @@ use rustc_span::symbol::sym;
115
128
116
129
let ty = todo! (" Get the `Foo` type to check for a trait implementation" );
117
130
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 ();
120
133
if implements_trait (cx , ty , borrow_id , & [generic_param ]) {
121
134
todo! (" Rest of lint implementation" )
122
135
}
123
136
```
124
137
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
126
139
representation that can be used by the compiler and the query engine. We then
127
140
use the ` rustc_middle::Ty ` of the type we are interested in, and query the
128
141
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.
136
149
[ symbol ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
137
150
[ symbol_index ] : https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
138
151
[ 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
140
153
[ rust ] : https://github.com/rust-lang/rust
141
154
[ 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
0 commit comments