internal static string GenerateMutualSafeRec(GeneratorExecutionContext context, IReadOnlyList <RecursiveMethodInfo> methodInfos)
        {
            var firstMethodInfo = methodInfos.First();

            if (string.IsNullOrEmpty(firstMethodInfo.CodeGenProps.MutualRecursionId))
            {
                throw new ArgumentException($"Empty {nameof(SafeRecursionCodeGenProps.MutualRecursionId)} in the first methodInfo of {nameof(methodInfos)}.");
            }

            if (methodInfos.Count == 1)
            {
                // Warn the user but continue anyway as we should generate a working code anyway if there
                // is actually exactly 1 MutualRecursionId. The code will be slower but it should work.
                context.ReportConfigurationWarning(firstMethodInfo.MethodSyntax,
                                                   $"Suspiciously only one method is found for the mutual recursive group '{firstMethodInfo.CodeGenProps.MutualRecursionId}'");
            }

            // TODO really check that all GenericParams and ConstraintClauses for all methodInfos are
            // the same. If it is not so, the compilation probably will fail anyway but the message will
            // not be very user-friendly
            foreach (var methodInfo in methodInfos)
            {
                if ((methodInfo.GenericParams != firstMethodInfo.GenericParams) ||
                    (methodInfo.ConstraintClauses != firstMethodInfo.ConstraintClauses))
                {
                    // string equality check is not really correct so only generate a warning
                    context.ReportConfigurationWarning(methodInfo.MethodSyntax,
                                                       $"Suspiciously generic methods '{firstMethodInfo.MethodName}' and '{methodInfo.MethodName}' have differently looking generic params"
                                                       + $" '{firstMethodInfo.GenericParams}' '{firstMethodInfo.ConstraintClauses}'"
                                                       + $" != '{methodInfo.GenericParams}' '{methodInfo.ConstraintClauses}'");
                }
            }

            var classSyntax = (ClassDeclarationSyntax)firstMethodInfo.MethodSyntax.Parent;
            var classSymbol = firstMethodInfo.MethodSymbol.ContainingType;
            var recursionId = firstMethodInfo.CodeGenProps.MutualRecursionId;
            var classInfo   = new RecursiveCalculatorClassInfo(classSyntax, classSymbol, isMultiSite: true, recursionId,
                                                               firstMethodInfo.GenericParams, firstMethodInfo.ConstraintClauses,
                                                               paramsStructName: recursionId + RecursiveCalculatorClassInfo.DispatchStructSuffix);

            return(new CalculatorClassGenerator(context, classInfo, methodInfos).GenerateAll());
        }