/// <summary> /// If (we believe) we know which symbol the user intended, then we should retain that information /// in the corresponding error symbol - it can be useful for deciding how to handle the error. /// For example, we might want to know whether (we believe) the error type was supposed to be an /// interface, so that we can put it in a derived type's interface list, rather than in the base /// type slot. /// /// Sometimes we will return the original definition of the intended symbol. For example, if we see /// <![CDATA[IGoo<int>]]> and we have an IGoo with a different arity or accessibility /// (e.g. <![CDATA[IGoo<int>]]> was constructed from an error symbol based on <![CDATA[IGoo<T>]]>), /// then we'll return <![CDATA[IGoo<T>]]>, rather than trying to construct a corresponding closed /// type (which may not be difficult/possible in the case of nested types or mismatched arities). /// /// NOTE: Any non-null type symbol returned is guaranteed not to be an error type. /// </summary> /// <remarks> /// TypeSymbolExtensions.GetNonErrorGuess is a more discoverable version of this functionality. /// However, the real definition is in this class so that it can access the private field /// nonErrorGuessType. /// </remarks> internal static TypeSymbol ExtractNonErrorType(TypeSymbol oldSymbol) { if ((object)oldSymbol == null || oldSymbol.TypeKind != TypeKind.Error) { return(oldSymbol); } // At this point, we know that oldSymbol is a non-null type symbol with kind error. // Hence, it is either an ErrorTypeSymbol or it has an ErrorTypeSymbol as its // original definition. In the former case, it is its own original definition. // Thus, if there's a CSErrorTypeSymbol in there somewhere, it's returned by // OriginalDefinition. ExtendedErrorTypeSymbol oldError = oldSymbol.OriginalDefinition as ExtendedErrorTypeSymbol; // If the original definition isn't a CSErrorTypeSymbol, then we don't know how to // pull out a non-error type. If it is, then if there is a unambiguous type inside it, // use that. if ((object)oldError != null && !oldError._candidateSymbols.IsDefault && oldError._candidateSymbols.Length == 1) { TypeSymbol type = oldError._candidateSymbols[0] as TypeSymbol; if ((object)type != null) { return(type.GetNonErrorGuess()); } } return(null); }
internal SemanticInfo( TypeSymbol type, Conversion conversion, TypeSymbol convertedType, ReadOnlyArray <Symbol> symbols, LookupResultKind resultKind, ReadOnlyArray <MethodSymbol> methodGroup, ConstantValue constantValue) { // When constructing the result for the Caas API, we expose the underlying symbols that // may have been hidden under error type, if the error type was immediate. We will // expose error types that were constructed, or type parameters of constructed types. this.Type = type.GetNonErrorGuess() ?? type; this.ConvertedType = convertedType.GetNonErrorGuess() ?? convertedType; this.ImplicitConversion = conversion; this.symbols = symbols; this.resultKind = resultKind; if (!symbols.Any()) { this.resultKind = LookupResultKind.Empty; } this.MethodGroup = methodGroup; this.constantValue = constantValue; }
internal CSharpTypeInfo(TypeSymbol type, TypeSymbol convertedType, Conversion implicitConversion) { // When constructing the result for the Caas API, we expose the underlying symbols that // may have been hidden under error type, if the error type was immediate. We will // expose error types that were constructed, or type parameters of constructed types. this.Type = type.GetNonErrorGuess() ?? type; this.ConvertedType = convertedType.GetNonErrorGuess() ?? convertedType; this.ImplicitConversion = implicitConversion; }
internal SemanticInfo( TypeSymbol type, Conversion conversion, TypeSymbol convertedType, ReadOnlyArray<Symbol> symbols, LookupResultKind resultKind, ReadOnlyArray<MethodSymbol> methodGroup, ConstantValue constantValue) { // When constructing the result for the Caas API, we expose the underlying symbols that // may have been hidden under error type, if the error type was immediate. We will // expose error types that were constructed, or type parameters of constructed types. this.Type = type.GetNonErrorGuess() ?? type; this.ConvertedType = convertedType.GetNonErrorGuess() ?? convertedType; this.ImplicitConversion = conversion; this.symbols = symbols; this.resultKind = resultKind; if (!symbols.Any()) { this.resultKind = LookupResultKind.Empty; } this.MethodGroup = methodGroup; this.constantValue = constantValue; }