@NotNull
    private List<AnalyzeArgumentResult> analyzeContainerMapping(@NotNull PyCallableParameter container,
                                                                @NotNull List<PyExpression> arguments,
                                                                @NotNull PyTypeChecker.GenericSubstitutions substitutions) {
      final PyType expected = container.getArgumentType(myTypeEvalContext);

      if (container.isPositionalContainer() && expected instanceof PyVariadicType) {
        PyUnpackedTupleType argumentTypes = PyUnpackedTupleTypeImpl.create(ContainerUtil.map(arguments, myTypeEvalContext::getType));
        boolean matched = matchParameterAndArgument(expected, argumentTypes, null, substitutions);
        return ContainerUtil.map(arguments, argument -> {
          PyType expectedWithSubstitutions = substituteGenerics(expected, substitutions);
          // TODO Don't duplicate the message of each argument, highlight an entire series of them
          return new AnalyzeArgumentResult(argument, expected, expectedWithSubstitutions, argumentTypes, matched);
        });
      }

      // For an expected type with generics we have to match all the actual types against it in order to do proper generic unification
      if (PyTypeChecker.hasGenerics(expected, myTypeEvalContext)) {
        // First collect type parameter substitutions by matching the expected type with the union.
        PyType actualJoin = PyUnionType.union(ContainerUtil.map(arguments, myTypeEvalContext::getType));
        matchParameterAndArgument(expected, actualJoin, null, substitutions);
        PyType expectedWithSubstitutions = substituteGenerics(expected, substitutions);
        return ContainerUtil.map(arguments, argument -> {
          // Then match each argument type against the expected type after these substitutions.
          PyType actual = myTypeEvalContext.getType(argument);
          boolean matched = matchParameterAndArgument(expected, actual, argument, substitutions);
          return new AnalyzeArgumentResult(argument, expected, expectedWithSubstitutions, actual, matched);
        });
      }
      else {
        return ContainerUtil.map(
          arguments,
          argument -> {
            PyType actual = myTypeEvalContext.getType(argument);
            boolean matched = matchParameterAndArgument(expected, actual, argument, substitutions);
            PyType expectedWithSubstitutions = substituteGenerics(expected, substitutions);
            return new AnalyzeArgumentResult(argument, expected, expectedWithSubstitutions, actual, matched);
          }
        );
      }
    }
@NotNull
    private List<AnalyzeArgumentResult> analyzeContainerMapping(@NotNull PyCallableParameter container,
                                                                @NotNull List<PyExpression> arguments,
                                                                @NotNull PyTypeChecker.GenericSubstitutions substitutions)