private bool TryVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, AggregateDeclaration context, AggregateType typeSrc, out CType typeDst) { Debug.Assert(typeSrc != null); Debug.Assert(typeSrc.IsInterfaceType || typeSrc.IsDelegateType); typeDst = null; AggregateSymbol aggSym = typeSrc.OwningAggregate; AggregateType aggOpenType = aggSym.getThisType(); if (!semanticChecker.CheckTypeAccess(aggOpenType, context)) { // if the aggregate symbol itself is not accessible, then forget it, there is no // variance that will help us arrive at an accessible type. return(false); } TypeArray typeArgs = typeSrc.TypeArgsThis; TypeArray typeParams = aggOpenType.TypeArgsThis; CType[] newTypeArgsTemp = new CType[typeArgs.Count]; for (int i = 0; i < newTypeArgsTemp.Length; i++) { CType typeArg = typeArgs[i]; if (semanticChecker.CheckTypeAccess(typeArg, context)) { // we have an accessible argument, this position is not a problem. newTypeArgsTemp[i] = typeArg; continue; } if (!typeArg.IsReferenceType || !((TypeParameterType)typeParams[i]).Covariant) { // This guy is inaccessible, and we are not going to be able to vary him, so we need to fail. return(false); } newTypeArgsTemp[i] = GetBestAccessibleType(semanticChecker, context, typeArg); // now we either have a value type (which must be accessible due to the above // check, OR we have an inaccessible type (which must be a ref type). In either // case, the recursion worked out and we are OK to vary this argument. } TypeArray newTypeArgs = semanticChecker.getBSymmgr().AllocParams(typeArgs.Count, newTypeArgsTemp); CType intermediateType = GetAggregate(aggSym, typeSrc.OuterType, newTypeArgs); // All type arguments were varied successfully, which means now we must be accessible. But we could // have violated constraints. Let's check that out. if (!TypeBind.CheckConstraints(semanticChecker, errHandling: null, intermediateType, CheckConstraintsFlags.NoErrors)) { return(false); } typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, context)); return(true); }
private bool TryVarianceAdjustmentToGetAccessibleType(CSemanticChecker semanticChecker, BindingContext bindingContext, AggregateType typeSrc, out CType typeDst) { Debug.Assert(typeSrc != null); Debug.Assert(typeSrc.isInterfaceType() || typeSrc.isDelegateType()); typeDst = null; AggregateSymbol aggSym = typeSrc.GetOwningAggregate(); AggregateType aggOpenType = aggSym.getThisType(); if (!semanticChecker.CheckTypeAccess(aggOpenType, bindingContext.ContextForMemberLookup)) { // if the aggregate symbol itself is not accessible, then forget it, there is no // variance that will help us arrive at an accessible type. return(false); } TypeArray typeArgs = typeSrc.GetTypeArgsThis(); TypeArray typeParams = aggOpenType.GetTypeArgsThis(); CType[] newTypeArgsTemp = new CType[typeArgs.Count]; for (int i = 0; i < typeArgs.Count; i++) { if (semanticChecker.CheckTypeAccess(typeArgs[i], bindingContext.ContextForMemberLookup)) { // we have an accessible argument, this position is not a problem. newTypeArgsTemp[i] = typeArgs[i]; continue; } if (!typeArgs[i].IsRefType() || !((TypeParameterType)typeParams[i]).Covariant) { // This guy is inaccessible, and we are not going to be able to vary him, so we need to fail. return(false); } CType intermediateTypeArg; if (GetBestAccessibleType(semanticChecker, bindingContext, typeArgs[i], out intermediateTypeArg)) { // now we either have a value type (which must be accessible due to the above // check, OR we have an inaccessible type (which must be a ref type). In either // case, the recursion worked out and we are OK to vary this argument. newTypeArgsTemp[i] = intermediateTypeArg; continue; } else { Debug.Assert(false, "GetBestAccessibleType unexpectedly failed on a type that was used as a type parameter"); return(false); } } TypeArray newTypeArgs = semanticChecker.getBSymmgr().AllocParams(typeArgs.Count, newTypeArgsTemp); CType intermediateType = this.GetAggregate(aggSym, typeSrc.outerType, newTypeArgs); // All type arguments were varied successfully, which means now we must be accessible. But we could // have violated constraints. Let's check that out. if (!TypeBind.CheckConstraints(semanticChecker, null /*ErrorHandling*/, intermediateType, CheckConstraintsFlags.NoErrors)) { return(false); } typeDst = intermediateType; Debug.Assert(semanticChecker.CheckTypeAccess(typeDst, bindingContext.ContextForMemberLookup)); return(true); }