Skip to content

Commit 29cd70d

Browse files
committed
Auto merge of #86437 - nikomatsakis:tait-docs, r=oli-obk
add various coments to explain how the TAIT code works r? `@oli-obk`
2 parents 39260f6 + 831759a commit 29cd70d

File tree

3 files changed

+86
-11
lines changed

3 files changed

+86
-11
lines changed

compiler/rustc_middle/src/ty/context.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,34 @@ pub struct TypeckResults<'tcx> {
392392
/// (including late-bound regions) are replaced with free
393393
/// equivalents. This table is not used in codegen (since regions
394394
/// are erased there) and hence is not serialized to metadata.
395+
///
396+
/// This table also contains the "revealed" values for any `impl Trait`
397+
/// that appear in the signature and whose values are being inferred
398+
/// by this function.
399+
///
400+
/// # Example
401+
///
402+
/// ```rust
403+
/// fn foo(x: &u32) -> impl Debug { *x }
404+
/// ```
405+
///
406+
/// The function signature here would be:
407+
///
408+
/// ```
409+
/// for<'a> fn(&'a u32) -> Foo
410+
/// ```
411+
///
412+
/// where `Foo` is an opaque type created for this function.
413+
///
414+
///
415+
/// The *liberated* form of this would be
416+
///
417+
/// ```
418+
/// fn(&'a u32) -> u32
419+
/// ```
420+
///
421+
/// Note that `'a` is not bound (it would be an `ReFree`) and
422+
/// that the `Foo` opaque type is replaced by its hidden type.
395423
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
396424

397425
/// For each FRU expression, record the normalized types of the fields

compiler/rustc_mir/src/borrow_check/type_check/mod.rs

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,36 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12061206
Ok(())
12071207
}
12081208

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`
12091239
fn eq_opaque_type_and_type(
12101240
&mut self,
12111241
revealed_ty: Ty<'tcx>,
@@ -1240,6 +1270,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12401270
let tcx = infcx.tcx;
12411271
let param_env = self.param_env;
12421272
let body = self.body;
1273+
1274+
// the "concrete opaque types" maps
12431275
let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
12441276
let mut opaque_type_values = VecMap::new();
12451277

@@ -1252,6 +1284,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12521284
let mut obligations = ObligationAccumulator::default();
12531285

12541286
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.)
12551294
let (output_ty, opaque_type_map) =
12561295
obligations.add(infcx.instantiate_opaque_types(
12571296
anon_owner_def_id,
@@ -1267,6 +1306,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12671306
revealed_ty={:?}",
12681307
output_ty, opaque_type_map, revealed_ty
12691308
);
1309+
12701310
// Make sure that the inferred types are well-formed. I'm
12711311
// not entirely sure this is needed (the HIR type check
12721312
// didn't do this) but it seems sensible to prevent opaque
@@ -1282,6 +1322,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12821322
.eq(output_ty, revealed_ty)?,
12831323
);
12841324

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.
12851328
for &(opaque_type_key, opaque_decl) in &opaque_type_map {
12861329
let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
12871330
let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
@@ -1290,6 +1333,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
12901333
false
12911334
};
12921335

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`.
12931339
let concrete_ty = match concrete_opaque_types
12941340
.get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
12951341
{
@@ -1308,7 +1354,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13081354
Some(concrete_ty) => concrete_ty,
13091355
};
13101356
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)>`
13111360
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.
13121364
let renumbered_opaque_defn_ty =
13131365
renumber::renumber_regions(infcx, subst_opaque_defn_ty);
13141366

@@ -1318,8 +1370,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13181370
);
13191371

13201372
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)>`).
13231376
obligations.add(
13241377
infcx
13251378
.at(&ObligationCause::dummy(), param_env)

compiler/rustc_trait_selection/src/opaque_types.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_data_structures::sync::Lrc;
55
use rustc_data_structures::vec_map::VecMap;
66
use rustc_hir as hir;
77
use rustc_hir::def_id::{DefId, LocalDefId};
8-
use rustc_hir::Node;
98
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
109
use rustc_infer::infer::free_regions::FreeRegionRelations;
1110
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -982,8 +981,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
982981
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
983982
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
984983
};
985-
let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
986-
Some(Node::Item(item)) => match item.kind {
984+
let (in_definition_scope, origin) =
985+
match tcx.hir().expect_item(opaque_hir_id).kind {
987986
// Anonymous `impl Trait`
988987
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
989988
impl_trait_fn: Some(parent),
@@ -1000,12 +999,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
1000999
origin,
10011000
),
10021001
_ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
1003-
},
1004-
_ => bug!(
1005-
"expected item, found {}",
1006-
tcx.hir().node_to_string(opaque_hir_id),
1007-
),
1008-
};
1002+
};
10091003
if in_definition_scope {
10101004
let opaque_type_key =
10111005
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };

0 commit comments

Comments
 (0)