///////////////////////////////////////////////////////////////////////////////// public void AddInconvertibleResult( MethodSymbol method, AggregateType currentType, TypeArray currentTypeArgs) { if (InconvertibleResult.Sym == null) { // This is the first one, so set it for error reporting usage. InconvertibleResult.Set(method, currentType, currentTypeArgs); } _inconvertibleResults.Add(new MethPropWithInst(method, currentType, currentTypeArgs)); }
/* SPEC: CType inference occurs as part of the compile-time processing of a method invocation and takes place before the overload resolution step of the invocation. When a particular method group is specified in a method invocation, and no CType arguments are specified as part of the method invocation, CType inference is applied to each generic method in the method group. If CType inference succeeds, then the inferred CType arguments are used to determine the types of formal parameters for subsequent overload resolution. If overload resolution chooses a generic method as the one to invoke then the inferred CType arguments are used as the actual CType arguments for the invocation. If CType inference for a particular method fails, that method does not participate in overload resolution. The failure of CType inference, in and of itself, does not cause a compile-time error. However, it often leads to a compile-time error when overload resolution then fails to find any applicable methods. If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. Otherwise, assume that the generic method has the following signature: Tr M<X1...Xn>(T1 x1 ... Tm xm) With a method call of the form M(E1...Em) the task of CType inference is to find unique CType arguments S1...Sn for each of the CType parameters X1...Xn so that the call M<S1...Sn>(E1...Em)becomes valid. During the process of inference each CType parameter Xi is either fixed to a particular CType Si or unfixed with an associated set of bounds. Each of the bounds is some CType T. Each bound is classified as an upper bound, lower bound or exact bound. Initially each CType variable Xi is unfixed with an empty set of bounds. */ // This file contains the implementation for method CType inference on calls (with // arguments, and method CType inference on conversion of method groups to delegate // types (which will not have arguments.) //////////////////////////////////////////////////////////////////////////////// public static bool Infer( ExpressionBinder binder, SymbolLoader symbolLoader, MethodSymbol pMethod, TypeArray pClassTypeArguments, TypeArray pMethodFormalParameterTypes, ArgInfos pMethodArguments, out TypeArray ppInferredTypeArguments) { Debug.Assert(pMethod != null); Debug.Assert(pMethod.typeVars.size > 0); Debug.Assert(pMethod.isParamArray || pMethod.Params == pMethodFormalParameterTypes); ppInferredTypeArguments = null; if (pMethodFormalParameterTypes.size == 0 || pMethod.InferenceMustFail()) { return false; } Debug.Assert(pMethodArguments != null); Debug.Assert(pMethodFormalParameterTypes != null); Debug.Assert(pMethodArguments.carg <= pMethodFormalParameterTypes.size); var inferrer = new MethodTypeInferrer(binder, symbolLoader, pMethodFormalParameterTypes, pMethodArguments, pMethod.typeVars, pClassTypeArguments); bool success; if (pMethodArguments.fHasExprs) { success = inferrer.InferTypeArgs(); } else { success = inferrer.InferForMethodGroupConversion(); } ppInferredTypeArguments = inferrer.GetResults(); return success; }
public TypeParameterSymbol CreateMethodTypeParameter(Name pName, MethodSymbol pParent, int index, int indexTotal) { TypeParameterSymbol pResult = newBasicSym(SYMKIND.SK_TypeParameterSymbol, pName, pParent).AsTypeParameterSymbol(); pResult.SetIndexInOwnParameters(index); pResult.SetIndexInTotalParameters(indexTotal); pResult.SetIsMethodTypeParameter(true); pResult.SetAccess(ACCESS.ACC_PRIVATE); // Always private - not accessible anywhere except their own type. return pResult; }
private bool isConvInTable(List<UdConvInfo> convTable, MethodSymbol meth, AggregateType ats, bool fSrc, bool fDst) { foreach (UdConvInfo conv in convTable) { if (conv.mwt.Meth() == meth && conv.mwt.GetType() == ats && conv.fSrcImplicit == fSrc && conv.fDstImplicit == fDst) { return true; } } return false; }
public void SetFirstUDConversion(MethodSymbol conv) { _pConvFirst = conv; }
public void SetConvNext(MethodSymbol conv) { Debug.Assert(isImplicit() || isExplicit()); Debug.Assert(conv == null || conv.isImplicit() || conv.isExplicit()); _convNext = conv; }
public void SetConvNext(MethodSymbol conv) { Debug.Assert(isImplicit() || isExplicit()); Debug.Assert(conv == null || conv.isImplicit() || conv.isExplicit()); _convNext = conv; }
public ExprMethodInfo CreateMethodInfo(MethodSymbol method, AggregateType methodType, TypeArray methodParameters) { return(new ExprMethodInfo( Types.GetPredefAgg(method.IsConstructor() ? PredefinedType.PT_CONSTRUCTORINFO : PredefinedType.PT_METHODINFO).getThisType(), method, methodType, methodParameters)); }
///////////////////////////////////////////////////////////////////////////////// private TypeParameterType LoadMethodTypeParameter(MethodSymbol parent, Type t) { for (Symbol sym = parent.firstChild; sym != null; sym = sym.nextChild) { if (!sym.IsTypeParameterSymbol()) { continue; } if (AreTypeParametersEquivalent(sym.AsTypeParameterSymbol().GetTypeParameterType().AssociatedSystemType, t)) { return sym.AsTypeParameterSymbol().GetTypeParameterType(); } } return AddTypeParameterToSymbolTable(null, parent, t, false); }
protected void ErrAppendMethodParentSym(MethodSymbol sym, SubstContext pcxt, out TypeArray substMethTyParams) { substMethTyParams = null; ErrAppendParentSym(sym, pcxt); }
public MethWithType(MethodSymbol meth, AggregateType ats) { Set(meth, ats); }
public EXPRMETHODINFO CreateMethodInfo(MethodSymbol method, AggregateType methodType, TypeArray methodParameters) { Debug.Assert(method != null); Debug.Assert(methodType != null); EXPRMETHODINFO methodInfo = new EXPRMETHODINFO(); CType type; if (method.IsConstructor()) { type = GetTypes().GetOptPredefAgg(PredefinedType.PT_CONSTRUCTORINFO).getThisType(); } else { type = GetTypes().GetOptPredefAgg(PredefinedType.PT_METHODINFO).getThisType(); } methodInfo.kind = ExpressionKind.EK_METHODINFO; methodInfo.type = type; methodInfo.flags = 0; methodInfo.Method = new MethWithInst(method, methodType, methodParameters); return methodInfo; }
protected Symbol newBasicSym( SYMKIND kind, Name name, ParentSymbol parent) { // The parser creates names with PN_MISSING when attempting to recover from errors // To prevent spurious errors, we create SYMs with a different name (PN_MISSINGSYM) // so that they are never found when doing lookup. if (name == m_pMissingNameNode) { name = m_pMissingNameSym; } Symbol sym; switch (kind) { case SYMKIND.SK_NamespaceSymbol: sym = new NamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_NamespaceDeclaration: sym = new NamespaceDeclaration(); sym.name = name; break; case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol: sym = new AssemblyQualifiedNamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateSymbol: sym = new AggregateSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateDeclaration: sym = new AggregateDeclaration(); sym.name = name; break; case SYMKIND.SK_TypeParameterSymbol: sym = new TypeParameterSymbol(); sym.name = name; break; case SYMKIND.SK_FieldSymbol: sym = new FieldSymbol(); sym.name = name; break; case SYMKIND.SK_LocalVariableSymbol: sym = new LocalVariableSymbol(); sym.name = name; break; case SYMKIND.SK_MethodSymbol: sym = new MethodSymbol(); sym.name = name; break; case SYMKIND.SK_PropertySymbol: sym = new PropertySymbol(); sym.name = name; break; case SYMKIND.SK_EventSymbol: sym = new EventSymbol(); sym.name = name; break; case SYMKIND.SK_TransparentIdentifierMemberSymbol: sym = new TransparentIdentifierMemberSymbol(); sym.name = name; break; case SYMKIND.SK_Scope: sym = new Scope(); sym.name = name; break; case SYMKIND.SK_LabelSymbol: sym = new LabelSymbol(); sym.name = name; break; case SYMKIND.SK_GlobalAttributeDeclaration: sym = new GlobalAttributeDeclaration(); sym.name = name; break; case SYMKIND.SK_UnresolvedAggregateSymbol: sym = new UnresolvedAggregateSymbol(); sym.name = name; break; case SYMKIND.SK_InterfaceImplementationMethodSymbol: sym = new InterfaceImplementationMethodSymbol(); sym.name = name; break; case SYMKIND.SK_IndexerSymbol: sym = new IndexerSymbol(); sym.name = name; break; case SYMKIND.SK_ParentSymbol: sym = new ParentSymbol(); sym.name = name; break; case SYMKIND.SK_IteratorFinallyMethodSymbol: sym = new IteratorFinallyMethodSymbol(); sym.name = name; break; default: throw Error.InternalCompilerError(); } sym.setKind(kind); if (parent != null) { // Set the parent element of the child symbol. parent.AddToChildList(sym); m_pSymTable.InsertChild(parent, sym); } return (sym); }
private void ReportBogusForEventsAndProperties(SymWithType swt, MethodSymbol meth1, MethodSymbol meth2) { if (meth1 != null && meth2 != null) { GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp2, swt.Sym.name, new SymWithType(meth1, swt.GetType()), new SymWithType(meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); return; } if (meth1 != null || meth2 != null) { GetErrorContext().Error(ErrorCode.ERR_BindToBogusProp1, swt.Sym.name, new SymWithType(meth1 != null ? meth1 : meth2, swt.GetType()), new ErrArgRefOnly(swt.Sym)); return; } throw Error.InternalCompilerError(); }
public void SetFirstUDConversion(MethodSymbol conv) { _pConvFirst = conv; }
private Symbol NewBasicSymbol( SYMKIND kind, Name name, ParentSymbol parent) { Symbol sym; switch (kind) { case SYMKIND.SK_NamespaceSymbol: sym = new NamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol: sym = new AssemblyQualifiedNamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateSymbol: sym = new AggregateSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateDeclaration: sym = new AggregateDeclaration(); sym.name = name; break; case SYMKIND.SK_TypeParameterSymbol: sym = new TypeParameterSymbol(); sym.name = name; break; case SYMKIND.SK_FieldSymbol: sym = new FieldSymbol(); sym.name = name; break; case SYMKIND.SK_LocalVariableSymbol: sym = new LocalVariableSymbol(); sym.name = name; break; case SYMKIND.SK_MethodSymbol: sym = new MethodSymbol(); sym.name = name; break; case SYMKIND.SK_PropertySymbol: sym = new PropertySymbol(); sym.name = name; break; case SYMKIND.SK_EventSymbol: sym = new EventSymbol(); sym.name = name; break; case SYMKIND.SK_Scope: sym = new Scope(); sym.name = name; break; case SYMKIND.SK_IndexerSymbol: sym = new IndexerSymbol(); sym.name = name; break; default: throw Error.InternalCompilerError(); } sym.setKind(kind); if (parent != null) { // Set the parent element of the child symbol. parent.AddToChildList(sym); _symbolTable.InsertChild(parent, sym); } return(sym); }
//////////////////////////////////////////////////////////////////////////////// // // In error recovery and reporting scenarios we sometimes end up in a situation // like this: // // x.Foo( y=> // // and the question is, "is Foo a valid extension method of x?" If Foo is // generic, then Foo will be something like: // // static Blah Foo<T>(this Bar<T> bar, Func<T, T> f){ ... } // // What we would like to know is: given _only_ the expression x, can we infer // what T is in Bar<T> ? If we can, then for error recovery and reporting // we can provisionally consider Foo to be an extension method of x. If we // cannot deduce this just from x then we should consider Foo to not be an // extension method of x, at least until we have more information. // // Clearly it is pointless to run multiple phases public static bool CanObjectOfExtensionBeInferred( ExpressionBinder binder, SymbolLoader symbolLoader, MethodSymbol pMethod, TypeArray pClassTypeArguments, TypeArray pMethodFormalParameterTypes, ArgInfos pMethodArguments) { Debug.Assert(pMethod != null); Debug.Assert(pMethod.typeVars.size > 0); Debug.Assert(pMethodFormalParameterTypes != null); Debug.Assert(pMethod.isParamArray || pMethod.Params == pMethodFormalParameterTypes); // We need at least one formal parameter type and at least one argument. if (pMethodFormalParameterTypes.size < 1 || pMethod.InferenceMustFail()) { return false; } Debug.Assert(pMethodArguments != null); Debug.Assert(pMethodArguments.carg <= pMethodFormalParameterTypes.size); if (pMethodArguments.carg < 1) { return false; } var inferrer = new MethodTypeInferrer(binder, symbolLoader, pMethodFormalParameterTypes, pMethodArguments, pMethod.typeVars, pClassTypeArguments); return inferrer.CanInferExtensionObject(); }
public MethWithInst(MethodSymbol meth, AggregateType ats, TypeArray typeArgs) { Set(meth, ats, typeArgs); }
protected void ErrAppendMethod(MethodSymbol meth, SubstContext pctx, bool fArgs) { if (meth.IsExpImpl() && meth.swtSlot) { ErrAppendParentSym(meth, pctx); // Get the type args from the explicit impl type and substitute using pctx (if there is one). SubstContext ctx = new SubstContext(GetTypeManager().SubstType(meth.swtSlot.GetType(), pctx).AsAggregateType()); ErrAppendSym(meth.swtSlot.Sym, ctx, fArgs); // args already added return; } if (meth.isPropertyAccessor()) { PropertySymbol prop = meth.getProperty(); // this includes the parent class ErrAppendSym(prop, pctx); // add accessor name if (prop.methGet == meth) { ErrAppendString(".get"); } else { Debug.Assert(meth == prop.methSet); ErrAppendString(".set"); } // args already added return; } if (meth.isEventAccessor()) { EventSymbol @event = meth.getEvent(); // this includes the parent class ErrAppendSym(@event, pctx); // add accessor name if (@event.methAdd == meth) { ErrAppendString(".add"); } else { Debug.Assert(meth == @event.methRemove); ErrAppendString(".remove"); } // args already added return; } TypeArray replacementTypeArray = null; ErrAppendMethodParentSym(meth, pctx, out replacementTypeArray); if (meth.IsConstructor()) { // Use the name of the parent class instead of the name "<ctor>". ErrAppendName(meth.getClass().name); } else if (meth.IsDestructor()) { // Use the name of the parent class instead of the name "Finalize". ErrAppendChar('~'); ErrAppendName(meth.getClass().name); } else if (meth.isConversionOperator()) { // implicit/explicit ErrAppendString(meth.isImplicit() ? "implicit" : "explicit"); ErrAppendString(" operator "); // destination type name ErrAppendType(meth.RetType, pctx); } else if (meth.isOperator) { // handle user defined operators // map from CLS predefined names to "operator <X>" ErrAppendString("operator "); // // This is kinda slow, but the alternative is to add bits to methsym. // string operatorName; OperatorKind op = Operators.OperatorOfMethodName(GetNameManager(), meth.name); if (Operators.HasDisplayName(op)) { operatorName = Operators.GetDisplayName(op); } else { // // either equals or compare // if (meth.name == GetNameManager().GetPredefName(PredefinedName.PN_OPEQUALS)) { operatorName = "equals"; } else { Debug.Assert(meth.name == GetNameManager().GetPredefName(PredefinedName.PN_OPCOMPARE)); operatorName = "compare"; } } ErrAppendString(operatorName); } else if (meth.IsExpImpl()) { if (meth.errExpImpl != null) ErrAppendType(meth.errExpImpl, pctx, fArgs); } else { // regular method ErrAppendName(meth.name); } if (null == replacementTypeArray) { ErrAppendTypeParameters(meth.typeVars, pctx, false); } if (fArgs) { // append argument types ErrAppendChar('('); if (!meth.computeCurrentBogusState()) { ErrAppendParamList(GetTypeManager().SubstTypeArray(meth.Params, pctx), meth.isVarargs, meth.isParamArray); } ErrAppendChar(')'); } }
/****************************************************************************** * Search just the given type (not any bases). Returns true iff it finds * something (which will have been recorded by RecordType). * * pfHideByName is set to true iff something was found that hides all * members of base types (eg, a hidebyname method). ******************************************************************************/ private bool SearchSingleType(AggregateType typeCur, out bool pfHideByName) { bool fFoundSome = false; pfHideByName = false; // Make sure this type is accessible. It may not be due to private inheritance // or friend assemblies. bool fInaccess = !CSemanticChecker.CheckTypeAccess(typeCur, _symWhere); if (fInaccess && (_csym != 0 || _swtInaccess != null)) { return(false); } // Loop through symbols. Symbol symCur; for (symCur = SymbolLoader.LookupAggMember(_name, typeCur.OwningAggregate, symbmask_t.MASK_Member); symCur != null; symCur = symCur.LookupNext(symbmask_t.MASK_Member)) { Debug.Assert(!(symCur is AggregateSymbol)); // Check for arity. // For non-zero arity, only methods of the correct arity are considered. // For zero arity, don't filter out any methods since we do type argument // inferencing. // All others are only considered when arity is zero. if (_arity > 0 && (!(symCur is MethodSymbol curMeth) || curMeth.typeVars.Count != _arity)) { if (!_swtBadArity) { _swtBadArity.Set(symCur, typeCur); } continue; } // Check for user callability. if (symCur.IsOverride() && !symCur.IsHideByName()) { continue; } MethodOrPropertySymbol methProp = symCur as MethodOrPropertySymbol; MethodSymbol meth = symCur as MethodSymbol; if (methProp != null && (_flags & MemLookFlags.UserCallable) != 0 && !methProp.isUserCallable()) { // If its an indexed property method symbol, let it through. // This is too liberal, but maintained for compatibility. if (meth == null || !meth.isPropertyAccessor() || (!symCur.name.Text.StartsWith("set_", StringComparison.Ordinal) || meth.Params.Count <= 1) && (!symCur.name.Text.StartsWith("get_", StringComparison.Ordinal) || meth.Params.Count <= 0)) { if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } continue; } } if (fInaccess || !CSemanticChecker.CheckAccess(symCur, typeCur, _symWhere, _typeQual)) { // Not accessible so get the next sym. if (!_swtInaccess) { _swtInaccess.Set(symCur, typeCur); } if (fInaccess) { return(false); } continue; } PropertySymbol prop = symCur as PropertySymbol; // Make sure that whether we're seeing a ctor, operator, or indexer is consistent with the flags. if (((_flags & MemLookFlags.Ctor) == 0) != (meth == null || !meth.IsConstructor()) || ((_flags & MemLookFlags.Operator) == 0) != (meth == null || !meth.isOperator) || ((_flags & MemLookFlags.Indexer) == 0) != !(prop is IndexerSymbol)) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } // We can't call CheckBogus on methods or indexers because if the method has the wrong // number of parameters people don't think they should have to /r the assemblies containing // the parameter types and they complain about the resulting CS0012 errors. if (!(symCur is MethodSymbol) && (_flags & MemLookFlags.Indexer) == 0 && CSemanticChecker.CheckBogus(symCur)) { // A bogus member - we can't use these, so only record them for error reporting. if (!_swtBogus) { _swtBogus.Set(symCur, typeCur); } continue; } // if we are in a calling context then we should only find a property if it is delegate valued if ((_flags & MemLookFlags.MustBeInvocable) != 0) { if ((symCur is FieldSymbol field && !IsDelegateType(field.GetType(), typeCur) && !IsDynamicMember(symCur)) || (prop != null && !IsDelegateType(prop.RetType, typeCur) && !IsDynamicMember(symCur))) { if (!_swtBad) { _swtBad.Set(symCur, typeCur); } continue; } } if (methProp != null) { MethPropWithType mwpInsert = new MethPropWithType(methProp, typeCur); _methPropWithTypeList.Add(mwpInsert); } // We have a visible symbol. fFoundSome = true; if (_swtFirst) { if (!typeCur.IsInterfaceType) { // Non-interface case. Debug.Assert(_fMulti || typeCur == _prgtype[0]); if (!_fMulti) { if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol // The isEvent bit is only set on symbols which come from source... // This is not a problem for the compiler because the field is only // accessible in the scope in which it is declared, // but in the EE we ignore accessibility... && _swtFirst.Field().isEvent ) { // m_swtFirst is just the field behind the event symCur so ignore symCur. continue; } else if (_swtFirst.Sym is FieldSymbol && symCur is EventSymbol) { // symCur is the matching event. continue; } goto LAmbig; } if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (typeCur == _prgtype[0]) { goto LAmbig; } // This one is hidden by the first one. This one also hides any more in base types. pfHideByName = true; continue; } } // Interface case. // m_fMulti : n n n y y y y y // same-kind : * * * y n n n n // fDiffHidden: * * * * y n n n // meth : * * * * * y n * can n happen? just in case, we better handle it.... // hack : n * y * * y * n // meth-2 : * n y * * * * * // res : A A S R H H A A else if (!_fMulti) { // Give method groups priority. if (!(symCur is MethodSymbol)) { goto LAmbig; } // Erase previous results so we'll record this method as the first. _prgtype = new List <AggregateType>(); _csym = 0; _swtFirst.Clear(); _swtAmbig.Clear(); } else if (_swtFirst.Sym.getKind() != symCur.getKind()) { if (!typeCur.DiffHidden) { // Give method groups priority. if (!(_swtFirst.Sym is MethodSymbol)) { goto LAmbig; } } // This one is hidden by another. This one also hides any more in base types. pfHideByName = true; continue; } } RecordType(typeCur, symCur); if (methProp != null && methProp.isHideByName) { pfHideByName = true; } // We've found a symbol in this type but need to make sure there aren't any conflicting // syms here, so keep searching the type. } Debug.Assert(!fInaccess || !fFoundSome); return(fFoundSome); LAmbig: // Ambiguous! if (!_swtAmbig) { _swtAmbig.Set(symCur, typeCur); } pfHideByName = true; return(true); }
public MethWithInst(MethodSymbol meth, AggregateType ats) : this(meth, ats, null) { }
private bool UserDefinedBinaryOperatorCanBeLifted(ExpressionKind ek, MethodSymbol method, AggregateType ats, TypeArray Params) { if (!Params.Item(0).IsNonNubValType()) { return false; } if (!Params.Item(1).IsNonNubValType()) { return false; } CType typeRet = GetTypes().SubstType(method.RetType, ats); if (!typeRet.IsNonNubValType()) { return false; } switch (ek) { case ExpressionKind.EK_EQ: case ExpressionKind.EK_NE: if (!typeRet.isPredefType(PredefinedType.PT_BOOL)) { return false; } if (Params.Item(0) != Params.Item(1)) { return false; } return true; case ExpressionKind.EK_GT: case ExpressionKind.EK_GE: case ExpressionKind.EK_LT: case ExpressionKind.EK_LE: if (!typeRet.isPredefType(PredefinedType.PT_BOOL)) { return false; } return true; default: return true; } }
///////////////////////////////////////////////////////////////////////////////// private TypeArray GetMethodTypeParameters(MethodInfo method, MethodSymbol parent) { if (method.IsGenericMethod) { Type[] genericArguments = method.GetGenericArguments(); CType[] ctypes = new CType[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { Type t = genericArguments[i]; ctypes[i] = LoadMethodTypeParameter(parent, t); } // After we load the type parameters, we need to resolve their bounds. for (int i = 0; i < genericArguments.Length; i++) { Type t = genericArguments[i]; ctypes[i].AsTypeParameterType().GetTypeParameterSymbol().SetBounds( _bsymmgr.AllocParams( GetCTypeArrayFromTypes(t.GetTypeInfo().GetGenericParameterConstraints()))); } return _bsymmgr.AllocParams(ctypes.Length, ctypes); } return BSYMMGR.EmptyTypeArray(); }
// If the operator is applicable in either its regular or lifted forms, // add it to the candidate set and return true, otherwise return false. private bool UserDefinedBinaryOperatorIsApplicable(List<CandidateFunctionMember> candidateList, ExpressionKind ek, MethodSymbol method, AggregateType ats, EXPR arg1, EXPR arg2, bool fDontLift) { if (!method.isOperator || method.Params.size != 2) { return false; } Debug.Assert(method.typeVars.size == 0); TypeArray paramsCur = GetTypes().SubstTypeArray(method.Params, ats); if (canConvert(arg1, paramsCur.Item(0)) && canConvert(arg2, paramsCur.Item(1))) { candidateList.Add(new CandidateFunctionMember( new MethPropWithInst(method, ats, BSYMMGR.EmptyTypeArray()), paramsCur, 0, // No lifted arguments false)); return true; } if (fDontLift || !GetSymbolLoader().FCanLift() || !UserDefinedBinaryOperatorCanBeLifted(ek, method, ats, paramsCur)) { return false; } CType[] rgtype = new CType[2]; rgtype[0] = GetTypes().GetNullable(paramsCur.Item(0)); rgtype[1] = GetTypes().GetNullable(paramsCur.Item(1)); if (!canConvert(arg1, rgtype[0]) || !canConvert(arg2, rgtype[1])) { return false; } candidateList.Add(new CandidateFunctionMember( new MethPropWithInst(method, ats, BSYMMGR.EmptyTypeArray()), GetGlobalSymbols().AllocParams(2, rgtype), 2, // two lifted arguments false)); return true; }
///////////////////////////////////////////////////////////////////////////////// private TypeParameterType AddTypeParameterToSymbolTable( AggregateSymbol agg, MethodSymbol meth, Type t, bool bIsAggregate) { Debug.Assert((agg != null && bIsAggregate) || (meth != null && !bIsAggregate)); TypeParameterSymbol typeParam; if (bIsAggregate) { typeParam = _symFactory.CreateClassTypeParameter( GetName(t), agg, t.GenericParameterPosition, t.GenericParameterPosition); } else { typeParam = _symFactory.CreateMethodTypeParameter( GetName(t), meth, t.GenericParameterPosition, t.GenericParameterPosition); } if ((t.GetTypeInfo().GenericParameterAttributes & GenericParameterAttributes.Covariant) != 0) { typeParam.Covariant = true; } if ((t.GetTypeInfo().GenericParameterAttributes & GenericParameterAttributes.Contravariant) != 0) { typeParam.Contravariant = true; } SpecCons cons = SpecCons.None; if ((t.GetTypeInfo().GenericParameterAttributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0) { cons |= SpecCons.New; } if ((t.GetTypeInfo().GenericParameterAttributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0) { cons |= SpecCons.Ref; } if ((t.GetTypeInfo().GenericParameterAttributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) { cons |= SpecCons.Val; } typeParam.SetConstraints(cons); typeParam.SetAccess(ACCESS.ACC_PUBLIC); TypeParameterType typeParamType = _typeManager.GetTypeParameter(typeParam); return typeParamType; }
protected Symbol newBasicSym( SYMKIND kind, Name name, ParentSymbol parent) { // The parser creates names with PN_MISSING when attempting to recover from errors // To prevent spurious errors, we create SYMs with a different name (PN_MISSINGSYM) // so that they are never found when doing lookup. if (name == m_pMissingNameNode) { name = m_pMissingNameSym; } Symbol sym; switch (kind) { case SYMKIND.SK_NamespaceSymbol: sym = new NamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_NamespaceDeclaration: sym = new NamespaceDeclaration(); sym.name = name; break; case SYMKIND.SK_AssemblyQualifiedNamespaceSymbol: sym = new AssemblyQualifiedNamespaceSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateSymbol: sym = new AggregateSymbol(); sym.name = name; break; case SYMKIND.SK_AggregateDeclaration: sym = new AggregateDeclaration(); sym.name = name; break; case SYMKIND.SK_TypeParameterSymbol: sym = new TypeParameterSymbol(); sym.name = name; break; case SYMKIND.SK_FieldSymbol: sym = new FieldSymbol(); sym.name = name; break; case SYMKIND.SK_LocalVariableSymbol: sym = new LocalVariableSymbol(); sym.name = name; break; case SYMKIND.SK_MethodSymbol: sym = new MethodSymbol(); sym.name = name; break; case SYMKIND.SK_PropertySymbol: sym = new PropertySymbol(); sym.name = name; break; case SYMKIND.SK_EventSymbol: sym = new EventSymbol(); sym.name = name; break; case SYMKIND.SK_TransparentIdentifierMemberSymbol: sym = new TransparentIdentifierMemberSymbol(); sym.name = name; break; case SYMKIND.SK_Scope: sym = new Scope(); sym.name = name; break; case SYMKIND.SK_LabelSymbol: sym = new LabelSymbol(); sym.name = name; break; case SYMKIND.SK_GlobalAttributeDeclaration: sym = new GlobalAttributeDeclaration(); sym.name = name; break; case SYMKIND.SK_UnresolvedAggregateSymbol: sym = new UnresolvedAggregateSymbol(); sym.name = name; break; case SYMKIND.SK_InterfaceImplementationMethodSymbol: sym = new InterfaceImplementationMethodSymbol(); sym.name = name; break; case SYMKIND.SK_IndexerSymbol: sym = new IndexerSymbol(); sym.name = name; break; case SYMKIND.SK_ParentSymbol: sym = new ParentSymbol(); sym.name = name; break; case SYMKIND.SK_IteratorFinallyMethodSymbol: sym = new IteratorFinallyMethodSymbol(); sym.name = name; break; default: throw Error.InternalCompilerError(); } sym.setKind(kind); if (parent != null) { // Set the parent element of the child symbol. parent.AddToChildList(sym); m_pSymTable.InsertChild(parent, sym); } return(sym); }