예제 #1
0
        internal ConstructorFunction(BuiltinFunction realTarget, IList<MethodBase> constructors)
            : base("__new__", ArrayUtils.ToArray(GetTargetsValidateFunction(realTarget)), realTarget.DeclaringType, FunctionType.Function | FunctionType.AlwaysVisible) {

            base.Name = realTarget.Name;
            base.FunctionType = realTarget.FunctionType;
            this._ctors = ArrayUtils.ToArray(constructors);
        }
        private object GetOverload(Type[] sig, IList<MethodBase> targets, bool wrapCtors) {
            // We can still end up with more than one target since generic and non-generic
            // methods can share the same name and signature. So we'll build up a new
            // reflected method with all the candidate targets. A caller can then index this
            // reflected method if necessary in order to provide generic type arguments and
            // fully disambiguate the target.

            // Search for targets with the right number of arguments.
            BuiltinFunction bf;
            BuiltinFunction.TypeList tl = new BuiltinFunction.TypeList(sig);
            lock (_function.OverloadDictionary) {
                if (!_function.OverloadDictionary.TryGetValue(tl, out bf)) {
                    MethodBase[] newTargets = FindMatchingTargets(sig, targets);

                    if (targets == null)
                        throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}", sig));    // TODO: Sig to usable display

                    _function.OverloadDictionary[tl] = bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
                }
            }

            if (_instance != null) {
                return bf.BindToInstance(_instance);
            } else if (wrapCtors) {
                return GetTargetFunction(bf);
            } else {
                return bf;
            }
        }
        private object CallGetter(CodeContext context, PythonType owner, SiteLocalStorage <CallSite <Func <CallSite, CodeContext, object, object> > > storage, object instance)
        {
            if (NeedToReturnProperty(instance, Getter))
            {
                return(this);
            }

            if (Getter.Length == 0)
            {
                throw new MissingMemberException("unreadable property");
            }

            if (owner == null)
            {
                owner = DynamicHelpers.GetPythonType(instance);
            }

            // this matches the logic in the default binder when it does a property get.  We
            // need to duplicate it here to be consistent for all gets.
            MethodInfo[] members = Getter;

            Type type = owner.UnderlyingSystemType;

            if (Getter.Length > 1)
            {
                // if we were given multiple members pick the member closest to the type...
                Type       bestMemberDeclaringType = Getter[0].DeclaringType;
                MethodInfo bestMember = Getter[0];

                for (int i = 1; i < Getter.Length; i++)
                {
                    MethodInfo mt = Getter[i];
                    if (!IsApplicableForType(type, mt))
                    {
                        continue;
                    }

                    if (Getter[i].DeclaringType.IsSubclassOf(bestMemberDeclaringType) ||
                        !IsApplicableForType(type, bestMember))
                    {
                        bestMember = Getter[i];
                        bestMemberDeclaringType = Getter[i].DeclaringType;
                    }
                }
                members = new MethodInfo[] { bestMember };
            }

            BuiltinFunction target = PythonTypeOps.GetBuiltinFunction(type, __name__, members);

            // Workaround for https://github.com/IronLanguages/ironpython3/issues/1326
            Debug.Assert(members.Length == 1);
            if (members[0].IsStatic)
            {
                instance = null;
            }

            return(target.Call0(context, storage, instance));
        }
예제 #4
0
        public BuiltinFunctionInfo(BuiltinFunction function, ProjectState projectState)
            : base(ClrModule.GetPythonType(typeof(BuiltinFunction)), projectState)
        {
            // TODO: get return information, parameters, members
            _function = function;

            _returnTypes = Utils.GetReturnTypes(function, projectState);
            _doc = null;
        }
예제 #5
0
 internal static void CheckSelfWorker(CodeContext/*!*/ context, object self, BuiltinFunction template) {
     // to a fast check on the CLR types, if they match we can avoid the slower
     // check that involves looking up dynamic types. (self can be null on
     // calls like set.add(None) 
     Type selfType = CompilerHelpers.GetType(self);
     if (selfType != template.DeclaringType && !template.DeclaringType.IsAssignableFrom(selfType)) {
         // if a conversion exists to the type allow the call.
         context.LanguageContext.Binder.Convert(self, template.DeclaringType);
     }
 }
예제 #6
0
        internal static BuiltinFunction/*!*/ MakeOrAdd(BuiltinFunction existing, string name, MethodBase mi, Type declaringType, FunctionType funcType) {
            PythonBinder.AssertNotExtensionType(declaringType);

            if (existing != null) {
                existing._data.AddMethod(mi);
                return existing;
            } else {
                return MakeMethod(name, mi, declaringType, funcType);
            }
        }
예제 #7
0
 internal static void CheckSelfWorker(CodeContext/*!*/ context, object self, BuiltinFunction template) {
     // to a fast check on the CLR types, if they match we can avoid the slower
     // check that involves looking up dynamic types. (self can be null on
     // calls like set.add(None) 
     Type selfType = CompilerHelpers.GetType(self);
     if (selfType != template.DeclaringType && !template.DeclaringType.IsAssignableFrom(selfType)) {
         // if a conversion exists to the type allow the call.
         context.LanguageContext.Binder.Convert(self, template.DeclaringType);
     }
 }
예제 #8
0
        internal BuiltinFunctionOverloadResult(ProjectState state, BuiltinFunction overload, int removedParams, string name, params ParameterResult[] extraParams)
            : base(null, name)
        {
            _overload = overload;
            _extraParameters = extraParams;
            _removedParams = removedParams;
            _projectState = state;

            CalculateDocumentation();
        }
예제 #9
0
        protected override object GetTargetFunction(BuiltinFunction bf)
        {
            // return a function that's bound to the overloads, we'll
            // the user then calls this w/ the dynamic type, and the bound
            // function drops the class & calls the overload.
            if (bf.Targets[0].DeclaringType != typeof(InstanceOps))
            {
                return(new ConstructorFunction(InstanceOps.OverloadedNew, bf.Targets).BindToInstance(bf));
            }

            return(base.GetTargetFunction(bf));
        }
예제 #10
0
        /// <summary>
        /// Returns a BuiltinFunction bound to the provided type arguments.  Returns null if the binding
        /// cannot be performed.
        /// </summary>
        internal BuiltinFunction MakeGenericMethod(Type[] types)
        {
            TypeList tl = new TypeList(types);

            // check for cached method first...
            BuiltinFunction bf;

            if (_data.BoundGenerics != null)
            {
                lock (_data.BoundGenerics) {
                    if (_data.BoundGenerics.TryGetValue(tl, out bf))
                    {
                        return(bf);
                    }
                }
            }

            // Search for generic targets with the correct arity (number of type parameters).
            // Compatible targets must be MethodInfos by definition (constructors never take
            // type arguments).
            List <MethodBase> targets = new List <MethodBase>(Targets.Count);

            foreach (MethodBase mb in Targets)
            {
                MethodInfo mi = mb as MethodInfo;
                if (mi == null)
                {
                    continue;
                }
                if (mi.ContainsGenericParameters && mi.GetGenericArguments().Length == types.Length)
                {
                    targets.Add(mi.MakeGenericMethod(types));
                }
            }

            if (targets.Count == 0)
            {
                return(null);
            }

            // Build a new ReflectedMethod that will contain targets with bound type arguments & cache it.
            bf = new BuiltinFunction(Name, targets.ToArray(), DeclaringType, FunctionType);

            EnsureBoundGenericDict();

            lock (_data.BoundGenerics) {
                _data.BoundGenerics[tl] = bf;
            }

            return(bf);
        }
예제 #11
0
 /// <summary>
 /// Trys to get the BuiltinFunction for the given name on the type of the provided MetaObject.  
 /// 
 /// Succeeds if the MetaObject is a BuiltinFunction or BuiltinMethodDescriptor.
 /// </summary>
 internal static bool TryGetStaticFunction(BinderState/*!*/ state, SymbolId op, DynamicMetaObject/*!*/ mo, out BuiltinFunction function) {
     PythonType type = MetaPythonObject.GetPythonType(mo);
     function = null;
     if (op != SymbolId.Empty) {
         PythonTypeSlot xSlot;
         object val;
         if (type.TryResolveSlot(state.Context, op, out xSlot) &&
             xSlot.TryGetValue(state.Context, null, type, out val)) {
             function = TryConvertToBuiltinFunction(val);
             if (function == null) return false;
         }
     }
     return true;
 }
예제 #12
0
        private bool Equals(BuiltinFunction other)
        {
            if (this == other)
            {
                return(true);
            }

            if (!IsUnbound && !other.IsUnbound)
            {
                return(_instance == other._instance && _data == other._data);
            }

            return(false);
        }
예제 #13
0
 /// <summary>
 /// Tries to get the BuiltinFunction for the given name on the type of the provided MetaObject.  
 /// 
 /// Succeeds if the MetaObject is a BuiltinFunction or BuiltinMethodDescriptor.
 /// </summary>
 internal static bool TryGetStaticFunction(PythonContext/*!*/ state, string op, DynamicMetaObject/*!*/ mo, out BuiltinFunction function) {
     PythonType type = MetaPythonObject.GetPythonType(mo);
     function = null;
     if (!String.IsNullOrEmpty(op)) {
         PythonTypeSlot xSlot;
         object val;
         if (type.TryResolveSlot(state.SharedContext, op, out xSlot) &&
             xSlot.TryGetValue(state.SharedContext, null, type, out val)) {
             function = TryConvertToBuiltinFunction(val);
             if (function == null) return false;
         }
     }
     return true;
 }
예제 #14
0
        private object GetOverload(Type[] sig, IList <MethodBase> targets, bool wrapCtors)
        {
            // We can still end up with more than one target since generic and non-generic
            // methods can share the same name and signature. So we'll build up a new
            // reflected method with all the candidate targets. A caller can then index this
            // reflected method if necessary in order to provide generic type arguments and
            // fully disambiguate the target.

            BuiltinFunction bf;

            BuiltinFunction.TypeList tl = new BuiltinFunction.TypeList(sig);
            lock (_function.OverloadDictionary) {
                if (!_function.OverloadDictionary.TryGetValue(tl, out bf))
                {
                    MethodBase[] newTargets = FindMatchingTargets(sig, targets, true);

                    if (newTargets.Length == 0)
                    {
                        // If no overload was found, check also using CodeContext for backward compatibility
                        newTargets = FindMatchingTargets(sig, targets, false);
                    }

                    if (newTargets.Length == 0)
                    {
                        ThrowOverloadException(sig, targets);
                    }
                    else
                    {
                        _function.OverloadDictionary[tl] = bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
                    }
                }
            }

            if (_instance != null)
            {
                return(bf.BindToInstance(_instance));
            }
            else if (wrapCtors)
            {
                return(GetTargetFunction(bf));
            }
            else
            {
                return(bf);
            }
        }
예제 #15
0
        /// <summary>
        /// Use indexing on generic methods to provide a new reflected method with targets bound with
        /// the supplied type arguments.
        /// </summary>
        public BuiltinFunction /*!*/ this[params object[] key] {
            get {
                // Retrieve the list of type arguments from the index.
                Type[] types = new Type[key.Length];
                for (int i = 0; i < types.Length; i++)
                {
                    types[i] = Converter.ConvertToType(key[i]);
                }

                BuiltinFunction res = MakeGenericMethod(types);
                if (res == null)
                {
                    bool hasGenerics = false;
                    foreach (MethodBase mb in Targets)
                    {
                        MethodInfo mi = mb as MethodInfo;
                        if (mi != null && mi.ContainsGenericParameters)
                        {
                            hasGenerics = true;
                        }
                    }

                    if (hasGenerics)
                    {
                        throw PythonOps.TypeError(string.Format("bad type args to this generic method {0}", Name));
                    }
                    else
                    {
                        throw PythonOps.TypeError(string.Format("{0} is not a generic method and is unsubscriptable", Name));
                    }
                }

                if (IsUnbound)
                {
                    return(res);
                }

                return(new BuiltinFunction(_instance, res._data));
            }
        }
예제 #16
0
        private object GetOverload(Type[] sig, IList <MethodBase> targets, bool wrapCtors)
        {
            // We can still end up with more than one target since generic and non-generic
            // methods can share the same name and signature. So we'll build up a new
            // reflected method with all the candidate targets. A caller can then index this
            // reflected method if necessary in order to provide generic type arguments and
            // fully disambiguate the target.

            // Search for targets with the right number of arguments.
            BuiltinFunction bf;

            BuiltinFunction.TypeList tl = new BuiltinFunction.TypeList(sig);
            lock (_function.OverloadDictionary) {
                if (!_function.OverloadDictionary.TryGetValue(tl, out bf))
                {
                    MethodBase[] newTargets = FindMatchingTargets(sig, targets);

                    if (targets == null)
                    {
                        throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}", sig));    // TODO: Sig to usable display
                    }
                    _function.OverloadDictionary[tl] = bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
                }
            }

            if (_instance != null)
            {
                return(bf.BindToInstance(_instance));
            }
            else if (wrapCtors)
            {
                return(GetTargetFunction(bf));
            }
            else
            {
                return(bf);
            }
        }
예제 #17
0
        public int __cmp__(CodeContext /*!*/ context, [NotNull] BuiltinFunction /*!*/ other)
        {
            if (other == this)
            {
                return(0);
            }

            if (!IsUnbound && !other.IsUnbound)
            {
                int result = PythonOps.Compare(__self__, other.__self__);
                if (result != 0)
                {
                    return(result);
                }

                if (_data == other._data)
                {
                    return(0);
                }
            }

            int res = String.CompareOrdinal(__name__, other.__name__);

            if (res != 0)
            {
                return(res);
            }

            res = String.CompareOrdinal(Get__module__(context), other.Get__module__(context));
            if (res != 0)
            {
                return(res);
            }

            long lres = IdDispenser.GetId(this) - IdDispenser.GetId(other);

            return(lres > 0 ? 1 : -1);
        }
예제 #18
0
 public BuiltinNewAdapter(ArgumentValues/*!*/ ai, PythonType/*!*/ creating, BuiltinFunction/*!*/ ctor, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _creating = creating;
     _ctor = ctor;
 }
예제 #19
0
 public bool __ne__([NotNone] BuiltinFunction /*!*/ other) => !Equals(other);
예제 #20
0
 internal void SetConstructor(BuiltinFunction ctor) {
     _ctor = ctor;
 }
예제 #21
0
 public SpecializedBuiltinFunction(ProjectState state, BuiltinFunction function, Func<CallExpression, AnalysisUnit, ISet<Namespace>[], ISet<Namespace>> call)
     : base(function, state)
 {
     _call = call;
 }
            /// <summary>
            /// Creates a new CallableObject.  If BuiltinFunction is available we'll create a BuiltinCallable otherwise
            /// we create a SlotCallable.
            /// </summary>
            public static Callable MakeCallable(PythonContext/*!*/ binder, PythonIndexType op, BuiltinFunction itemFunc, PythonTypeSlot itemSlot) {
                if (itemFunc != null) {
                    // we'll call a builtin function to produce the rule
                    return new BuiltinCallable(binder, op, itemFunc);
                } else if (itemSlot != null) {
                    // we'll call a PythonTypeSlot to produce the rule
                    return new SlotCallable(binder, op, itemSlot);
                }

                return null;
            }
예제 #23
0
        private static BuiltinFunction CheckAlwaysNotImplemented(BuiltinFunction xBf) {
            if (xBf != null) {
                bool returnsValue = false;
                foreach (MethodBase mb in xBf.Targets) {
                    if (mb.GetReturnType() != typeof(NotImplementedType) ||
                        mb.IsDefined(typeof(Python3WarningAttribute), true)) {
                        returnsValue = true;
                        break;
                    }
                }

                if (!returnsValue) {
                    xBf = null;
                }
            }
            return xBf;
        }
 private static ICollection<OverloadDoc> GetBuiltinFunctionOverloads(BuiltinFunction bf) {
     OverloadDoc[] res = new OverloadDoc[bf.Targets.Count];
     for (int i = 0; i < bf.Targets.Count; i++) {
         res[i] = GetOverloadDoc(bf.__name__, bf.Targets[i]);
     }
     return res;
 }
예제 #25
0
 private void MakeGetFunc()
 {
     _getfunc = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, _getter);
 }
예제 #26
0
 private static IList<MethodBase> GetTargetsValidateFunction(BuiltinFunction realTarget) {
     ContractUtils.RequiresNotNull(realTarget, "realTarget");
     return realTarget.Targets;
 }
예제 #27
0
 public bool __eq__([NotNull] BuiltinFunction /*!*/ other) => Equals(other);
        private PythonTuple _allOverloads;  // overloads are stored here and may be bound to an instance

        public BuiltinFunctionOverloadMapper(BuiltinFunction builtinFunction, object instance) {
            this._function = builtinFunction;
            this._instance = instance;
        }
        protected override object GetTargetFunction(BuiltinFunction bf) {
            // return a function that's bound to the overloads, we'll
            // the user then calls this w/ the dynamic type, and the bound
            // function drops the class & calls the overload.
            if (bf.Targets[0].DeclaringType != typeof(InstanceOps)) {
                return new ConstructorFunction(InstanceOps.OverloadedNew, bf.Targets).BindToInstance(bf);
            }

            return base.GetTargetFunction(bf);
        }
 protected virtual object GetTargetFunction(BuiltinFunction bf) {
     return bf;
 }
예제 #31
0
 public BuiltinInitAdapter(ArgumentValues/*!*/ ai, BuiltinFunction/*!*/ method, PythonContext/*!*/ state, Expression/*!*/ codeContext)
     : base(ai, state, codeContext) {
     _method = method;
 }
예제 #32
0
 internal ClassMethodDescriptor(BuiltinFunction func) {
     this._func = func;
 }
예제 #33
0
 private static IList <MethodBase> GetTargetsValidateFunction(BuiltinFunction realTarget)
 {
     ContractUtils.RequiresNotNull(realTarget, "realTarget");
     return(realTarget.Targets);
 }
예제 #34
0
        internal object CallTarget(CodeContext context, SiteLocalStorage <CallSite <Func <CallSite, CodeContext, object, object[], object> > > storage, MethodInfo[] targets, object instance, params object[] args)
        {
            BuiltinFunction target = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, targets);

            return(target.Call(context, storage, instance, args));
        }
예제 #35
0
        private static BuiltinFunction CheckAlwaysNotImplemented(BuiltinFunction xBf) {
            if (xBf != null) {
                bool returnsValue = false;
                foreach (MethodBase mb in xBf.Targets) {
                    if (CompilerHelpers.GetReturnType(mb) != typeof(NotImplementedType)) {
                        returnsValue = true;
                        break;
                    }
                }

                if (!returnsValue) {
                    xBf = null;
                }
            }
            return xBf;
        }
예제 #36
0
 internal BuiltinMethodDescriptor(BuiltinFunction/*!*/ function) {
     _template = function;
 }
예제 #37
0
        internal static ConstructorFunction GetConstructor(Type type, BuiltinFunction realTarget, params MethodBase[] mems) {
            ConstructorFunction res = null;

            if (mems.Length != 0) {
                ReflectionCache.MethodBaseCache cache = new ReflectionCache.MethodBaseCache("__new__", mems);
                lock (_ctors) {
                    if (!_ctors.TryGetValue(cache, out res)) {
                        _ctors[cache] = res = new ConstructorFunction(realTarget, mems);
                    }
                }
            }

            return res;
        }
예제 #38
0
 public MetaBuiltinFunction(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, BuiltinFunction/*!*/ value)
     : base(expression, BindingRestrictions.Empty, value) {
     Assert.NotNull(value);
 }
예제 #39
0
        private PythonTuple _allOverloads;  // overloads are stored here and may be bound to an instance

        public BuiltinFunctionOverloadMapper(BuiltinFunction builtinFunction, object instance)
        {
            this._function = builtinFunction;
            this._instance = instance;
        }
예제 #40
0
 private void MakeGetFunc() {
     _getfunc = PythonTypeOps.GetBuiltinFunction(DeclaringType, __name__, _getter);
 }
예제 #41
0
 protected virtual object GetTargetFunction(BuiltinFunction bf)
 {
     return(bf);
 }
            public BuiltinCallable(PythonContext/*!*/ binder, PythonIndexType op, BuiltinFunction/*!*/ func)
                : base(binder, op) {
                Assert.NotNull(func);

                _bf = func;
            }
예제 #43
0
            public BuiltinCallable(BinderState/*!*/ binder, string op, BuiltinFunction/*!*/ func)
                : base(binder, op) {
                Assert.NotNull(func);

                _bf = func;
            }
예제 #44
0
        internal static PythonTypeSlot/*!*/ GetFinalSlotForFunction(BuiltinFunction/*!*/ func) {
            if ((func.FunctionType & FunctionType.Method) != 0) {
                BuiltinMethodDescriptor desc;
                lock (_methodCache) {
                    if (!_methodCache.TryGetValue(func, out desc)) {
                        _methodCache[func] = desc = new BuiltinMethodDescriptor(func);
                    }

                    return desc;
                }
            }

            if (func.Targets[0].IsDefined(typeof(ClassMethodAttribute), true)) {
                lock (_classMethodCache) {
                    ClassMethodDescriptor desc;
                    if (!_classMethodCache.TryGetValue(func, out desc)) {
                        _classMethodCache[func] = desc = new ClassMethodDescriptor(func);
                    }

                    return desc;
                }
            }

            return func;
        }
예제 #45
0
        private void InitializeUserType(CodeContext/*!*/ context, string name, PythonTuple bases, IAttributesCollection vars) {
            // we don't support overriding __mro__
            if (vars.ContainsKey(Symbols.MethodResolutionOrder))
                throw new NotImplementedException("Overriding __mro__ of built-in types is not implemented");

            // cannot override mro when inheriting from type
            if (vars.ContainsKey(SymbolTable.StringToId("mro"))) {
                foreach (object o in bases) {
                    PythonType dt = o as PythonType;
                    if (dt != null && dt.IsSubclassOf(TypeCache.PythonType)) {
                        throw new NotImplementedException("Overriding type.mro is not implemented");
                    }
                }
            }

            bases = ValidateBases(bases);

            _name = name;
            _bases = GetBasesAsList(bases).ToArray();
            _pythonContext = PythonContext.GetContext(context);
            _resolutionOrder = CalculateMro(this, _bases);

            foreach (PythonType pt in _bases) {
                pt.AddSubType(this);
                _originalSlotCount += pt.SlotCount;
            }

            BuildUserTypeDictionary(context, vars);
            InitializeSlots(name, bases, vars);

            // calculate the .NET type once so it can be used for things like super calls
            _underlyingSystemType = NewTypeMaker.GetNewType(name, bases, vars);

            // then let the user intercept and rewrite the type - the user can't create
            // instances of this type yet.
            _underlyingSystemType = __clrtype__();
            
            // finally assign the ctors from the real type the user provided
            _ctor = BuiltinFunction.MakeMethod(Name, _underlyingSystemType.GetConstructors(), _underlyingSystemType, FunctionType.Function);
        }
예제 #46
0
 internal BuiltinMethodDescriptor(BuiltinFunction /*!*/ function)
 {
     _template = function;
 }
예제 #47
0
        /// <summary>
        /// Returns a BuiltinFunction bound to the provided type arguments.  Returns null if the binding
        /// cannot be performed.
        /// </summary>
        internal BuiltinFunction MakeGenericMethod(Type[] types) {
            TypeList tl = new TypeList(types);

            // check for cached method first...
            BuiltinFunction bf;
            if (_data.BoundGenerics != null) {
                lock (_data.BoundGenerics) {
                    if (_data.BoundGenerics.TryGetValue(tl, out bf)) {
                        return bf;
                    }
                }
            }

            // Search for generic targets with the correct arity (number of type parameters).
            // Compatible targets must be MethodInfos by definition (constructors never take
            // type arguments).
            List<MethodBase> targets = new List<MethodBase>(Targets.Count);
            foreach (MethodBase mb in Targets) {
                MethodInfo mi = mb as MethodInfo;
                if (mi == null)
                    continue;
                if (mi.ContainsGenericParameters && mi.GetGenericArguments().Length == types.Length)
                    targets.Add(mi.MakeGenericMethod(types));
            }

            if (targets.Count == 0) {
                return null;
            }

            // Build a new ReflectedMethod that will contain targets with bound type arguments & cache it.
            bf = new BuiltinFunction(Name, targets.ToArray(), DeclaringType, FunctionType);

            EnsureBoundGenericDict();

            lock (_data.BoundGenerics) {
                _data.BoundGenerics[tl] = bf;
            }

            return bf;
        }