public virtual bool CheckTypeAccess(CType type, Symbol symWhere) { Debug.Assert(type != null); // Array, Ptr, Nub, etc don't matter. type = type.GetNakedType(true); if (!type.IsAggregateType()) { Debug.Assert(type.IsVoidType() || type.IsErrorType() || type.IsTypeParameterType()); return(true); } for (AggregateType ats = type.AsAggregateType(); ats != null; ats = ats.outerType) { if (ACCESSERROR.ACCESSERROR_NOERROR != CheckAccessCore(ats.GetOwningAggregate(), ats.outerType, symWhere, null)) { return(false); } } TypeArray typeArgs = type.AsAggregateType().GetTypeArgsAll(); for (int i = 0; i < typeArgs.size; i++) { if (!CheckTypeAccess(typeArgs.Item(i), symWhere)) { return(false); } } return(true); }
private AggCastResult bindExplicitConversionToAggregate(AggregateType aggTypeDest) { Debug.Assert(_typeSrc != null); Debug.Assert(aggTypeDest != null); // TypeReference and ArgIterator can't be boxed (or converted to anything else) if (_typeSrc.isSpecialByRefType()) { return(AggCastResult.Abort); } AggCastResult result; result = bindExplicitConversionFromEnumToAggregate(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } result = bindExplicitConversionToEnum(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } result = bindExplicitConversionBetweenSimpleTypes(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } result = bindExplicitConversionBetweenAggregates(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } result = bindExplicitConversionFromPointerToInt(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } if (_typeSrc.IsVoidType()) { // No conversion is allowed to or from a void type (user defined or otherwise) // This is most likely the result of a failed anonymous method or member group conversion return(AggCastResult.Abort); } result = bindExplicitConversionFromTypeVarToAggregate(aggTypeDest); if (result != AggCastResult.Failure) { return(result); } return(AggCastResult.Failure); }
public virtual bool CheckTypeAccess(CType type, Symbol symWhere) { Debug.Assert(type != null); // Array, Ptr, Nub, etc don't matter. type = type.GetNakedType(true); if (!type.IsAggregateType()) { Debug.Assert(type.IsVoidType() || type.IsErrorType() || type.IsTypeParameterType()); return true; } for (AggregateType ats = type.AsAggregateType(); ats != null; ats = ats.outerType) { if (ACCESSERROR.ACCESSERROR_NOERROR != CheckAccessCore(ats.GetOwningAggregate(), ats.outerType, symWhere, null)) { return false; } } TypeArray typeArgs = type.AsAggregateType().GetTypeArgsAll(); for (int i = 0; i < typeArgs.size; i++) { if (!CheckTypeAccess(typeArgs.Item(i), symWhere)) return false; } return true; }
//////////////////////////////////////////////////////////////////////////////// private static bool IsReallyAType(CType pType) { if (pType.IsNullType() || pType.IsBoundLambdaType() || pType.IsVoidType() || pType.IsMethodGroupType()) { return false; } return true; }
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // RUNTIME BINDER ONLY CHANGE // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! internal bool GetBestAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, CType typeSrc, out CType typeDst) { // This method implements the "best accessible type" algorithm for determining the type // of untyped arguments in the runtime binder. It is also used in method type inference // to fix type arguments to types that are accessible. // The new type is returned in an out parameter. The result will be true (and the out param // non-null) only when the algorithm could find a suitable accessible type. Debug.Assert(semanticChecker != null); Debug.Assert(bindingContext != null); Debug.Assert(typeSrc != null); typeDst = null; if (semanticChecker.CheckTypeAccess(typeSrc, bindingContext.ContextForMemberLookup())) { // If we already have an accessible type, then use it. This is the terminal point of the recursion. typeDst = typeSrc; return true; } // These guys have no accessibility concerns. Debug.Assert(!typeSrc.IsVoidType() && !typeSrc.IsErrorType() && !typeSrc.IsTypeParameterType()); if (typeSrc.IsParameterModifierType() || typeSrc.IsPointerType()) { // We cannot vary these. return false; } CType intermediateType; if ((typeSrc.isInterfaceType() || typeSrc.isDelegateType()) && TryVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsAggregateType(), out intermediateType)) { // If we have an interface or delegate type, then it can potentially be varied by its type arguments // to produce an accessible type, and if that's the case, then return that. // Example: IEnumerable<PrivateConcreteFoo> --> IEnumerable<PublicAbstractFoo> typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup())); return true; } if (typeSrc.IsArrayType() && TryArrayVarianceAdjustmentToGetAccessibleType(semanticChecker, bindingContext, typeSrc.AsArrayType(), out intermediateType)) { // Similarly to the interface and delegate case, arrays are covariant in their element type and // so we can potentially produce an array type that is accessible. // Example: PrivateConcreteFoo[] --> PublicAbstractFoo[] typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup())); return true; } if (typeSrc.IsNullableType()) { // We have an inaccessible nullable type, which means that the best we can do is System.ValueType. typeDst = this.GetOptPredefAgg(PredefinedType.PT_VALUE).getThisType(); Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup())); return true; } if (typeSrc.IsArrayType()) { // We have an inaccessible array type for which we could not earlier find a better array type // with a covariant conversion, so the best we can do is System.Array. typeDst = this.GetReqPredefAgg(PredefinedType.PT_ARRAY).getThisType(); Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup())); return true; } Debug.Assert(typeSrc.IsAggregateType()); if (typeSrc.IsAggregateType()) { // We have an AggregateType, so recurse on its base class. AggregateType aggType = typeSrc.AsAggregateType(); AggregateType baseType = aggType.GetBaseClass(); if (baseType == null) { // This happens with interfaces, for instance. But in that case, the // conversion to object does exist, is an implicit reference conversion, // and so we will use it. baseType = this.GetReqPredefAgg(PredefinedType.PT_OBJECT).getThisType(); } return GetBestAccessibleType(semanticChecker, bindingContext, baseType, out typeDst); } return false; }