]> git.proxmox.com Git - rustc.git/blobdiff - vendor/chalk-ir/src/zip.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / chalk-ir / src / zip.rs
index 0dd964366ee295e335c6994cdde9a35e7b7e9acd..d7a70d366150ab9e16f48125396e532c1bc25da0 100644 (file)
@@ -21,52 +21,95 @@ use std::sync::Arc;
 /// represented by two distinct `ItemId` values, and the impl for
 /// `ItemId` requires that all `ItemId` in the two zipped values match
 /// up.
-pub trait Zipper<'i, I: Interner> {
+pub trait Zipper<'i, I: Interner + 'i> {
     /// Indicates that the two types `a` and `b` were found in matching spots.
-    fn zip_tys(&mut self, a: &Ty<I>, b: &Ty<I>) -> Fallible<()>;
+    fn zip_tys(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()>;
 
     /// Indicates that the two lifetimes `a` and `b` were found in matching spots.
-    fn zip_lifetimes(&mut self, a: &Lifetime<I>, b: &Lifetime<I>) -> Fallible<()>;
+    fn zip_lifetimes(
+        &mut self,
+        variance: Variance,
+        a: &Lifetime<I>,
+        b: &Lifetime<I>,
+    ) -> Fallible<()>;
 
     /// Indicates that the two consts `a` and `b` were found in matching spots.
-    fn zip_consts(&mut self, a: &Const<I>, b: &Const<I>) -> Fallible<()>;
+    fn zip_consts(&mut self, variance: Variance, a: &Const<I>, b: &Const<I>) -> Fallible<()>;
 
     /// Zips two values appearing beneath binders.
-    fn zip_binders<T>(&mut self, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
+    fn zip_binders<T>(
+        &mut self,
+        variance: Variance,
+        a: &Binders<T>,
+        b: &Binders<T>,
+    ) -> Fallible<()>
     where
-        T: HasInterner<Interner = I> + Zip<I> + Fold<I, I, Result = T>;
+        T: Clone + HasInterner<Interner = I> + Zip<I> + Fold<I, Result = T>;
+
+    /// Zips two substs
+    fn zip_substs(
+        &mut self,
+        ambient: Variance,
+        variances: Option<Variances<I>>,
+        a: &[GenericArg<I>],
+        b: &[GenericArg<I>],
+    ) -> Fallible<()>
+    where
+        Self: Sized,
+    {
+        for (i, (a, b)) in a.iter().zip(b.iter()).enumerate() {
+            let variance = variances
+                .as_ref()
+                .map(|v| v.as_slice(self.interner())[i])
+                .unwrap_or(Variance::Invariant);
+            Zip::zip_with(self, ambient.xform(variance), a, b)?;
+        }
+        Ok(())
+    }
 
-    /// Retreives the interner from the underlying zipper object
+    /// Retrieves the interner from the underlying zipper object
     fn interner(&self) -> &'i I;
+
+    /// Retrieves the `UnificationDatabase` from the underlying zipper object
+    fn unification_database(&self) -> &dyn UnificationDatabase<I>;
 }
 
 impl<'f, 'i, Z, I> Zipper<'i, I> for &'f mut Z
 where
-    I: Interner,
+    I: Interner + 'i,
     Z: Zipper<'i, I>,
 {
-    fn zip_tys(&mut self, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
-        (**self).zip_tys(a, b)
+    fn zip_tys(&mut self, variance: Variance, a: &Ty<I>, b: &Ty<I>) -> Fallible<()> {
+        (**self).zip_tys(variance, a, b)
     }
 
-    fn zip_lifetimes(&mut self, a: &Lifetime<I>, b: &Lifetime<I>) -> Fallible<()> {
-        (**self).zip_lifetimes(a, b)
+    fn zip_lifetimes(
+        &mut self,
+        variance: Variance,
+        a: &Lifetime<I>,
+        b: &Lifetime<I>,
+    ) -> Fallible<()> {
+        (**self).zip_lifetimes(variance, a, b)
     }
 
-    fn zip_consts(&mut self, a: &Const<I>, b: &Const<I>) -> Fallible<()> {
-        (**self).zip_consts(a, b)
+    fn zip_consts(&mut self, variance: Variance, a: &Const<I>, b: &Const<I>) -> Fallible<()> {
+        (**self).zip_consts(variance, a, b)
     }
 
-    fn zip_binders<T>(&mut self, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
+    fn zip_binders<T>(&mut self, variance: Variance, a: &Binders<T>, b: &Binders<T>) -> Fallible<()>
     where
-        T: HasInterner<Interner = I> + Zip<I> + Fold<I, I, Result = T>,
+        T: Clone + HasInterner<Interner = I> + Zip<I> + Fold<I, Result = T>,
     {
-        (**self).zip_binders(a, b)
+        (**self).zip_binders(variance, a, b)
     }
 
     fn interner(&self) -> &'i I {
         Z::interner(*self)
     }
+
+    fn unification_database(&self) -> &dyn UnificationDatabase<I> {
+        (**self).unification_database()
+    }
 }
 
 /// The `Zip` trait walks two values, invoking the `Zipper` methods where
@@ -81,37 +124,60 @@ where
     I: Interner,
 {
     /// Uses the zipper to walk through two values, ensuring that they match.
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i;
 }
 
 impl<'a, T: ?Sized + Zip<I>, I: Interner> Zip<I> for &'a T {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        <T as Zip<I>>::zip_with(zipper, a, b)
+        <T as Zip<I>>::zip_with(zipper, variance, a, b)
     }
 }
 
 impl<I: Interner> Zip<I> for () {
-    fn zip_with<'i, Z: Zipper<'i, I>>(_: &mut Z, _: &Self, _: &Self) -> Fallible<()> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(_: &mut Z, _: Variance, _: &Self, _: &Self) -> Fallible<()>
+    where
+        I: 'i,
+    {
         Ok(())
     }
 }
 
 impl<T: Zip<I>, I: Interner> Zip<I> for Vec<T> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        <[T] as Zip<I>>::zip_with(zipper, a, b)
+        <[T] as Zip<I>>::zip_with(zipper, variance, a, b)
     }
 }
 
 impl<T: Zip<I>, I: Interner> Zip<I> for [T] {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
@@ -120,7 +186,7 @@ impl<T: Zip<I>, I: Interner> Zip<I> for [T] {
         }
 
         for (a_elem, b_elem) in a.iter().zip(b) {
-            Zip::zip_with(zipper, a_elem, b_elem)?;
+            Zip::zip_with(zipper, variance, a_elem, b_elem)?;
         }
 
         Ok(())
@@ -128,68 +194,104 @@ impl<T: Zip<I>, I: Interner> Zip<I> for [T] {
 }
 
 impl<T: Zip<I>, I: Interner> Zip<I> for Arc<T> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        <T as Zip<I>>::zip_with(zipper, a, b)
+        <T as Zip<I>>::zip_with(zipper, variance, a, b)
     }
 }
 
 impl<T: Zip<I>, I: Interner> Zip<I> for Box<T> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        <T as Zip<I>>::zip_with(zipper, a, b)
+        <T as Zip<I>>::zip_with(zipper, variance, a, b)
     }
 }
 
 impl<T: Zip<I>, U: Zip<I>, I: Interner> Zip<I> for (T, U) {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        Zip::zip_with(zipper, &a.0, &b.0)?;
-        Zip::zip_with(zipper, &a.1, &b.1)?;
+        Zip::zip_with(zipper, variance, &a.0, &b.0)?;
+        Zip::zip_with(zipper, variance, &a.1, &b.1)?;
         Ok(())
     }
 }
 
 impl<I: Interner> Zip<I> for Ty<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        zipper.zip_tys(a, b)
+        zipper.zip_tys(variance, a, b)
     }
 }
 
 impl<I: Interner> Zip<I> for Lifetime<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        zipper.zip_lifetimes(a, b)
+        zipper.zip_lifetimes(variance, a, b)
     }
 }
 
 impl<I: Interner> Zip<I> for Const<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        zipper.zip_consts(a, b)
+        zipper.zip_consts(variance, a, b)
     }
 }
-impl<I: Interner, T: HasInterner<Interner = I> + Zip<I> + Fold<I, I, Result = T>> Zip<I>
-    for Binders<T>
+impl<I: Interner, T> Zip<I> for Binders<T>
+where
+    T: Clone + HasInterner<Interner = I> + Zip<I> + Fold<I, Result = T>,
 {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        zipper.zip_binders(a, b)
+        zipper.zip_binders(variance, a, b)
     }
 }
 
@@ -198,7 +300,12 @@ impl<I: Interner, T: HasInterner<Interner = I> + Zip<I> + Fold<I, I, Result = T>
 macro_rules! eq_zip {
     ($I:ident => $t:ty) => {
         impl<$I: Interner> Zip<$I> for $t {
-            fn zip_with<'i, Z: Zipper<'i, $I>>(_zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+            fn zip_with<'i, Z: Zipper<'i, $I>>(
+                _zipper: &mut Z,
+                _variance: Variance,
+                a: &Self,
+                b: &Self,
+            ) -> Fallible<()>
             where
                 I: 'i,
             {
@@ -227,18 +334,28 @@ eq_zip!(I => Mutability);
 eq_zip!(I => Scalar);
 
 impl<T: HasInterner<Interner = I> + Zip<I>, I: Interner> Zip<I> for InEnvironment<T> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
-        Zip::zip_with(zipper, &a.environment, &b.environment)?;
-        Zip::zip_with(zipper, &a.goal, &b.goal)?;
+        Zip::zip_with(zipper, variance, &a.environment, &b.environment)?;
+        Zip::zip_with(zipper, variance, &a.goal, &b.goal)?;
         Ok(())
     }
 }
 
 impl<I: Interner> Zip<I> for Environment<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
@@ -246,6 +363,7 @@ impl<I: Interner> Zip<I> for Environment<I> {
         assert_eq!(a.clauses.len(interner), b.clauses.len(interner)); // or different numbers of clauses
         Zip::zip_with(
             zipper,
+            variance,
             a.clauses.as_slice(interner),
             b.clauses.as_slice(interner),
         )?;
@@ -254,75 +372,95 @@ impl<I: Interner> Zip<I> for Environment<I> {
 }
 
 impl<I: Interner> Zip<I> for Goals<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
+        Zip::zip_with(zipper, variance, a.as_slice(interner), b.as_slice(interner))?;
         Ok(())
     }
 }
 
 impl<I: Interner> Zip<I> for ProgramClauses<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
+        Zip::zip_with(zipper, variance, a.as_slice(interner), b.as_slice(interner))?;
         Ok(())
     }
 }
 
 impl<I: Interner> Zip<I> for Constraints<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
+        Zip::zip_with(zipper, variance, a.as_slice(interner), b.as_slice(interner))?;
         Ok(())
     }
 }
 
 impl<I: Interner> Zip<I> for QuantifiedWhereClauses<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))?;
+        Zip::zip_with(zipper, variance, a.as_slice(interner), b.as_slice(interner))?;
         Ok(())
     }
 }
 
-impl<I: Interner> Zip<I> for Substitution<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
-    where
-        I: 'i,
-    {
-        let interner = zipper.interner();
-        Zip::zip_with(zipper, a.as_slice(interner), b.as_slice(interner))
-    }
-}
-
 // Annoyingly, Goal cannot use `enum_zip` because some variants have
 // two parameters, and I'm too lazy to make the macro account for the
 // relevant name mangling.
 impl<I: Interner> Zip<I> for Goal<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.data(interner), b.data(interner))
+        Zip::zip_with(zipper, variance, a.data(interner), b.data(interner))
     }
 }
 
 // I'm too lazy to make `enum_zip` support type parameters.
 impl<I: Interner> Zip<I> for VariableKind<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
@@ -330,7 +468,7 @@ impl<I: Interner> Zip<I> for VariableKind<I> {
             (VariableKind::Ty(a), VariableKind::Ty(b)) if a == b => Ok(()),
             (VariableKind::Lifetime, VariableKind::Lifetime) => Ok(()),
             (VariableKind::Const(ty_a), VariableKind::Const(ty_b)) => {
-                Zip::zip_with(zipper, ty_a, ty_b)
+                Zip::zip_with(zipper, variance, ty_a, ty_b)
             }
             (VariableKind::Ty(_), _)
             | (VariableKind::Lifetime, _)
@@ -340,21 +478,149 @@ impl<I: Interner> Zip<I> for VariableKind<I> {
 }
 
 impl<I: Interner> Zip<I> for GenericArg<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.data(interner), b.data(interner))
+        Zip::zip_with(zipper, variance, a.data(interner), b.data(interner))
     }
 }
 
 impl<I: Interner> Zip<I> for ProgramClause<I> {
-    fn zip_with<'i, Z: Zipper<'i, I>>(zipper: &mut Z, a: &Self, b: &Self) -> Fallible<()>
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
+    where
+        I: 'i,
+    {
+        let interner = zipper.interner();
+        Zip::zip_with(zipper, variance, a.data(interner), b.data(interner))
+    }
+}
+
+impl<I: Interner> Zip<I> for TraitRef<I> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
+    where
+        I: 'i,
+    {
+        let interner = zipper.interner();
+        Zip::zip_with(zipper, variance, &a.trait_id, &b.trait_id)?;
+        zipper.zip_substs(
+            variance,
+            None,
+            a.substitution.as_slice(interner),
+            b.substitution.as_slice(interner),
+        )
+    }
+}
+
+impl<I: Interner> Zip<I> for ProjectionTy<I> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
     where
         I: 'i,
     {
         let interner = zipper.interner();
-        Zip::zip_with(zipper, a.data(interner), b.data(interner))
+        Zip::zip_with(zipper, variance, &a.associated_ty_id, &b.associated_ty_id)?;
+        zipper.zip_substs(
+            variance,
+            None,
+            a.substitution.as_slice(interner),
+            b.substitution.as_slice(interner),
+        )
+    }
+}
+
+impl<I: Interner> Zip<I> for OpaqueTy<I> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
+    where
+        I: 'i,
+    {
+        let interner = zipper.interner();
+        Zip::zip_with(zipper, variance, &a.opaque_ty_id, &b.opaque_ty_id)?;
+        zipper.zip_substs(
+            variance,
+            None,
+            a.substitution.as_slice(interner),
+            b.substitution.as_slice(interner),
+        )
+    }
+}
+
+impl<I: Interner> Zip<I> for DynTy<I> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
+    where
+        I: 'i,
+    {
+        Zip::zip_with(
+            zipper,
+            variance.xform(Variance::Invariant),
+            &a.bounds,
+            &b.bounds,
+        )?;
+        Zip::zip_with(
+            zipper,
+            variance.xform(Variance::Contravariant),
+            &a.lifetime,
+            &b.lifetime,
+        )?;
+        Ok(())
+    }
+}
+
+impl<I: Interner> Zip<I> for FnSubst<I> {
+    fn zip_with<'i, Z: Zipper<'i, I>>(
+        zipper: &mut Z,
+        variance: Variance,
+        a: &Self,
+        b: &Self,
+    ) -> Fallible<()>
+    where
+        I: 'i,
+    {
+        let interner = zipper.interner();
+        // Parameters
+        for (a, b) in a.0.as_slice(interner)[..a.0.len(interner) - 1]
+            .iter()
+            .zip(b.0.as_slice(interner)[..b.0.len(interner) - 1].iter())
+        {
+            Zip::zip_with(zipper, variance.xform(Variance::Contravariant), a, b)?;
+        }
+        // Return type
+        Zip::zip_with(
+            zipper,
+            variance,
+            a.0.iter(interner).last().unwrap(),
+            b.0.iter(interner).last().unwrap(),
+        )?;
+        Ok(())
     }
 }