@@ -1206,6 +1206,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1206
1206
Ok ( ( ) )
1207
1207
}
1208
1208
1209
+ /// Equates a type `anon_ty` that may contain opaque types whose
1210
+ /// values are to be inferred by the MIR with def-id `anon_owner_def_id`.
1211
+ ///
1212
+ /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
1213
+ /// hidden types for impl traits revealed.
1214
+ ///
1215
+ /// # Example
1216
+ ///
1217
+ /// Consider a piece of code like
1218
+ ///
1219
+ /// ```rust
1220
+ /// type Foo<U> = impl Debug;
1221
+ ///
1222
+ /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
1223
+ /// Box::new((t, 22_u32))
1224
+ /// }
1225
+ /// ```
1226
+ ///
1227
+ /// Here, the function signature would be something like
1228
+ /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
1229
+ /// the type with the opaque type revealed, so `Box<(T, u32)>`.
1230
+ ///
1231
+ /// In terms of our function parameters:
1232
+ ///
1233
+ /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
1234
+ /// scoped to this function (note that it is parameterized by the
1235
+ /// generics of `foo`). Note that `anon_ty` is not just the opaque type,
1236
+ /// but the entire return type (which may contain opaque types within it).
1237
+ /// * `revealed_ty` would be `Box<(T, u32)>`
1238
+ /// * `anon_owner_def_id` would be the def-id of `foo`
1209
1239
fn eq_opaque_type_and_type (
1210
1240
& mut self ,
1211
1241
revealed_ty : Ty < ' tcx > ,
@@ -1240,6 +1270,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1240
1270
let tcx = infcx. tcx ;
1241
1271
let param_env = self . param_env ;
1242
1272
let body = self . body ;
1273
+
1274
+ // the "concrete opaque types" maps
1243
1275
let concrete_opaque_types = & tcx. typeck ( anon_owner_def_id) . concrete_opaque_types ;
1244
1276
let mut opaque_type_values = VecMap :: new ( ) ;
1245
1277
@@ -1252,6 +1284,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1252
1284
let mut obligations = ObligationAccumulator :: default ( ) ;
1253
1285
1254
1286
let dummy_body_id = hir:: CRATE_HIR_ID ;
1287
+
1288
+ // Replace the opaque types defined by this function with
1289
+ // inference variables, creating a map. In our example above,
1290
+ // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
1291
+ // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
1292
+ // (Note that the key of the map is both the def-id of `Foo` along with
1293
+ // any generic parameters.)
1255
1294
let ( output_ty, opaque_type_map) =
1256
1295
obligations. add ( infcx. instantiate_opaque_types (
1257
1296
anon_owner_def_id,
@@ -1267,6 +1306,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1267
1306
revealed_ty={:?}",
1268
1307
output_ty, opaque_type_map, revealed_ty
1269
1308
) ;
1309
+
1270
1310
// Make sure that the inferred types are well-formed. I'm
1271
1311
// not entirely sure this is needed (the HIR type check
1272
1312
// didn't do this) but it seems sensible to prevent opaque
@@ -1282,6 +1322,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1282
1322
. eq ( output_ty, revealed_ty) ?,
1283
1323
) ;
1284
1324
1325
+ // For each opaque type `Foo<T>` inferred by this value, we want to equate
1326
+ // the inference variable `?T` with the revealed type that was computed
1327
+ // earlier by type check.
1285
1328
for & ( opaque_type_key, opaque_decl) in & opaque_type_map {
1286
1329
let resolved_ty = infcx. resolve_vars_if_possible ( opaque_decl. concrete_ty ) ;
1287
1330
let concrete_is_opaque = if let ty:: Opaque ( def_id, _) = resolved_ty. kind ( ) {
@@ -1290,6 +1333,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1290
1333
false
1291
1334
} ;
1292
1335
1336
+ // The revealed type computed by the earlier phase of type check.
1337
+ // In our example, this would be `(U, u32)`. Note that this references
1338
+ // the type parameter `U` from the definition of `Foo`.
1293
1339
let concrete_ty = match concrete_opaque_types
1294
1340
. get_by ( |( key, _) | key. def_id == opaque_type_key. def_id )
1295
1341
{
@@ -1308,7 +1354,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1308
1354
Some ( concrete_ty) => concrete_ty,
1309
1355
} ;
1310
1356
debug ! ( "concrete_ty = {:?}" , concrete_ty) ;
1357
+
1358
+ // Apply the substitution, in this case `[U -> T]`, so that the
1359
+ // concrete type becomes `Foo<(T, u32)>`
1311
1360
let subst_opaque_defn_ty = concrete_ty. subst ( tcx, opaque_type_key. substs ) ;
1361
+
1362
+ // "Renumber" this, meaning that we replace all the regions
1363
+ // with fresh inference variables. Not relevant to our example.
1312
1364
let renumbered_opaque_defn_ty =
1313
1365
renumber:: renumber_regions ( infcx, subst_opaque_defn_ty) ;
1314
1366
@@ -1318,8 +1370,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1318
1370
) ;
1319
1371
1320
1372
if !concrete_is_opaque {
1321
- // Equate concrete_ty (an inference variable) with
1322
- // the renumbered type from typeck.
1373
+ // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
1374
+ // in our example) with the renumbered version that we took from
1375
+ // the type check results (`Foo<(T, u32)>`).
1323
1376
obligations. add (
1324
1377
infcx
1325
1378
. at ( & ObligationCause :: dummy ( ) , param_env)
0 commit comments