From 0f4a5ca33ceb22edd4f2cd12a03806331a2883ed Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 8 May 2019 15:56:39 -0400 Subject: [PATCH] Added some comments to lowering code. --- src/librustc/hir/lowering.rs | 53 ++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a49744aa523..06f9128cd22 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1361,26 +1361,73 @@ impl<'a> LoweringContext<'a> { } } + /// Given an associated type constraint like one of these: + /// + /// ``` + /// T: Iterator + /// ^^^^^^^^^^^ + /// T: Iterator + /// ^^^^^^^^^^^^ + /// ``` + /// + /// returns a `hir::TypeBinding` representing `Item`. fn lower_assoc_ty_constraint(&mut self, c: &AssocTyConstraint, itctx: ImplTraitContext<'_>) -> hir::TypeBinding { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx); + // Convert to a type representing the `T::Item` value. let ty = match c.kind { AssocTyConstraintKind::Equality { ref ty } => self.lower_ty(ty, itctx), AssocTyConstraintKind::Bound { ref bounds } => { - let (existential_desugaring, itctx) = match itctx { + // Piggy-back on the impl trait context to figure out + // the correct behavior. + let (desugar_to_impl_trait, itctx) = match itctx { + // We are in the return position: + // + // fn foo() -> impl Iterator + // + // so desugar to + // + // fn foo() -> impl Iterator ImplTraitContext::Existential(_) => (true, itctx), + + // We are in the argument position, but within a dyn type: + // + // fn foo(x: dyn Iterator) + // + // so desugar to + // + // fn foo(x: dyn Iterator) ImplTraitContext::Universal(_) if self.is_in_dyn_type => (true, itctx), + + // In `type Foo = dyn Iterator` we + // desugar to `type Foo = dyn Iterator` but we have to override the "impl trait + // context" to permit `impl Debug` in this + // position (it desugars then to an existential + // type). + // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => (true, ImplTraitContext::Existential(None)), + + // We are in the argument position, but not within a dyn type: + // + // fn foo(x: impl Iterator) + // + // so we leave it as is and this gets expanded in + // astconv to a bound like `::Item: + // Debug` where `T` is the type parameter for the + // `impl Iterator`. _ => (false, itctx), }; - if existential_desugaring { - // Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. + if desugar_to_impl_trait { + // Desugar `AssocTy: Bounds` into `AssocTy = impl + // Bounds`. We do this by constructing the HIR + // for "impl bounds" and then lowering that. let impl_trait_node_id = self.sess.next_node_id(); let parent_def_index = self.current_hir_id_owner.last().unwrap().0;