/// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodTarget target, NarrowingLevel level, RestrictionInfo restrictedArgs) { _name = name; _target = target; _restrictedArgs = restrictedArgs; _level = level; _actualArgs = actualArgumentCount; }
public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArg, ParameterWrapper toParameter, NarrowingLevel level) { if ((fromType == typeof(List) || fromType.IsSubclassOf(typeof(List)))) { if (toParameter.Type.IsGenericType() && toParameter.Type.GetGenericTypeDefinition() == typeof(IList<>) && (toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false) || toParameter.ParameterInfo.IsDefined(typeof(BytesConversionNoStringAttribute), false))) { return false; } } else if (fromType == typeof(string)) { if (toParameter.Type == typeof(IList<byte>) && !Binder.Context.PythonOptions.Python30 && toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) { // string -> byte array, we allow this in Python 2.6 return true; } } else if (fromType == typeof(Bytes)) { if (toParameter.Type == typeof(string) && !Binder.Context.PythonOptions.Python30 && toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) { return true; } } return base.CanConvertFrom(fromType, fromArg, toParameter, level); }
public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level) { if (toParameter.Type == typeof(string) && (level == NarrowingLevel.Three || level == NarrowingLevel.All)) return true; if (toParameter.IsParamsArray == true && typeof(IList<object>).IsAssignableFrom(fromType)) { var toType = toParameter.Type.GetElementType(); var list = (IList<object>)fromArgument.Value; for(var i = 0; i < list.Count; i++) { var itm = list[i]; var argExp = Expression.Call( Expression.Convert(fromArgument.Expression, fromArgument.LimitType), (typeof(IList<object>).GetMethod("get_Item")), Expression.Constant(i, typeof(int)) ); var arg = new DynamicMetaObject( argExp, fromArgument.Restrictions, itm ); if(!CanConvertFrom(itm.GetType(), arg, new ParameterWrapper(null, toType, null, ParameterBindingFlags.None), level)) return false; } return true; } return base.CanConvertFrom(fromType, fromArgument, toParameter, level); }
private readonly int _actualArgs; // gets the actual number of arguments provided /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate candidate, NarrowingLevel level, RestrictedArguments restrictedArgs) { _name = name; _candidate = candidate; _restrictedArgs = restrictedArgs; _level = level; _actualArgs = actualArgumentCount; }
private readonly int _actualArgs; // gets the actual number of arguments provided /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// /// OBSOLETE /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodTarget target, NarrowingLevel level, Type[] argTests) { _name = name; _target = target; _argTests = argTests; _level = level; _actualArgs = actualArgumentCount; }
public CallBinderHelper(CodeContext context, TAction action, object[] args, RuleBuilder rule, IList <MethodBase> targets, NarrowingLevel maxLevel, bool isReversedOperator) : this(context, action, args, rule) { _targets = ArrayUtils.ToArray(targets); _reversedOperator = isReversedOperator; _maxLevel = maxLevel; }
public bool HasConversionFrom(Type ty, NarrowingLevel allowNarrowing) { if (ty == Type) { return(true); } if (ty == None.Type) { if (_prohibitNull) { return(false); } if (Type.IsGenericType && Type.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(true); } return(!Type.IsValueType); } else { return(_binder.CanConvertFrom(ty, Type, allowNarrowing)); } }
/// <summary> /// Performs binding against a set of overloaded methods using the specified arguments. The arguments are /// consumed as specified by the CallSignature object. /// </summary> /// <param name="minLevel">TODO.</param> /// <param name="maxLevel">TODO.</param> /// <param name="resolver">Overload resolver.</param> /// <param name="targets">The methods to be called</param> /// <param name="restrictions">Additional restrictions which should be applied to the resulting MetaObject.</param> /// <param name="target">The resulting binding target which can be used for producing error information.</param> /// <param name="name">The name of the method or null to use the name from targets.</param> /// <returns>A meta object which results from the call.</returns> public DynamicMetaObject CallMethod(DefaultOverloadResolver resolver, IList <MethodBase> targets, BindingRestrictions restrictions, string name, NarrowingLevel minLevel, NarrowingLevel maxLevel, out BindingTarget target) { ContractUtils.RequiresNotNull(resolver, nameof(resolver)); ContractUtils.RequiresNotNullItems(targets, nameof(targets)); ContractUtils.RequiresNotNull(restrictions, nameof(restrictions)); // attempt to bind to an individual method target = resolver.ResolveOverload(name ?? GetTargetName(targets), targets, minLevel, maxLevel); if (target.Success) { // if we succeed make the target for the rule return(new DynamicMetaObject( target.MakeExpression(), restrictions.Merge( MakeSplatTests(resolver.CallType, resolver.Signature, resolver.Arguments). Merge(target.RestrictedArguments.GetAllRestrictions()) ) )); } // make an error rule return(MakeInvalidParametersRule(resolver, restrictions, target)); }
/// <summary> /// Creates a new BindingTarget when the method binding has succeeded /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodTarget target, NarrowingLevel level, MetaObject[] restrictedArgs) { _name = name; _target = target; _restrictedArgs = restrictedArgs; _level = level; _actualArgs = actualArgumentCount; }
private readonly int _actualArgs; // gets the actual number of arguments provided /// <summary> /// Creates a new BindingTarget when the method binding has succeeded /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodTarget target, NarrowingLevel level, Type[] argTests) { _name = name; _target = target; _argTests = argTests; _level = level; _actualArgs = actualArgumentCount; }
private readonly int[] _expectedArgs; // gets the acceptable number of parameters which can be passed to the method. /// <summary> /// Creates a new BindingTarget when the method binding has succeeded. /// </summary> internal BindingTarget(string name, int actualArgumentCount, MethodCandidate candidate, NarrowingLevel level, RestrictedArguments restrictedArgs) { Name = name; MethodCandidate = candidate; RestrictedArguments = restrictedArgs; NarrowingLevel = level; ActualArgumentCount = actualArgumentCount; }
public bool IsApplicable(Type[] types, SymbolId[] names, NarrowingLevel allowNarrowing) { if (!TryGetNormalizedArguments(types, names, out types)) { return(false); } return(IsApplicable(types, allowNarrowing)); }
internal MethodCandidate(MethodTarget target, List <ParameterWrapper> parameters) { Debug.Assert(target != null); _target = target; _parameters = parameters; _narrowingLevel = NarrowingLevel.None; parameters.TrimExcess(); }
public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level) { if (level >= NarrowingLevel.Two) { if (toParameter.Type == typeof(string)) return true; } return base.CanConvertFrom(fromType, fromArgument, toParameter, level); }
private readonly NarrowingLevel _maxLevel; // the maximum narrowing level allowed public CallBinderHelper(CodeContext context, TAction action, object[] args, RuleBuilder rule) : base(context, action) { ContractUtils.RequiresNotEmpty(args, "args"); _maxLevel = NarrowingLevel.All; _args = RemoveExplicitInstanceArgument(action, args); _rule = rule; _test = _rule.MakeTypeTest(CompilerHelpers.GetType(Callable), 0); }
public override bool CanConvertFrom(Type fromType, ParameterWrapper toParameter, NarrowingLevel level) { if ((fromType == typeof(List) || fromType.IsSubclassOf(typeof(List))) && toParameter.Type.IsGenericType && toParameter.Type.GetGenericTypeDefinition() == typeof(IList<>)) { if (toParameter.ParameterInfo.IsDefined(typeof(ProhibitGenericListConversionAttribute), false)) { return false; } } return base.CanConvertFrom(fromType, toParameter, level); }
private List <MethodCandidate> SelectTargets(CallType callType, Type[] types, SymbolId[] names) { // obsolete: this should be removed entirely: if (!_binder.StrictParameterCheck) { if (_targets.Count == 1 && !_binder.IsBinaryOperator && names.Length == 0) { return(_targets); } } List <MethodCandidate> applicableTargets = new List <MethodCandidate>(); foreach (MethodCandidate target in _targets) { if (target.IsApplicable(types, names, NarrowingLevel.None)) { applicableTargets.Add(target); } } List <MethodCandidate> result = null; if (TryGetApplicableTarget(callType, applicableTargets, types, out result)) { return(result); } //no targets are applicable without narrowing conversions, so try those foreach (MethodCandidate target in _targets) { if (target.IsApplicable(types, names, NarrowingLevel.Preferred)) { applicableTargets.Add(new MethodCandidate(target, NarrowingLevel.Preferred)); } } if (TryGetApplicableTarget(callType, applicableTargets, types, out result)) { return(result); } foreach (MethodCandidate target in _targets) { NarrowingLevel nl = _binder.IsBinaryOperator ? NarrowingLevel.Operator : NarrowingLevel.All; if (target.IsApplicable(types, names, nl)) { applicableTargets.Add(new MethodCandidate(target, nl)); } } return(applicableTargets); }
/// <summary> /// Performs binding against a set of overloaded methods using the specified arguments. All arguments /// are treated as positional arguments. /// </summary> /// <param name="parameterBinder">ParameterBinder used to map arguments to parameters.</param> /// <param name="targets">The methods to be called</param> /// <param name="args">The arguments for the call</param> /// <param name="maxLevel">The maximum narrowing level for arguments. The current narrowing level is flowed thorugh to the DefaultBinder.</param> /// <param name="minLevel">The minimum narrowing level for the arguments. The current narrowing level is flowed thorugh to the DefaultBinder.</param> /// <returns>A meta object which results from the call.</returns> public DynamicMetaObject CallMethod(ParameterBinder parameterBinder, IList<MethodBase> targets, IList<DynamicMetaObject> args, NarrowingLevel minLevel, NarrowingLevel maxLevel) { return CallWorker( parameterBinder, targets, args, new CallSignature(args.Count), CallTypes.None, BindingRestrictions.Empty, minLevel, maxLevel, null ); }
public bool IsApplicable(Type[] types, NarrowingLevel allowNarrowing) { Debug.Assert(types.Length == _parameters.Count); for (int i = 0; i < types.Length; i++) { if (!_parameters[i].HasConversionFrom(types[i], allowNarrowing)) { return(false); } } return(true); }
internal bool IsApplicable(Type[] types, NarrowingLevel narrowingLevel, List <ConversionResult> conversionResults) { // attempt to convert each parameter bool res = true; for (int i = 0; i < types.Length; i++) { bool success = _parameters[i].HasConversionFrom(types[i], narrowingLevel); conversionResults.Add(new ConversionResult(types[i], _parameters[i].Type, i, !success)); res &= success; } return(res); }
private static Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, MetaObject actualType) { Assert.NotNull(candidateOne, candidateTwo, actualType); if (candidateOne._binder.ParametersEquivalent(candidateOne, candidateTwo)) { return(Candidate.Equivalent); } for (NarrowingLevel curLevel = NarrowingLevel.None; curLevel <= NarrowingLevel.All; curLevel++) { Candidate candidate = candidateOne._binder.SelectBestConversionFor(actualType.LimitType, candidateOne, candidateTwo, curLevel); if (candidate.Chosen()) { return(candidate); } } return(GetPreferredParameter(candidateOne, candidateTwo)); }
internal bool IsApplicable(MetaObject[] objects, NarrowingLevel narrowingLevel, List <ConversionResult> conversionResults) { // attempt to convert each parameter bool res = true; for (int i = 0; i < objects.Length; i++) { /*if (objects[i].NeedsDeferral) { * conversionResults.Add(new ConversionResult(typeof(Dynamic), _parameters[i].Type, i, false)); * } else*/{ bool success = _parameters[i].HasConversionFrom(objects[i].LimitType, narrowingLevel); conversionResults.Add(new ConversionResult(objects[i].LimitType, _parameters[i].Type, i, !success)); res &= success; } } return(res); }
public bool IsApplicable(Type[] types, SymbolId[] names, NarrowingLevel allowNarrowing) { #if FULL foreach (ParameterWrapper pw in _parameters) { // can't bind to methods that are params dictionaries, only to their extended forms. if (pw.IsParamsDict) { return(false); } } #endif if (!TryGetNormalizedArguments(types, names, out types)) { return(false); } return(IsApplicable(types, allowNarrowing)); }
internal static ConversionResultKind?ToConversionResultKind(this NarrowingLevel narrowingLevel) { switch (narrowingLevel) { case NarrowingLevel.None: return(null); case NarrowingLevel.One: return(ConversionResultKind.ImplicitCast); case NarrowingLevel.Two: return(ConversionResultKind.ImplicitTry); case NarrowingLevel.Three: return(ConversionResultKind.ExplicitCast); case NarrowingLevel.All: default: return(ConversionResultKind.ExplicitTry); } }
public override bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level) { if (fromType == toType || toType.IsAssignableFrom(fromType)) { return(true); } if (toType == typeof(object) || toType == fromType) { return(true); } if (fromType == typeof(int) && toType == typeof(double)) { return(true); } if (fromType == typeof(SymbolId) && toType.IsEnum) { return(true); } if (fromType == typeof(object) && level == NarrowingLevel.All) { return(true); } return(false); }
public override bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level) { if (fromType == toType || toType.IsAssignableFrom(fromType)) { return true; } if (toType == typeof(object) || toType == fromType) { return true; } if (fromType == typeof(int) && toType == typeof(double)) { return true; } if (fromType == typeof(SymbolId) && toType.IsEnum) { return true; } if (fromType == typeof(object) && level == NarrowingLevel.All) { return true; } return false; }
public override Candidate SelectBestConversionFor(Type /*!*/ actualType, ParameterWrapper /*!*/ candidateOne, ParameterWrapper /*!*/ candidateTwo, NarrowingLevel level) { Type typeOne = candidateOne.Type; Type typeTwo = candidateTwo.Type; if (actualType == typeof(Null)) { // if nil is passed as a block argument prefer BlockParam over missing block; if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) { return(Candidate.One); } if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) { return(Candidate.Two); } } else { if (actualType == typeOne && candidateOne.ProhibitNull) { return(Candidate.One); } if (actualType == typeTwo && candidateTwo.ProhibitNull) { return(Candidate.Two); } } if (actualType == typeOne) { return(Candidate.One); } if (actualType == typeTwo) { return(Candidate.Two); } return(Candidate.Equivalent); }
public override bool CanConvertFrom(Type/*!*/ fromType, Type/*!*/ toType, bool toNotNullable, NarrowingLevel level) { return Converter.CanConvertFrom(null, fromType, toType, toNotNullable, level, false, false); }
private Candidate GetPreferredParameter(ParameterWrapper candidateOne, ParameterWrapper candidateTwo, DynamicMetaObject arg, NarrowingLevel level) { Assert.NotNull(candidateOne, candidateTwo); if (ParametersEquivalent(candidateOne, candidateTwo)) { return Candidate.Equivalent; } Candidate candidate = SelectBestConversionFor(arg, candidateOne, candidateTwo, level); if (candidate.Chosen()) { return candidate; } if (CanConvertFrom(candidateTwo, candidateOne)) { if (CanConvertFrom(candidateOne, candidateTwo)) { return Candidate.Ambiguous; } else { return Candidate.Two; } } else if (CanConvertFrom(candidateOne, candidateTwo)) { return Candidate.One; } // Special additional rules to order numeric value types Type t1 = candidateOne.Type; Type t2 = candidateTwo.Type; Candidate preferred = PreferConvert(t1, t2); if (preferred.Chosen()) { return preferred; } preferred = PreferConvert(t2, t1).TheOther(); if (preferred.Chosen()) { return preferred; } // consider the actual argument type: Type argType = arg.GetLimitType(); NarrowingLevel levelOne = NarrowingLevel.None; while (levelOne < level && !CanConvertFrom(argType, arg, candidateOne, levelOne)) { if (levelOne == NarrowingLevel.All) { Debug.Assert(false, "Each argument should be convertible to the corresponding parameter"); break; } levelOne++; } NarrowingLevel levelTwo = NarrowingLevel.None; while (levelTwo < level && !CanConvertFrom(argType, arg, candidateTwo, levelTwo)) { if (levelTwo == NarrowingLevel.All) { Debug.Assert(false, "Each argument should be convertible to the corresponding parameter"); break; } levelTwo++; } if (levelOne < levelTwo) { return Candidate.One; } else if (levelOne > levelTwo) { return Candidate.Two; } else { return Candidate.Ambiguous; } }
private int? SelectBestConversionFor(Type actualType, Type candidateOne, Type candidateTwo, NarrowingLevel level) { Type ret = _binder.SelectBestConversionFor(actualType, candidateOne, candidateTwo, level); if (ret != null) { if (ret == candidateOne) { return +1; } else if (ret == candidateTwo) { return -1; } } return null; }
public override Candidate SelectBestConversionFor(DynamicMetaObject /*!*/ arg, ParameterWrapper /*!*/ candidateOne, ParameterWrapper /*!*/ candidateTwo, NarrowingLevel level) { Type typeOne = candidateOne.Type; Type typeTwo = candidateTwo.Type; Type actualType = arg.GetLimitType(); if (actualType == typeof(DynamicNull)) { // if nil is passed as a block argument prefers BlockParam over a missing block: if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) { Debug.Assert(!candidateOne.ProhibitNull); return(Candidate.One); } if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) { Debug.Assert(!candidateTwo.ProhibitNull); return(Candidate.Two); } } else { if (typeOne == actualType) { if (typeTwo == actualType) { // prefer non-nullable reference type over nullable: if (!actualType.IsValueType) { if (candidateOne.ProhibitNull) { return(Candidate.One); } else if (candidateTwo.ProhibitNull) { return(Candidate.Two); } } } else { return(Candidate.One); } } else if (typeTwo == actualType) { return(Candidate.Two); } } // prefer integer type over enum: if (typeOne.IsEnum && Enum.GetUnderlyingType(typeOne) == typeTwo) { return(Candidate.Two); } if (typeTwo.IsEnum && Enum.GetUnderlyingType(typeTwo) == typeOne) { return(Candidate.One); } return(base.SelectBestConversionFor(arg, candidateOne, candidateTwo, level)); }
public override bool CanConvertFrom(Type /*!*/ fromType, Type /*!*/ toType, bool toNotNullable, NarrowingLevel level) { return(Converter.CanConvertFrom(null, fromType, toType, toNotNullable, level, false, false).IsConvertible); }
internal static bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); // NarrowingLevel.Zero if (fromType == toType) { return(true); } // I don't want to consider boxing before numeric conversion, else I don't get the convert-int-to-long behavior required to select Numbers.lt(long,long) over Numbers.lt(long,Object) // We also need to get the narrow-long-to-int behavior required to avoid casting in host expression calls. // IronRuby and IronPython both do this here: //if (toType.IsAssignableFrom(fromType)) //{ // return true; //} // Because long[] and ulong[] are inter-assignable, we run into problems. // Let's just not convert from an array of one primitive type to another. if (fromType.IsArray && toType.IsArray && (Util.IsPrimitiveNumeric(fromType.GetElementType()) || Util.IsPrimitiveNumeric(toType.GetElementType()))) { return(false); } if (!Util.IsPrimitiveNumeric(fromType) && toType.IsAssignableFrom(fromType)) { return(true); } if (fromType.IsCOMObject && toType.IsInterface) { return(true); // A COM object could be cast to any interface } if (HasImplicitNumericConversion(fromType, toType)) { return(true); } // try available type conversions... object[] tcas = toType.GetCustomAttributes(typeof(TypeConverterAttribute), true); foreach (TypeConverterAttribute tca in tcas) { TypeConverter tc = GetTypeConverter(tca); if (tc == null) { continue; } if (tc.CanConvertFrom(fromType)) { return(true); } } //!!!do user-defined implicit conversions here if (level == NarrowingLevel.None) { return(false); } // NarrowingLevel.One if (WideningIntegerConversion(fromType, toType)) { return(true); } if (level == NarrowingLevel.One) { return(false); } // NarrowingLevel.Two if (SpecialClojureConversion(fromType, toType)) { return(true); } if (DelegateType.IsAssignableFrom(toType) && typeof(IFn).IsAssignableFrom(fromType)) { return(true); } if (level == NarrowingLevel.Two) { return(false); } // NarrowingLevel.Three if (toType == typeof(bool)) { return(true); } if (Util.IsPrimitiveNumeric(toType) && Util.IsPrimitiveNumeric(fromType)) { return(true); } // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion if (toType.IsGenericType) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == typeof(IEnumerable <>)) { return(typeof(IEnumerable <Object>).IsAssignableFrom(fromType) || typeof(IEnumerable).IsAssignableFrom(fromType)); } } if (level == NarrowingLevel.Three) { return(false); } // NarrowingLevel.All if (level < NarrowingLevel.All) { return(false); } // pick up boxing numerics here if (toType.IsAssignableFrom(fromType)) { return(true); } // TODO: Rethink. IPy has the following, but we get overload problems on Numbers ops //return HasNarrowingConversion(fromType, toType, level); // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion if (toType.IsGenericType) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == typeof(IList <>)) { return(typeof(IList <object>).IsAssignableFrom(fromType)); } else if (genTo == typeof(Nullable <>)) { if (fromType == typeof(DynamicNull) || CanConvertFrom(fromType, toType.GetGenericArguments()[0], level)) { return(true); } } else if (genTo == typeof(IDictionary <,>)) { return(typeof(IDictionary <object, object>).IsAssignableFrom(fromType)); } } return(false); }
private static bool HasNarrowingConversion(Type fromType, Type toType, NarrowingLevel allowNarrowing) { if (allowNarrowing == PythonNarrowing.IndexOperator) { if (toType == CharType && fromType == StringType) { return(true); } if (toType == StringType && fromType == CharType) { return(true); } //if (toType == Int32Type && fromType == BigIntegerType) return true; //if (IsIntegral(fromType) && IsIntegral(toType)) return true; //Check if there is an implicit convertor defined on fromType to toType if (HasImplicitConversion(fromType, toType)) { return(true); } } if (toType == DoubleType && fromType == DecimalType) { return(true); } if (toType == SingleType && fromType == DecimalType) { return(true); } if (toType.IsArray) { return(typeof(PythonTuple).IsAssignableFrom(fromType)); } if (allowNarrowing == PythonNarrowing.IndexOperator) { if (IsNumeric(fromType) && IsNumeric(toType)) { if (fromType != typeof(float) && fromType != typeof(double) && fromType != typeof(decimal) && fromType != typeof(Complex)) { return(true); } } if (fromType == typeof(bool) && IsNumeric(toType)) { return(true); } if (toType == CharType && fromType == StringType) { return(true); } if (toType == Int32Type && fromType == BooleanType) { return(true); } // Everything can convert to Boolean in Python if (toType == BooleanType) { return(true); } if (DelegateType.IsAssignableFrom(toType) && IsPythonType(fromType)) { return(true); } if (IEnumerableType == toType && IsPythonType(fromType)) { return(true); } if (toType == typeof(IEnumerator)) { if (IsPythonType(fromType)) { return(true); } } else if (toType.IsGenericType()) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == IEnumerableOfTType) { return(IEnumerableOfObjectType.IsAssignableFrom(fromType) || IEnumerableType.IsAssignableFrom(fromType) || fromType == typeof(OldInstance)); } else if (genTo == typeof(System.Collections.Generic.IEnumerator <>)) { if (IsPythonType(fromType)) { return(true); } } } } if (allowNarrowing == PythonNarrowing.All) { //__int__, __float__, __long__ if (IsNumeric(fromType) && IsNumeric(toType)) { return(true); } if (toType == Int32Type && HasPythonProtocol(fromType, "__int__")) { return(true); } if (toType == DoubleType && HasPythonProtocol(fromType, "__float__")) { return(true); } if (toType == BigIntegerType && HasPythonProtocol(fromType, "__long__")) { return(true); } } if (toType.IsGenericType()) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == IListOfTType) { return(IListOfObjectType.IsAssignableFrom(fromType)); } else if (genTo == NullableOfTType) { if (fromType == typeof(DynamicNull) || CanConvertFrom(fromType, toType.GetGenericArguments()[0], allowNarrowing)) { return(true); } } else if (genTo == IDictOfTType) { return(IDictionaryOfObjectType.IsAssignableFrom(fromType)); } } if (fromType == BigIntegerType && toType == Int64Type) { return(true); } if (toType.IsEnum() && fromType == Enum.GetUnderlyingType(toType)) { return(true); } return(false); }
public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level) { return(toType.IsAssignableFrom(fromType)); }
internal static bool CanConvertFrom(DynamicMetaObject fromArg, Type/*!*/ fromType, Type/*!*/ toType, bool toNotNullable, NarrowingLevel level, bool explicitProtocolConversions, bool implicitProtocolConversions) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); var metaConvertible = fromArg as IConvertibleMetaObject; // // narrowing level 0: // if (toType == fromType) { return true; } if (fromType == typeof(DynamicNull)) { if (toNotNullable) { return false; } if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return true; } if (!toType.IsValueType) { // null convertible to any reference type: return true; } else if (toType == typeof(bool)) { return true; } else if (!ProtocolConversionAction.HasDefaultConversion(toType)) { // null not convertible to a value type unless a protocol conversion is allowed: return false; } } // blocks: if (fromType == typeof(MissingBlockParam)) { return toType == typeof(BlockParam) && !toNotNullable; } if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) { return true; } if (toType.IsAssignableFrom(fromType)) { return true; } // A COM object could be cast to any interface: if (Utils.IsComObjectType(fromType) && toType.IsInterface) { return true; } if (HasImplicitNumericConversion(fromType, toType)) { return true; } if (CompilerHelpers.GetImplicitConverter(fromType, toType) != null) { return true; } if (metaConvertible != null) { return metaConvertible.CanConvertTo(toType, false); } // // narrowing level 1: // if (level < NarrowingLevel.One) { return false; } if (explicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return true; } // // narrowing level 2: // if (level < NarrowingLevel.Two) { return false; } if (HasExplicitNumericConversion(fromType, toType)) { return true; } if (CompilerHelpers.GetExplicitConverter(fromType, toType) != null) { return true; } if (CompilerHelpers.HasTypeConverter(fromType, toType)) { return true; } if (fromType == typeof(char) && toType == typeof(string)) { return true; } if (toType == typeof(bool)) { return true; } if (metaConvertible != null) { return metaConvertible.CanConvertTo(toType, true); } // // narrowing level 3: // if (level < NarrowingLevel.Three) { return false; } if (implicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return true; } return false; }
internal static bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); // NarrowingLevel.Zero if (fromType == toType) return true; // I don't want to consider boxing before numeric conversion, else I don't get the convert-int-to-long behavior required to select Numbers.lt(long,long) over Numbers.lt(long,Object) // We also need to get the narrow-long-to-int behavior required to avoid casting in host expression calls. // IronRuby and IronPython both do this here: //if (toType.IsAssignableFrom(fromType)) //{ // return true; //} // Because long[] and ulong[] are inter-assignable, we run into problems. // Let's just not convert from an array of one primitive type to another. if (fromType.IsArray && toType.IsArray && (Util.IsPrimitiveNumeric(fromType.GetElementType()) || Util.IsPrimitiveNumeric(toType.GetElementType()))) { return false; } if (!Util.IsPrimitiveNumeric(fromType) && toType.IsAssignableFrom(fromType)) { return true; } if (fromType.IsCOMObject && toType.IsInterface) return true; // A COM object could be cast to any interface if (HasImplicitNumericConversion(fromType, toType)) return true; // try available type conversions... object[] tcas = toType.GetCustomAttributes(typeof(TypeConverterAttribute), true); foreach (TypeConverterAttribute tca in tcas) { TypeConverter tc = GetTypeConverter(tca); if (tc == null) continue; if (tc.CanConvertFrom(fromType)) { return true; } } //!!!do user-defined implicit conversions here if (level == NarrowingLevel.None) return false; // NarrowingLevel.One if (WideningIntegerConversion(fromType, toType)) { return true; } if (level == NarrowingLevel.One) return false; // NarrowingLevel.Two if (SpecialClojureConversion(fromType, toType)) { return true; } if (DelegateType.IsAssignableFrom(toType) && typeof(IFn).IsAssignableFrom(fromType)) return true; if (level == NarrowingLevel.Two) return false; // NarrowingLevel.Three if (toType == typeof(bool)) { return true; } if (Util.IsPrimitiveNumeric(toType) && Util.IsPrimitiveNumeric(fromType)) { return true; } // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion if (toType.IsGenericType) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == typeof(IEnumerable<>)) return typeof(IEnumerable<Object>).IsAssignableFrom(fromType) || typeof(IEnumerable).IsAssignableFrom(fromType); } if (level == NarrowingLevel.Three) return false; // NarrowingLevel.All if (level < NarrowingLevel.All) { return false; } // pick up boxing numerics here if (toType.IsAssignableFrom(fromType)) { return true; } // TODO: Rethink. IPy has the following, but we get overload problems on Numbers ops //return HasNarrowingConversion(fromType, toType, level); // Handle conversions of IEnumerable<Object> or IEnumerable to IEnumerable<T> for any T // Similar to code in IPy's IronPython.Runtime.Converter.HasNarrowingConversion if (toType.IsGenericType) { Type genTo = toType.GetGenericTypeDefinition(); if (genTo == typeof(IList<>) ) { return typeof(IList<object>).IsAssignableFrom(fromType); } else if (genTo == typeof(Nullable<>)) { if (fromType == typeof(DynamicNull) || CanConvertFrom(fromType, toType.GetGenericArguments()[0], level)) { return true; } } else if (genTo == typeof(IDictionary<,>) ) { return typeof(IDictionary<object,object>).IsAssignableFrom(fromType); } } return false; }
private BindingTarget MakeSuccessfulBindingTarget(ApplicableCandidate result, List<ApplicableCandidate> potentialCandidates, NarrowingLevel level, CandidateSet targetSet) { return new BindingTarget( _methodName, _actualArguments.VisibleCount, result.Method, level, GetRestrictedArgs(result, potentialCandidates, targetSet.Arity) ); }
private ApplicableCandidate SelectBestCandidate(List<ApplicableCandidate> candidates, NarrowingLevel level) { foreach (var candidate in candidates) { if (IsBest(candidate, candidates, level)) { return candidate; } } return null; }
/// <summary> /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level. /// </summary> public override bool CanConvertFrom(Type /*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper /*!*/ toParameter, NarrowingLevel level) { return(Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions )); }
public override bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel level) { return toType.IsAssignableFrom(fromType); }
public static bool CanConvertFrom(Type fromType, Type toType, NarrowingLevel allowNarrowing) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); if (toType == fromType) { return(true); } if (toType.IsAssignableFrom(fromType)) { return(true); } #if FEATURE_COM if (fromType.IsCOMObject && toType.IsInterface) { return(true); // A COM object could be cast to any interface } #endif if (HasImplicitNumericConversion(fromType, toType)) { return(true); } // Handling the hole that Type is the only object that we 'box' if (toType == TypeType && (typeof(PythonType).IsAssignableFrom(fromType) || typeof(TypeGroup).IsAssignableFrom(fromType))) { return(true); } // Support extensible types with simple implicit conversions to their base types if (typeof(Extensible <int>).IsAssignableFrom(fromType) && CanConvertFrom(Int32Type, toType, allowNarrowing)) { return(true); } if (typeof(Extensible <BigInteger>).IsAssignableFrom(fromType) && CanConvertFrom(BigIntegerType, toType, allowNarrowing)) { return(true); } if (typeof(ExtensibleString).IsAssignableFrom(fromType) && CanConvertFrom(StringType, toType, allowNarrowing)) { return(true); } if (typeof(Extensible <double>).IsAssignableFrom(fromType) && CanConvertFrom(DoubleType, toType, allowNarrowing)) { return(true); } if (typeof(Extensible <Complex>).IsAssignableFrom(fromType) && CanConvertFrom(ComplexType, toType, allowNarrowing)) { return(true); } #if FEATURE_CUSTOM_TYPE_DESCRIPTOR // try available type conversions... object[] tcas = toType.GetCustomAttributes(typeof(TypeConverterAttribute), true); foreach (TypeConverterAttribute tca in tcas) { TypeConverter tc = GetTypeConverter(tca); if (tc == null) { continue; } if (tc.CanConvertFrom(fromType)) { return(true); } } #endif //!!!do user-defined implicit conversions here if (allowNarrowing == PythonNarrowing.None) { return(false); } return(HasNarrowingConversion(fromType, toType, allowNarrowing)); }
/// <summary> /// Determines if a conversion exists from fromType to toType at the specified narrowing level. /// toNotNullable is true if the target variable doesn't allow null values. /// </summary> public abstract bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level);
private int?SelectBestConversionFor(Type actualType, Type candidateOne, Type candidateTwo, NarrowingLevel level) { Type ret = _binder.SelectBestConversionFor(actualType, candidateOne, candidateTwo, level); if (ret != null) { if (ret == candidateOne) { return(+1); } else if (ret == candidateTwo) { return(-1); } } return(null); }
/// <summary> /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level. /// </summary> public override bool CanConvertFrom(Type/*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper/*!*/ toParameter, NarrowingLevel level) { var result = Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions ); if (result.Assumption != null) { if (_argumentAssumptions == null) { _argumentAssumptions = new List<Key<int, NarrowingLevel, Ast>>(); } if (_argumentAssumptions.FindIndex((k) => k.First == toParameter.ParameterInfo.Position && k.Second == level) < 0) { _argumentAssumptions.Add(Key.Create(toParameter.ParameterInfo.Position, level, result.Assumption)); } } return result.IsConvertible; }
/// <summary> /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level. /// </summary> public override bool CanConvertFrom(Type /*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper /*!*/ toParameter, NarrowingLevel level) { var result = Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions ); if (result.Assumption != null) { if (_argumentAssumptions == null) { _argumentAssumptions = new List <Key <int, NarrowingLevel, Ast> >(); } if (_argumentAssumptions.FindIndex((k) => k.First == toParameter.ParameterInfo.Position && k.Second == level) < 0) { _argumentAssumptions.Add(Key.Create(toParameter.ParameterInfo.Position, level, result.Assumption)); } } return(result.IsConvertible); }
/// <summary> /// Performs binding against a set of overloaded methods using the specified arguments. The arguments are /// consumed as specified by the CallSignature object. /// </summary> /// <param name="minLevel">TODO.</param> /// <param name="maxLevel">TODO.</param> /// <param name="resolver">Overload resolver.</param> /// <param name="targets">The methods to be called</param> /// <param name="restrictions">Additional restrictions which should be applied to the resulting MetaObject.</param> /// <param name="target">The resulting binding target which can be used for producing error information.</param> /// <param name="name">The name of the method or null to use the name from targets.</param> /// <returns>A meta object which results from the call.</returns> public DynamicMetaObject CallMethod(DefaultOverloadResolver resolver, IList<MethodBase> targets, BindingRestrictions restrictions, string name, NarrowingLevel minLevel, NarrowingLevel maxLevel, out BindingTarget target) { ContractUtils.RequiresNotNull(resolver, "resolver"); ContractUtils.RequiresNotNullItems(targets, "targets"); ContractUtils.RequiresNotNull(restrictions, "restrictions"); // attempt to bind to an individual method target = resolver.ResolveOverload(name ?? GetTargetName(targets), targets, minLevel, maxLevel); if (target.Success) { // if we succeed make the target for the rule return new DynamicMetaObject( target.MakeExpression(), restrictions.Merge( MakeSplatTests(resolver.CallType, resolver.Signature, resolver.Arguments). Merge(target.RestrictedArguments.GetAllRestrictions()) ) ); } // make an error rule return MakeInvalidParametersRule(resolver, restrictions, target); }
public bool HasConversionFrom(Type ty, NarrowingLevel allowNarrowing) { if (ty == Type) return true; if (ty == None.Type) { if (_prohibitNull) return false; if (Type.IsGenericType && Type.GetGenericTypeDefinition() == typeof(Nullable<>)) { return true; } return !Type.IsValueType; } else { return _binder.CanConvertFrom(ty, Type, allowNarrowing); } }
public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level) { // // NarrowLevel.Zero // if (fromType == toType) return true; // I don't want to consider boxing before numeric conversion, else I don't get the convert-int-to-long behavior required to select Numbers.lt(long,long) over Numbers.lt(long,Object) // We also need to get the narrow-long-to-int behavior required to avoid casting in host expression calls. // IronRuby does this here: //if (toType.IsAssignableFrom(fromType)) //{ // return true; //} if ( !Util.IsPrimitiveNumeric(fromType) && toType.IsAssignableFrom(fromType)) { return true; } // // NarrowingLevel.One // if (level < NarrowingLevel.One) { return false; } if (WideningIntegerConversion(fromType, toType)) { return true; } // // NarrowingLevel.Two // if (level < NarrowingLevel.Two) { return false; } if ( SpecialClojureConversion(fromType, toType) ) { return true; } //if (fromType == typeof(char) && toType == typeof(string)) //{ // return true; //} if (toType == typeof(bool)) { return true; } // // NarrowingLevel.Three // if (level < NarrowingLevel.Three) { return false; } if ( Util.IsPrimitiveNumeric(toType) && Util.IsPrimitiveNumeric(fromType) ) { return true; } // // NarrowingLevel.All // if (level < NarrowingLevel.All) { return false; } // pick up boxing numerics here if (toType.IsAssignableFrom(fromType)) { return true; } return false; //if (level == NarrowingLevel.All) //{ // if (fromType == typeof(long)) // { // if (toType == typeof(int) || toType == typeof(uint) || toType == typeof(short) || toType == typeof(ushort) || toType == typeof(byte) || toType == typeof(sbyte)) // return true; // } // else if (fromType == typeof(double)) // { // if (toType == typeof(float)) // return true; // } //} //return base.CanConvertFrom(fromType, toType, toNotNullable, level); }
public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level) { return Converter.CanConvertFrom(fromType, toType, level); }
/// <summary> /// Returns true if fromArg of type fromType can be assigned to toParameter with a conversion on given narrowing level. /// </summary> public override bool CanConvertFrom(Type/*!*/ fromType, DynamicMetaObject fromArg, ParameterWrapper/*!*/ toParameter, NarrowingLevel level) { return Converter.CanConvertFrom(fromArg, fromType, toParameter.Type, toParameter.ProhibitNull, level, HasExplicitProtocolConversion(toParameter), _implicitProtocolConversions ); }
public virtual bool CanConvertFrom(Type fromType, DynamicMetaObject fromArgument, ParameterWrapper toParameter, NarrowingLevel level) { Assert.NotNull(fromType, toParameter); Type toType = toParameter.Type; if (fromType == typeof(DynamicNull)) { if (toParameter.ProhibitNull) { return false; } if (toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return true; } if (!toType.IsValueType) { return true; } } if (fromType == toType) { return true; } return _binder.CanConvertFrom(fromType, toType, toParameter.ProhibitNull, level); }
public override Candidate SelectBestConversionFor(DynamicMetaObject/*!*/ arg, ParameterWrapper/*!*/ candidateOne, ParameterWrapper/*!*/ candidateTwo, NarrowingLevel level) { Type typeOne = candidateOne.Type; Type typeTwo = candidateTwo.Type; Type actualType = arg.GetLimitType(); if (actualType == typeof(DynamicNull)) { // if nil is passed as a block argument prefers BlockParam over a missing block: if (typeOne == typeof(BlockParam) && typeTwo == typeof(MissingBlockParam)) { Debug.Assert(!candidateOne.ProhibitNull); return Candidate.One; } if (typeOne == typeof(MissingBlockParam) && typeTwo == typeof(BlockParam)) { Debug.Assert(!candidateTwo.ProhibitNull); return Candidate.Two; } } else { if (typeOne == actualType) { if (typeTwo == actualType) { // prefer non-nullable reference type over nullable: if (!actualType.IsValueType) { if (candidateOne.ProhibitNull) { return Candidate.One; } else if (candidateTwo.ProhibitNull) { return Candidate.Two; } } } else { return Candidate.One; } } else if (typeTwo == actualType) { return Candidate.Two; } } // prefer integer type over enum: if (typeOne.IsEnum && Enum.GetUnderlyingType(typeOne) == typeTwo) { return Candidate.Two; } if (typeTwo.IsEnum && Enum.GetUnderlyingType(typeTwo) == typeOne) { return Candidate.One; } return base.SelectBestConversionFor(arg, candidateOne, candidateTwo, level); }
public override bool CanConvertFrom(Type fromType, DynamicMetaObject fromArg, ParameterWrapper toParameter, NarrowingLevel level) { if ((fromType == typeof(List) || fromType.IsSubclassOf(typeof(List)))) { if (toParameter.Type.IsGenericType() && toParameter.Type.GetGenericTypeDefinition() == typeof(IList <>) && (toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false) || toParameter.ParameterInfo.IsDefined(typeof(BytesConversionNoStringAttribute), false))) { return(false); } } else if (fromType == typeof(string)) { if (toParameter.Type == typeof(IList <byte>) && !Binder.Context.PythonOptions.Python30 && toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) { // string -> byte array, we allow this in Python 2.6 return(true); } } else if (fromType == typeof(Bytes)) { if (toParameter.Type == typeof(string) && !Binder.Context.PythonOptions.Python30 && toParameter.ParameterInfo.IsDefined(typeof(BytesConversionAttribute), false)) { return(true); } } return(base.CanConvertFrom(fromType, fromArg, toParameter, level)); }
/// <summary> /// Selects the best (of two) candidates for conversion from actualType /// </summary> public virtual Candidate SelectBestConversionFor(DynamicMetaObject arg, ParameterWrapper candidateOne, ParameterWrapper candidateTwo, NarrowingLevel level) { return Candidate.Equivalent; }
public bool HasConversionFrom(Type fromType, NarrowingLevel level) { return _binder.CanConvertFrom(fromType, this, level); }
public override bool CanConvertFrom(Type fromType, Type toType, bool toNotNullable, NarrowingLevel level) { // TODO: None -> nullable reference types? return toType.IsAssignableFrom(fromType); }
internal static Convertibility CanConvertFrom(DynamicMetaObject fromArg, Type/*!*/ fromType, Type/*!*/ toType, bool toNotNullable, NarrowingLevel level, bool explicitProtocolConversions, bool implicitProtocolConversions) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); var metaConvertible = fromArg as IConvertibleMetaObject; var rubyMetaConvertible = fromArg as IConvertibleRubyMetaObject; // // narrowing level 0: // if (toType == fromType) { return Convertibility.AlwaysConvertible; } if (fromType == typeof(DynamicNull)) { if (toNotNullable) { return Convertibility.NotConvertible; } if (toType.IsGenericType() && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return Convertibility.AlwaysConvertible; } if (!toType.IsValueType()) { // null convertible to any reference type: return Convertibility.AlwaysConvertible; } else if (toType == typeof(bool)) { return Convertibility.AlwaysConvertible; } else if (!ProtocolConversionAction.HasDefaultConversion(toType)) { // null not convertible to a value type unless a protocol conversion is allowed: return Convertibility.NotConvertible; } } // blocks: if (fromType == typeof(MissingBlockParam)) { return new Convertibility(toType == typeof(BlockParam) && !toNotNullable, null); } if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) { return Convertibility.AlwaysConvertible; } if (toType.IsAssignableFrom(fromType)) { return Convertibility.AlwaysConvertible; } if (HasImplicitNumericConversion(fromType, toType)) { return Convertibility.AlwaysConvertible; } if (CompilerHelpers.GetImplicitConverter(fromType, toType) != null) { return Convertibility.AlwaysConvertible; } if (rubyMetaConvertible != null) { return rubyMetaConvertible.IsConvertibleTo(toType, false); } else if (metaConvertible != null) { return new Convertibility(metaConvertible.CanConvertTo(toType, false), null); } // // narrowing level 1: // if (level < NarrowingLevel.One) { return Convertibility.NotConvertible; } if (explicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return Convertibility.AlwaysConvertible; } // // narrowing level 2: // if (level < NarrowingLevel.Two) { return Convertibility.NotConvertible; } if (HasExplicitNumericConversion(fromType, toType)) { return Convertibility.AlwaysConvertible; } if (CompilerHelpers.GetExplicitConverter(fromType, toType) != null) { return Convertibility.AlwaysConvertible; } if (CompilerHelpers.HasTypeConverter(fromType, toType)) { return Convertibility.AlwaysConvertible; } if (fromType == typeof(char) && toType == typeof(string)) { return Convertibility.AlwaysConvertible; } if (toType == typeof(bool)) { return Convertibility.AlwaysConvertible; } if (rubyMetaConvertible != null) { return rubyMetaConvertible.IsConvertibleTo(toType, true); } else if (metaConvertible != null) { return new Convertibility(metaConvertible.CanConvertTo(toType, true), null); } // // narrowing level 3: // if (level < NarrowingLevel.Three) { return Convertibility.NotConvertible; } if (implicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return Convertibility.AlwaysConvertible; } // A COM object can potentially be converted to the given interface, but might also be not so use this only as the last resort: if (TypeUtils.IsComObjectType(fromType) && toType.IsInterface()) { return Convertibility.AlwaysConvertible; } return Convertibility.NotConvertible; }