public IPythonType CreateSpecificType(IArgumentSet args, IPythonModule declaringModule, LocationInfo location = null)
        {
            location = location ?? LocationInfo.Empty;
            // Get declared generic parameters of the class, i.e. list of Ts in Generic[T1, T2, ...]
            var genericClassParameters = Bases.OfType <IGenericClassParameter>().ToArray();
            // Optimistically use the first one
            // TODO: handle optional generics as class A(Generic[_T1], Optional[Generic[_T2]])
            var genericClassParameter = genericClassParameters.FirstOrDefault();

            // Create map of names listed in Generic[...] in the class definition.
            // We will be filling the map with specific types, if any provided.
            var genericTypeDefinitions     = genericClassParameter?.TypeDefinitions ?? Array.Empty <IGenericTypeDefinition>();
            var genericClassTypeParameters = genericTypeDefinitions.ToDictionary(td => td.Name, td => td);

            var specificClassTypeParameters = new Dictionary <string, IPythonType>();
            var newBases = new List <IPythonType>();

            // Arguments passed are those of __init__ or it is a copy constructor.
            // They do not necessarily match all of the declared generic parameters.
            // Some generic parameters may be used to specify method return types or
            // method arguments and do not appear in the constructor argument list.
            // Figure out whatever specific types we can from the arguments.
            foreach (var a in args.Arguments)
            {
                // The argument may either match generic type definition of be a specific type
                // created off generic type. Consider '__init__(self, v: _T)' and
                // 'class A(Generic[K, V], Mapping[K, V])'.
                if (a.Type is IGenericTypeDefinition argTypeDefinition)
                {
                    // Parameter is annotated as generic type definition. Check if its generic type
                    // name matches any of the generic class parameters. I.e. if there is
                    // an argument like 'v: _T' we need to check if class has matching Generic[_T].
                    if (genericClassTypeParameters.ContainsKey(argTypeDefinition.Name))
                    {
                        // TODO: Check if specific type matches generic type definition constraints and report mismatches.
                        // Assign specific type.
                        if (a.Value is IMember m && m.GetPythonType() is IPythonType pt)
                        {
                            specificClassTypeParameters[argTypeDefinition.Name] = pt;
                        }
                        else
                        {
                            // TODO: report supplied parameter is not a type.
                        }
                    }
                    else
                    {
                        // TODO: report generic parameter name mismatch.
                    }
                }
        public IPythonType CreateSpecificType(IArgumentSet args)
        {
            // Get declared generic parameters of the class, i.e. list of Ts in Generic[T1, T2, ...]
            var genericClassParameters = Bases.OfType <IGenericClassParameter>().ToArray();
            // Optimistically use the first one
            // TODO: handle optional generics as class A(Generic[_T1], Optional[Generic[_T2]])
            var genericClassParameter = genericClassParameters.FirstOrDefault();

            // Create map of names listed in Generic[...] in the class definition.
            // We will be filling the map with specific types, if any provided.
            var genericTypeDefinitions     = genericClassParameter?.TypeDefinitions ?? Array.Empty <IGenericTypeDefinition>();
            var genericClassTypeParameters = genericTypeDefinitions.ToDictionary(td => td.Name, td => td);

            var specificClassTypeParameters = new Dictionary <string, IPythonType>();
            var newBases = new List <IPythonType>();

            // Arguments passed are those of __init__ or it is a copy constructor.
            // They do not necessarily match all of the declared generic parameters.
            // Some generic parameters may be used to specify method return types or
            // method arguments and do not appear in the constructor argument list.
            // Figure out whatever specific types we can from the arguments.
            foreach (var arg in args.Arguments)
            {
                // The argument may either match generic type definition of be a specific type
                // created off generic type. Consider '__init__(self, v: _T)' and
                // 'class A(Generic[K, V], Mapping[K, V])'.
                if (arg.Type is IGenericTypeDefinition argTypeDefinition)
                {
                    // Parameter is annotated as generic type definition. Check if its generic type
                    // name matches any of the generic class parameters. I.e. if there is
                    // an argument like 'v: _T' we need to check if class has matching Generic[_T].
                    if (genericClassTypeParameters.ContainsKey(argTypeDefinition.Name))
                    {
                        // TODO: Check if specific type matches generic type definition constraints and report mismatches.
                        // Assign specific type.
                        if (arg.Value is IMember m && m.GetPythonType() is IPythonType pt)
                        {
                            specificClassTypeParameters[argTypeDefinition.Name] = pt;
                        }
                        else
                        {
                            // TODO: report supplied parameter is not a type.
                        }
                    }
                    else
                    {
                        // TODO: report generic parameter name mismatch.
                    }
                    continue;
                }

                if (arg.Value is IMember member && !member.GetPythonType().IsUnknown())
                {
                    var type = member.GetPythonType();
                    // Type may be a specific type created off generic or just a type
                    // for the copy constructor. Consider 'class A(Generic[K, V], Mapping[K, V])'
                    // constructed as 'd = {1:'a', 2:'b'}; A(d)'. Here we look through bases
                    // and see if any matches the builtin type id. For example, Mapping or Dict
                    // will have BultinTypeId.Dict and we can figure out specific types from
                    // the content of the collection.
                    var b = _bases.OfType <IGenericType>().FirstOrDefault(x => x.TypeId == type.TypeId);
                    if (b != null && b.Parameters.Count > 0)
                    {
                        newBases.Add(type);
                        // Optimistically assign argument types if they match.
                        // Handle common cases directly.
                        GetSpecificTypeFromArgumentValue(b, arg.Value, specificClassTypeParameters);
                        continue;
                    }

                    // Any regular base match?
                    if (_bases.Any(x => x.TypeId == type.TypeId) && !type.Equals(this))
                    {
                        newBases.Add(type);
                    }
                }
            }