@@ -161,22 +161,47 @@ Because types are interned, it is possible to compare them for equality efficien
161
161
for duplicates. This is because often in Rust there are multiple ways to represent the same type,
162
162
particularly once inference is involved.
163
163
164
- For example, the type ` {integer} ` (an integer inference variable, the type of an integer
165
- literal like ` 0 ` ) and ` u8 ` should often be treated as equal when testing whether they
166
- can be assigned to each other (which is a common operation in diagnostics code).
167
- ` == ` on them will return ` false ` though, since they are different types.
164
+ For example, the type ` {integer} ` (` ty::Infer(ty::IntVar(..)) ` an integer inference variable,
165
+ the type of an integer literal like ` 0 ` ) and ` u8 ` ( ` ty::UInt(..) ` ) should often be treated as
166
+ equal when testing whether they can be assigned to each other (which is a common operation in
167
+ diagnostics code). ` == ` on them will return ` false ` though, since they are different types.
168
168
169
169
The simplest way to compare two types correctly requires an inference context (` infcx ` ).
170
- If you have one, you can use ` infcx.can_eq(ty1, ty2) ` to check whether the types can be made equal,
171
- so whether they can be assigned to each other.
170
+ If you have one, you can use ` infcx.can_eq(ty1, ty2) ` to check whether the types can be made equal.
171
+ This is typically what you want to check during diagnostics, which is concerned with questions such
172
+ as whether two types can be assigned to each other, not whether they're represented identically in
173
+ the compiler's type-checking layer.
174
+
172
175
When working with an inference context, you have to be careful to ensure that potential inference
173
176
variables inside the types actually belong to that inference context. If you are in a function
174
- that has access to an inference context already, this should be the case.
175
-
176
- Another consideration is normalization. Two types may actually be the same, but one is behind an associated type.
177
- To compare them correctly, you have to normalize the types first. <!-- FIXME: When do you have to worry about this? When not? -->
178
-
179
- <!-- What to do when you don't have an inference context available already? Just create one and hope all goes well? -->
177
+ that has access to an inference context already, this should be the case. Specifically, this is the
178
+ case during HIR type checking or MIR borrow checking.
179
+
180
+ Another consideration is normalization. Two types may actually be the same, but one is behind an
181
+ associated type. To compare them correctly, you have to normalize the types first. This is
182
+ primarily a concern during HIR type checking and with all types from a ` TyCtxt ` query
183
+ (for example from ` tcx.type_of() ` ).
184
+
185
+ When a ` FnCtxt ` or an ` ObligationCtxt ` is available during type checking, ` .normalize(ty) `
186
+ can be used on them to normalize the type. After type checking, diagnostics code can use
187
+ ` tcx.normalize_erasing_regions(ty) ` .
188
+
189
+ There are also cases where using ` == ` on ` Ty ` is fine. This is for example the case in late lints
190
+ or after monomorphization, since type checking has been completed, meaning all inference variables
191
+ are resolved and all regions have been erased. In these cases, if you know that inference variables
192
+ or normalization won't be a concern, ` #[allow] ` or ` #[expect] ` ing the lint is recommended.
193
+
194
+ When diagnostics code does not have access to an inference context, it should be threaded through
195
+ the function calls if one is available in some place (like during type checking).
196
+
197
+ If no inference context is available at all, then one can be created as described in
198
+ [ type-inference] . But this is only useful when the involved types (for example, if
199
+ they came from a query like ` tcx.type_of() ` ) are actually substituted with fresh
200
+ inference variables using [ ` fresh_substs_for_item ` ] . This can be used to answer questions
201
+ like "can ` Vec<T> ` for any ` T ` be unified with ` Vec<u32> ` ?".
202
+
203
+ [ type-inference ] : ./type-inference.md#creating-an-inference-context
204
+ [ `fresh_substs_for_item` ] : https://doc.rust-lang.org/beta/nightly-rustc/rustc_infer/infer/struct.InferCtxt.html#method.fresh_substs_for_item
180
205
181
206
## ` ty::TyKind ` Variants
182
207
0 commit comments