diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index ea815f6c0778..b4b1573286b6 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -467,16 +467,23 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
   }
 
   /** If `projection` is of the form T # Apply where `T` is an instance of a Lambda class,
-   *  and `other` is not a type lambda projection, then convert `other` to a type lambda `U`, and
-   *  continue with `T <:< U` if `inOrder` is true and `U <:< T` otherwise.
+   *  then
+   *    (1) if `other` is not a (possibly projected) type lambda, convert `other` to a type lambda `U`,
+   *        and continue with `T <:< U` if `inOrder` is true and `U <:< T` otherwise.
+   *    (2) if `other` is a already a type lambda,
+   *        continue with `T <:< other` if `inOrder` is true and `other <:< T` otherwise.
    */
   def compareHK(projection: NamedType, other: Type, inOrder: Boolean) =
     projection.name == tpnme.Apply && {
       val lambda = projection.prefix.LambdaClass(forcing = true)
-      lambda.exists && !other.isLambda &&
-        other.testLifted(lambda.typeParams,
-          if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
-          if (inOrder) Nil else classBounds(projection.prefix))
+      lambda.exists && {
+        if (!other.isLambda)
+          other.testLifted(lambda.typeParams,
+            if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
+            if (inOrder) Nil else classBounds(projection.prefix))
+        else if (inOrder) isSubType(projection.prefix, other)
+        else isSubType(other, projection.prefix)
+      }
     }
 
   /** The class symbols bounding the type of the `Apply` member of `tp` */
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index a3ddca5d99db..c5755e3fa7d8 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -462,7 +462,8 @@ trait Implicits { self: Typer =>
     }
 
     /** The expected type where parameters and uninstantiated typevars are replaced by wildcard types */
-    val wildProto = implicitProto(pt, wildApprox(_))
+    val approximator = new WildApproxMap(new mutable.ListBuffer[Type])
+    val wildProto = implicitProto(pt, wildApprox(_, approximator))
 
     /** Search failures; overridden in ExplainedImplicitSearch */
     protected def nonMatchingImplicit(ref: TermRef): SearchFailure = NoImplicitMatches
@@ -565,11 +566,23 @@ trait Implicits { self: Typer =>
         case result: SearchSuccess => result
         case result: AmbiguousImplicits => result
         case result: SearchFailure =>
-          searchImplicits(implicitScope(wildProto).eligible, contextual = false)
+          searchImplicits(implicitScope(wildProto, approximator.discarded).eligible, contextual = false)
       }
     }
 
-    def implicitScope(tp: Type): OfTypeImplicits = ctx.runInfo.implicitScope(tp, ctx)
+    /** The implicit scope corresponding to type `tp` and discarded parts `others`.
+     */
+    def implicitScope(tp: Type, others: Traversable[Type]): OfTypeImplicits = {
+      val typeScope = ctx.runInfo.implicitScope(tp, ctx)
+      if (others.isEmpty) typeScope
+      else {
+        val allCompanionRefs = new TermRefSet
+        allCompanionRefs ++= typeScope.companionRefs
+        for (tp <- others)
+          allCompanionRefs ++= ctx.runInfo.implicitScope(tp, ctx).companionRefs
+        new OfTypeImplicits(tp, allCompanionRefs)(ctx)
+      }
+    }
   }
 
   final class ExplainedImplicitSearch(pt: Type, argument: Tree, pos: Position)(implicit ctx: Context)
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index 9a012c30e0b0..622fbc6167ac 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -378,24 +378,31 @@ object ProtoTypes {
   final def wildApprox(tp: Type, theMap: WildApproxMap = null)(implicit ctx: Context): Type = tp match {
     case tp: NamedType => // default case, inlined for speed
       if (tp.symbol.isStatic) tp
-      else tp.derivedSelect(wildApprox(tp.prefix, theMap))
+      else {
+        val pre = wildApprox(tp.prefix, theMap)
+        val res = tp.derivedSelect(pre)
+        if ((res eq WildcardType) && (pre ne WildcardType) &&
+            (theMap != null) && (theMap.discarded != null))
+          theMap.discarded += pre
+        res
+      }
     case tp: RefinedType => // default case, inlined for speed
       tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap))
     case tp: TypeAlias => // default case, inlined for speed
       tp.derivedTypeAlias(wildApprox(tp.alias, theMap))
     case tp @ PolyParam(poly, pnum) =>
       ctx.typerState.constraint.entry(tp) match {
-        case bounds: TypeBounds => wildApprox(WildcardType(bounds))
-        case NoType => WildcardType(wildApprox(poly.paramBounds(pnum)).bounds)
-        case inst => wildApprox(inst)
+        case bounds: TypeBounds => wildApprox(WildcardType(bounds), theMap)
+        case NoType => WildcardType(wildApprox(poly.paramBounds(pnum), theMap).bounds)
+        case inst => wildApprox(inst, theMap)
       }
     case MethodParam(mt, pnum) =>
-      WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum))))
+      WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap)))
     case tp: TypeVar =>
-      wildApprox(tp.underlying)
+      wildApprox(tp.underlying, theMap)
     case tp: AndType =>
-      val tp1a = wildApprox(tp.tp1)
-      val tp2a = wildApprox(tp.tp2)
+      val tp1a = wildApprox(tp.tp1, theMap)
+      val tp2a = wildApprox(tp.tp2, theMap)
       def wildBounds(tp: Type) =
         if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
       if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
@@ -403,23 +410,29 @@ object ProtoTypes {
       else
         tp.derivedAndType(tp1a, tp2a)
     case tp: OrType =>
-      val tp1a = wildApprox(tp.tp1)
-      val tp2a = wildApprox(tp.tp2)
+      val tp1a = wildApprox(tp.tp1, theMap)
+      val tp2a = wildApprox(tp.tp2, theMap)
       if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
         WildcardType(tp1a.bounds | tp2a.bounds)
       else
         tp.derivedOrType(tp1a, tp2a)
     case tp: SelectionProto =>
-      tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto), NoViewsAllowed)
+      tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto, theMap), NoViewsAllowed)
     case tp: ViewProto =>
-      tp.derivedViewProto(wildApprox(tp.argType), wildApprox(tp.resultType))
+      tp.derivedViewProto(wildApprox(tp.argType, theMap), wildApprox(tp.resultType, theMap))
     case  _: ThisType | _: BoundType | NoPrefix => // default case, inlined for speed
       tp
     case _ =>
       (if (theMap != null) theMap else new WildApproxMap).mapOver(tp)
   }
 
-  private[ProtoTypes] class WildApproxMap(implicit ctx: Context) extends TypeMap {
+  /** A backing map for `wildApprox`.
+   *  @param discarded  A ListBuffer in which to store parts of intermediate steps of the approximation
+   *                    that have been discarded in a lookupRefined yielding a WildcardType.
+   *                    The idea is that these bits still matter as far as companion search is
+   *                    concerned, so they need to be kept somewhere.
+   */
+  private[dotty] class WildApproxMap(val discarded: mutable.ListBuffer[Type] = null)(implicit ctx: Context) extends TypeMap {
     def apply(tp: Type) = wildApprox(tp, this)
   }
 
diff --git a/tests/pos/i553-shuffle.scala b/tests/pos/i553-shuffle.scala
new file mode 100644
index 000000000000..105379918e88
--- /dev/null
+++ b/tests/pos/i553-shuffle.scala
@@ -0,0 +1,8 @@
+import scala.util.Random
+import scala.collection.immutable.List._
+object Test {
+  def test = {
+    val rand = new Random
+    rand.shuffle(List(1,2))//(List.canBuildFrom[Int]) // fails
+  }
+}