/*************************************************************************************************** * * There exists an explicit conversion ... * From a generic delegate type S to generic delegate type T, provided all of the follow are true: * o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is, * S is D<S1,... Sk> and T is D<T1,... Tk>. * o S is not compatible with or identical to T. * o If type parameter Xi is declared to be invariant then Si must be identical to Ti. * o If type parameter Xi is declared to be covariant ("out") then Si must be convertible * to Ti via an identify conversion, implicit reference conversion, or explicit reference conversion. * o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti, * or Si and Ti must both be reference types. ***************************************************************************************************/ public static bool HasGenericDelegateExplicitReferenceConversion(SymbolLoader loader, CType pSource, CType pTarget) { if (!pSource.isDelegateType() || !pTarget.isDelegateType() || pSource.getAggregate() != pTarget.getAggregate() || loader.HasIdentityOrImplicitReferenceConversion(pSource, pTarget)) { return(false); } TypeArray pTypeParams = pSource.getAggregate().GetTypeVarsAll(); TypeArray pSourceArgs = ((AggregateType)pSource).GetTypeArgsAll(); TypeArray pTargetArgs = ((AggregateType)pTarget).GetTypeArgsAll(); Debug.Assert(pTypeParams.Count == pSourceArgs.Count); Debug.Assert(pTypeParams.Count == pTargetArgs.Count); for (int iParam = 0; iParam < pTypeParams.Count; ++iParam) { CType pSourceArg = pSourceArgs[iParam]; CType pTargetArg = pTargetArgs[iParam]; // If they're identical then this one is automatically good, so skip it. // If we have an error type, then we're in some fault tolerance. Let it through. if (pSourceArg == pTargetArg) { continue; } TypeParameterType pParam = (TypeParameterType)pTypeParams[iParam]; if (pParam.Invariant) { return(false); } if (pParam.Covariant) { if (!FExpRefConv(loader, pSourceArg, pTargetArg)) { return(false); } } else if (pParam.Contravariant) { if (!pSourceArg.IsRefType() || !pTargetArg.IsRefType()) { return(false); } } } return(true); }
// We want to delay load the predefined symbols as needed. private AggregateSymbol DelayLoadPredefSym(PredefinedType pt) { CType type = _runtimeBinderSymbolTable.GetCTypeFromType(PredefinedTypeFacts.GetAssociatedSystemType(pt)); AggregateSymbol sym = type.getAggregate(); return(InitializePredefinedType(sym, pt)); }
// We want to delay load the predef syms as needed. private AggregateSymbol DelayLoadPredefSym(PredefinedType pt) { CType type = _runtimeBinderSymbolTable.GetCTypeFromType(PredefinedTypeFacts.GetAssociatedSystemType(pt)); AggregateSymbol sym = type.getAggregate(); // If we failed to load this thing, we have problems. if (sym == null) { return(null); } return(InitializePredefinedType(sym, pt)); }
private bool HasArrayConversionToInterface(ArrayType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (!pSource.IsSZArray) { return(false); } if (!pDest.isInterfaceType()) { return(false); } // * From a single-dimensional array type S[] to IList<T> or IReadOnlyList<T> and their base // interfaces, provided that there is an implicit identity or reference // conversion from S to T. // We only have six interfaces to check. IList<T>, IReadOnlyList<T> and their bases: // * The base interface of IList<T> is ICollection<T>. // * The base interface of ICollection<T> is IEnumerable<T>. // * The base interface of IEnumerable<T> is IEnumerable. // * The base interface of IReadOnlyList<T> is IReadOnlyCollection<T>. // * The base interface of IReadOnlyCollection<T> is IEnumerable<T>. if (pDest.isPredefType(PredefinedType.PT_IENUMERABLE)) { return(true); } AggregateType atsDest = pDest.AsAggregateType(); AggregateSymbol aggDest = pDest.getAggregate(); if (!aggDest.isPredefAgg(PredefinedType.PT_G_ILIST) && !aggDest.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) && !aggDest.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) && !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) && !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST)) { return(false); } Debug.Assert(atsDest.GetTypeArgsAll().Count == 1); CType pSourceElement = pSource.GetElementType(); CType pDestTypeArgument = atsDest.GetTypeArgsAll()[0]; return(HasIdentityOrImplicitReferenceConversion(pSourceElement, pDestTypeArgument)); }
/****************************************************************************** * Reports errors. Only call this if FError() is true. ******************************************************************************/ public void ReportErrors() { Debug.Assert(FError()); // Report error. // NOTE: If the definition of FError changes, this code will need to change. Debug.Assert(!_swtFirst || _swtAmbig); if (_swtFirst) { // Ambiguous lookup. GetErrorContext().ErrorRef(ErrorCode.ERR_AmbigMember, _swtFirst, _swtAmbig); } else if (_swtInaccess) { if (!_swtInaccess.Sym.isUserCallable() && ((_flags & MemLookFlags.UserCallable) != 0)) { GetErrorContext().Error(ErrorCode.ERR_CantCallSpecialMethod, _swtInaccess); } else { GetSemanticChecker().ReportAccessError(_swtInaccess, _symWhere, _typeQual); } } else if ((_flags & MemLookFlags.Ctor) != 0) { if (_arity > 0) { GetErrorContext().Error(ErrorCode.ERR_BadCtorArgCount, _typeSrc.getAggregate(), _arity); } else { GetErrorContext().Error(ErrorCode.ERR_NoConstructors, _typeSrc.getAggregate()); } } else if ((_flags & MemLookFlags.Operator) != 0) { GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); } else if ((_flags & MemLookFlags.Indexer) != 0) { GetErrorContext().Error(ErrorCode.ERR_BadIndexLHS, _typeSrc); } else if (_swtBad) { GetErrorContext().Error((_flags & MemLookFlags.MustBeInvocable) != 0 ? ErrorCode.ERR_NonInvocableMemberCalled : ErrorCode.ERR_CantCallSpecialMethod, _swtBad); } else if (_swtBogus) { ReportBogus(_swtBogus); } else if (_swtBadArity) { int cvar; switch (_swtBadArity.Sym.getKind()) { case SYMKIND.SK_MethodSymbol: Debug.Assert(_arity != 0); cvar = _swtBadArity.Sym.AsMethodSymbol().typeVars.size; GetErrorContext().ErrorRef(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar); break; case SYMKIND.SK_AggregateSymbol: cvar = _swtBadArity.Sym.AsAggregateSymbol().GetTypeVars().size; GetErrorContext().ErrorRef(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar); break; default: Debug.Assert(_arity != 0); ExpressionBinder.ReportTypeArgsNotAllowedError(GetSymbolLoader(), _arity, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym)); break; } } else { if ((_flags & MemLookFlags.ExtensionCall) != 0) { GetErrorContext().Error(ErrorCode.ERR_NoSuchMemberOrExtension, _typeSrc, _name); } else { GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name); } } }
/*************************************************************************************************** There exists an explicit conversion ... * From a generic delegate type S to generic delegate type T, provided all of the follow are true: o Both types are constructed generic types of the same generic delegate type, D<X1,... Xk>.That is, S is D<S1,... Sk> and T is D<T1,... Tk>. o S is not compatible with or identical to T. o If type parameter Xi is declared to be invariant then Si must be identical to Ti. o If type parameter Xi is declared to be covariant ("out") then Si must be convertible to Ti via an identify conversion, implicit reference conversion, or explicit reference conversion. o If type parameter Xi is declared to be contravariant ("in") then either Si must be identical to Ti, or Si and Ti must both be reference types. ***************************************************************************************************/ public static bool HasGenericDelegateExplicitReferenceConversion(SymbolLoader loader, CType pSource, CType pTarget) { if (!pSource.isDelegateType() || !pTarget.isDelegateType() || pSource.getAggregate() != pTarget.getAggregate() || loader.HasIdentityOrImplicitReferenceConversion(pSource, pTarget)) { return false; } TypeArray pTypeParams = pSource.getAggregate().GetTypeVarsAll(); TypeArray pSourceArgs = pSource.AsAggregateType().GetTypeArgsAll(); TypeArray pTargetArgs = pTarget.AsAggregateType().GetTypeArgsAll(); Debug.Assert(pTypeParams.size == pSourceArgs.size); Debug.Assert(pTypeParams.size == pTargetArgs.size); for (int iParam = 0; iParam < pTypeParams.size; ++iParam) { CType pSourceArg = pSourceArgs.Item(iParam); CType pTargetArg = pTargetArgs.Item(iParam); // If they're identical then this one is automatically good, so skip it. // If we have an error type, then we're in some fault tolerance. Let it through. if (pSourceArg == pTargetArg || pTargetArg.IsErrorType() || pSourceArg.IsErrorType()) { continue; } TypeParameterType pParam = pTypeParams.Item(iParam).AsTypeParameterType(); if (pParam.Invariant) { return false; } if (pParam.Covariant) { if (!FExpRefConv(loader, pSourceArg, pTargetArg)) { return false; } } else if (pParam.Contravariant) { if (!pSourceArg.IsRefType() || !pTargetArg.IsRefType()) { return false; } } } return true; }
/****************************************************************************** * Reports errors. Only call this if FError() is true. ******************************************************************************/ public Exception ReportErrors() { Debug.Assert(FError()); // Report error. // NOTE: If the definition of FError changes, this code will need to change. Debug.Assert(!_swtFirst || _swtAmbig); if (_swtFirst) { // Ambiguous lookup. return(GetErrorContext().Error(ErrorCode.ERR_AmbigMember, _swtFirst, _swtAmbig)); } if (_swtInaccess) { return(!_swtInaccess.Sym.isUserCallable() && ((_flags & MemLookFlags.UserCallable) != 0) ? GetErrorContext().Error(ErrorCode.ERR_CantCallSpecialMethod, _swtInaccess) : GetSemanticChecker().ReportAccessError(_swtInaccess, _symWhere, _typeQual)); } if ((_flags & MemLookFlags.Ctor) != 0) { return(_arity > 0 ? GetErrorContext().Error(ErrorCode.ERR_BadCtorArgCount, _typeSrc.getAggregate(), _arity) : GetErrorContext().Error(ErrorCode.ERR_NoConstructors, _typeSrc.getAggregate())); } if ((_flags & MemLookFlags.Operator) != 0) { return(GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name)); } if ((_flags & MemLookFlags.Indexer) != 0) { return(GetErrorContext().Error(ErrorCode.ERR_BadIndexLHS, _typeSrc)); } if (_swtBad) { return(GetErrorContext().Error((_flags & MemLookFlags.MustBeInvocable) != 0 ? ErrorCode.ERR_NonInvocableMemberCalled : ErrorCode.ERR_CantCallSpecialMethod, _swtBad)); } if (_swtBogus) { return(ReportBogus(_swtBogus)); } if (_swtBadArity) { int cvar; switch (_swtBadArity.Sym.getKind()) { case SYMKIND.SK_MethodSymbol: Debug.Assert(_arity != 0); cvar = ((MethodSymbol)_swtBadArity.Sym).typeVars.Count; return(GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar)); case SYMKIND.SK_AggregateSymbol: cvar = ((AggregateSymbol)_swtBadArity.Sym).GetTypeVars().Count; return(GetErrorContext().Error(cvar > 0 ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym), cvar)); default: Debug.Assert(_arity != 0); return(GetErrorContext().Error(ErrorCode.ERR_TypeArgsNotAllowed, _swtBadArity, new ErrArgSymKind(_swtBadArity.Sym))); } } return(GetErrorContext().Error(ErrorCode.ERR_NoSuchMember, _typeSrc, _name)); }
private bool HasArrayConversionToInterface(ArrayType pSource, CType pDest) { Debug.Assert(pSource != null); Debug.Assert(pDest != null); if (pSource.rank != 1) { return false; } if (!pDest.isInterfaceType()) { return false; } // * From a single-dimensional array type S[] to IList<T> or IReadOnlyList<T> and their base // interfaces, provided that there is an implicit identity or reference // conversion from S to T. // We only have six interfaces to check. IList<T>, IReadOnlyList<T> and their bases: // * The base interface of IList<T> is ICollection<T>. // * The base interface of ICollection<T> is IEnumerable<T>. // * The base interface of IEnumerable<T> is IEnumerable. // * The base interface of IReadOnlyList<T> is IReadOnlyCollection<T>. // * The base interface of IReadOnlyCollection<T> is IEnumerable<T>. if (pDest.isPredefType(PredefinedType.PT_IENUMERABLE)) { return true; } AggregateType atsDest = pDest.AsAggregateType(); AggregateSymbol aggDest = pDest.getAggregate(); if (!aggDest.isPredefAgg(PredefinedType.PT_G_ILIST) && !aggDest.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) && !aggDest.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) && !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) && !aggDest.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST)) { return false; } Debug.Assert(atsDest.GetTypeArgsAll().Size == 1); CType pSourceElement = pSource.GetElementType(); CType pDestTypeArgument = atsDest.GetTypeArgsAll().Item(0); return HasIdentityOrImplicitReferenceConversion(pSourceElement, pDestTypeArgument); }