Beispiel #1
0
        /// <summary>
        /// Create an instance setting <see cref="IsNullable"/> lazily from
        /// <see cref="NonNullTypesContext"/> and <see cref="IsAnnotated"/>.
        /// </summary>
        /// <remarks>
        /// Should be used for scenarios where calculating <see cref="IsNullable"/> eagerly
        /// may result in cycles (when binding member declarations for instance).
        /// </remarks>
        internal static TypeSymbolWithAnnotations Create(INonNullTypesContext nonNullTypesContext, TypeSymbol typeSymbol, bool isAnnotated = false, ImmutableArray <CustomModifier> customModifiers = default)
        {
            Debug.Assert(nonNullTypesContext != null);
            Debug.Assert((nonNullTypesContext as Symbol)?.IsDefinition != false);

            if (typeSymbol is null)
            {
                return(default);
Beispiel #2
0
        internal ImmutableArray <TypeSymbolWithAnnotations> GetTypeParametersAsTypeArguments()
        {
            // Resolving [NonNullTypes] only makes sense within the definition of the generic type or method.
            // If this is a substituted symbol, we use a dummy NonNullTypes context.
            var definition = OriginalDefinition;
            INonNullTypesContext nonNullTypesContext = (object)this == definition ? definition : NonNullTypesFalseContext.Instance;

            return(GetTypeParametersAsTypeArguments(nonNullTypesContext));
        }
Beispiel #3
0
 private TypeSymbolWithAnnotations(TypeSymbol defaultType, INonNullTypesContext nonNullTypesContext, bool isAnnotated, bool treatPossiblyNullableReferenceTypeTypeParameterAsNullable, Extensions extensions)
 {
     Debug.Assert((object)defaultType != null);
     Debug.Assert(!defaultType.IsNullableType() || isAnnotated);
     Debug.Assert(nonNullTypesContext != null);
     Debug.Assert(extensions != null);
     _defaultType = defaultType;
     IsAnnotated  = isAnnotated;
     _treatPossiblyNullableReferenceTypeTypeParameterAsNullable = treatPossiblyNullableReferenceTypeTypeParameterAsNullable;
     NonNullTypesContext = nonNullTypesContext;
     _extensions         = extensions;
 }
Beispiel #4
0
        internal TypeMap WithConcatAlphaRename(
            MethodSymbol oldOwner,
            Symbol newOwner,
            INonNullTypesContext nonNullTypesContext,
            out ImmutableArray <TypeParameterSymbol> newTypeParameters,
            out ImmutableArray <TypeParameterSymbol> oldTypeParameters,
            MethodSymbol stopAt = null)
        {
            Debug.Assert(oldOwner.ConstructedFrom == oldOwner);
            Debug.Assert(stopAt == null || stopAt.ConstructedFrom == stopAt);

            // Build the array up backwards, then reverse it.
            // The following example goes through the do-loop in order M3, M2, M1
            // but the type parameters have to be <T1, T2, T3, T4>
            // void M1<T1>() {
            //   void M2<T2, T3>() {
            //     void M3<T4>() {
            //     }
            //   }
            // }
            // However, if stopAt is M1, then the type parameters would be <T2, T3, T4>
            // That is, stopAt's type parameters are excluded - the parameters are in the range (stopAt, oldOwner]
            // A null stopAt means "include everything"
            var parameters = ArrayBuilder <TypeParameterSymbol> .GetInstance();

            while (oldOwner != null && oldOwner != stopAt)
            {
                var currentParameters = oldOwner.OriginalDefinition.TypeParameters;

                for (int i = currentParameters.Length - 1; i >= 0; i--)
                {
                    parameters.Add(currentParameters[i]);
                }

                oldOwner = oldOwner.ContainingSymbol.OriginalDefinition as MethodSymbol;
            }
            parameters.ReverseContents();

            // Ensure that if stopAt was provided, it actually was in the chain and we stopped at it.
            // If not provided, both should be null (if stopAt != null && oldOwner == null, then it wasn't in the chain).
            // Alternately, we were inside a field initializer, in which case we were to stop at the constructor,
            // but never made it that far because we encountered the field in the ContainingSymbol chain.
            Debug.Assert(
                stopAt == oldOwner ||
                stopAt?.MethodKind == MethodKind.StaticConstructor ||
                stopAt?.MethodKind == MethodKind.Constructor);

            oldTypeParameters = parameters.ToImmutableAndFree();
            return(WithAlphaRename(oldTypeParameters, newOwner, nonNullTypesContext, out newTypeParameters));
        }
Beispiel #5
0
        /// <summary>
        /// If the type reference has an associated NullableAttribute, this method
        /// returns the type transformed to have IsNullable set to true or false
        /// (but not null) for each reference type in the type.
        /// </summary>
        internal static TypeSymbolWithAnnotations TransformType(
            TypeSymbolWithAnnotations metadataType,
            EntityHandle targetSymbolToken,
            PEModuleSymbol containingModule,
            INonNullTypesContext nonNullTypesContext)
        {
            Debug.Assert(!metadataType.IsNull);

            ImmutableArray <bool> nullableTransformFlags;

            containingModule.Module.HasNullableAttribute(targetSymbolToken, out nullableTransformFlags);

            return(TransformType(metadataType, nullableTransformFlags, nonNullTypesContext));
        }
Beispiel #6
0
 // https://github.com/dotnet/roslyn/issues/29821 external annotations should be removed or fully designed/productized
 internal static TypeSymbolWithAnnotations TransformType(
     TypeSymbolWithAnnotations metadataType,
     EntityHandle targetSymbolToken,
     PEModuleSymbol containingModule,
     INonNullTypesContext nonNullTypesContext,
     ImmutableArray <bool> extraAnnotations)
 {
     if (extraAnnotations.IsDefault)
     {
         return(NullableTypeDecoder.TransformType(metadataType, targetSymbolToken, containingModule, nonNullTypesContext));
     }
     else
     {
         return(NullableTypeDecoder.TransformType(metadataType, extraAnnotations, NonNullTypesTrueContext.Instance));
     }
 }
Beispiel #7
0
 internal static NamespaceOrTypeOrAliasSymbolWithAnnotations CreateUnannotated(INonNullTypesContext nonNullTypesContext, Symbol symbol)
 {
     if (symbol is null)
     {
         return(default);
Beispiel #8
0
        internal override bool ApplyNullableTransforms(ImmutableArray <bool> transforms, INonNullTypesContext nonNullTypesContext, ref int position, out TypeSymbol result)
        {
            TypeSymbolWithAnnotations oldElementType = ElementType;
            TypeSymbolWithAnnotations newElementType;

            if (!oldElementType.ApplyNullableTransforms(transforms, nonNullTypesContext, ref position, out newElementType))
            {
                result = this;
                return(false);
            }

            result = WithElementType(newElementType);
            return(true);
        }
        /// <param name="sourceType">Type that already has custom modifiers.</param>
        /// <param name="destinationType">Same as <paramref name="sourceType"/>, but without custom modifiers.  May differ in object/dynamic.</param>
        /// <param name="containingAssembly">The assembly containing the signature referring to the destination type.</param>
        /// <param name="nonNullTypesContext">The NonNullTypes context at the destination.</param>
        /// <returns><paramref name="destinationType"/> with custom modifiers copied from <paramref name="sourceType"/>.</returns>
        internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSymbol destinationType, AssemblySymbol containingAssembly, INonNullTypesContext nonNullTypesContext)
        {
            Debug.Assert(sourceType.Equals(destinationType, TypeCompareKind.AllIgnoreOptions));
            Debug.Assert(nonNullTypesContext != null);

            const RefKind refKind = RefKind.None;

            // NOTE: overrides can differ by object/dynamic.  If they do, we'll need to tweak newType before
            // we can use it in place of this.Type.  We do so by computing the dynamic transform flags that
            // code gen uses and then passing them to the dynamic type decoder that metadata reading uses.
            // NOTE: ref is irrelevant here since we are just encoding/decoding the type out of the signature context
            ImmutableArray <bool> flags           = CSharpCompilation.DynamicTransformsEncoder.EncodeWithoutCustomModifierFlags(destinationType, refKind);
            TypeSymbol            typeWithDynamic = DynamicTypeDecoder.TransformTypeWithoutCustomModifierFlags(sourceType, containingAssembly, refKind, flags);

            TypeSymbol resultType;

            if (destinationType.ContainsTuple() && !sourceType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds | TypeCompareKind.IgnoreDynamic))
            {
                // We also preserve tuple names, if present and different
                ImmutableArray <string> names = CSharpCompilation.TupleNamesEncoder.Encode(destinationType);
                resultType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeWithDynamic, names);
            }
            else
            {
                resultType = typeWithDynamic;
            }

            // Preserve nullable modifiers as well.
            // https://github.com/dotnet/roslyn/issues/30077: Is it reasonable to copy annotations from the source?
            // If the destination had some of those annotations but not all, then clearly the destination
            // was incorrect. Or if the destination is C#7, then the destination will advertise annotations
            // that the author did not write and did not validate.
            var flagsBuilder = ArrayBuilder <bool> .GetInstance();

            destinationType.AddNullableTransforms(flagsBuilder);
            int  position        = 0;
            int  length          = flagsBuilder.Count;
            bool transformResult = resultType.ApplyNullableTransforms(flagsBuilder.ToImmutableAndFree(), nonNullTypesContext, ref position, out resultType);

            Debug.Assert(transformResult && position == length);

            Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames)); // Same custom modifiers as source type.
            // Note: We would want to check nullability, but that would pull on NonNullTypes too early (ie. cause cycles).
            Debug.Assert(resultType.Equals(destinationType,
                                           TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic and tuple names as destination type.

            return(resultType);
        }
Beispiel #10
0
        private TypeMap WithAlphaRename(ImmutableArray <TypeParameterSymbol> oldTypeParameters, Symbol newOwner, INonNullTypesContext nonNullTypesContext, out ImmutableArray <TypeParameterSymbol> newTypeParameters)
        {
            if (oldTypeParameters.Length == 0)
            {
                newTypeParameters = ImmutableArray <TypeParameterSymbol> .Empty;
                return(this);
            }

            // Note: the below assertion doesn't hold while rewriting async lambdas defined inside generic methods.
            // The async rewriter adds a synthesized struct inside the lambda frame and construct a typemap from
            // the lambda frame's substituted type parameters.
            // Debug.Assert(!oldTypeParameters.Any(tp => tp is SubstitutedTypeParameterSymbol));

            // warning: we expose result to the SubstitutedTypeParameterSymbol constructor, below, even before it's all filled in.
            TypeMap result = new TypeMap(this.Mapping);
            ArrayBuilder <TypeParameterSymbol> newTypeParametersBuilder = ArrayBuilder <TypeParameterSymbol> .GetInstance();

            // The case where it is "synthesized" is when we're creating type parameters for a synthesized (generic)
            // class or method for a lambda appearing in a generic method.
            bool synthesized = !ReferenceEquals(oldTypeParameters[0].ContainingSymbol.OriginalDefinition, newOwner.OriginalDefinition);

            int ordinal = 0;

            foreach (var tp in oldTypeParameters)
            {
                var newTp = synthesized ?
                            new SynthesizedSubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal) :
                            new SubstitutedTypeParameterSymbol(newOwner, result, tp, ordinal);
                result.Mapping.Add(tp, TypeSymbolWithAnnotations.Create(nonNullTypesContext, newTp));
                newTypeParametersBuilder.Add(newTp);
                ordinal++;
            }

            newTypeParameters = newTypeParametersBuilder.ToImmutableAndFree();
            return(result);
        }
Beispiel #11
0
 internal override bool ApplyNullableTransforms(ImmutableArray <bool> transforms, INonNullTypesContext nonNullTypesContext, ref int position, out TypeSymbol result)
 {
     result = this;
     return(true);
 }
Beispiel #12
0
 internal static ImmutableArray <TypeSymbolWithAnnotations> TypeParametersAsTypeSymbolsWithAnnotations(INonNullTypesContext nonNullTypesContext, ImmutableArray <TypeParameterSymbol> typeParameters)
 {
     return(typeParameters.SelectAsArray((tp, c) =>
                                         TypeSymbolWithAnnotations.Create(nonNullTypesContext: c, tp, isAnnotated: false, customModifiers: ImmutableArray <CustomModifier> .Empty),
                                         nonNullTypesContext));
 }
Beispiel #13
0
 // Only when the caller passes allowAlpha=true do we tolerate substituted (alpha-renamed) type parameters as keys
 internal TypeMap(INonNullTypesContext nonNullTypesContext, ImmutableArray <TypeParameterSymbol> from, ImmutableArray <TypeParameterSymbol> to, bool allowAlpha = false)
     : this(from, TypeParametersAsTypeSymbolsWithAnnotations(nonNullTypesContext, to), allowAlpha)
 {
     // mapping contents are read-only hereafter
 }
Beispiel #14
0
 internal TypeMap WithAlphaRename(MethodSymbol oldOwner, Symbol newOwner, INonNullTypesContext nonNullTypesContext, out ImmutableArray <TypeParameterSymbol> newTypeParameters)
 {
     Debug.Assert(oldOwner.ConstructedFrom == oldOwner);
     return(WithAlphaRename(oldOwner.OriginalDefinition.TypeParameters, newOwner, nonNullTypesContext, out newTypeParameters));
 }
Beispiel #15
0
        internal override bool ApplyNullableTransforms(ImmutableArray <bool> transforms, INonNullTypesContext nonNullTypesContext, ref int position, out TypeSymbol result)
        {
            TypeSymbolWithAnnotations oldElementType = ElementType;
            TypeSymbolWithAnnotations newElementType;

            if (!oldElementType.ApplyNullableTransforms(transforms, nonNullTypesContext, ref position, out newElementType))
            {
                result = this;
                return(false);
            }

            if (oldElementType.IsSameAs(newElementType))
            {
                result = this;
            }
            else
            {
                result = IsSZArray ?
                         ArrayTypeSymbol.CreateSZArray(newElementType, _baseType) :
                         ArrayTypeSymbol.CreateMDArray(newElementType, Rank, Sizes, LowerBounds, _baseType);
            }

            return(true);
        }
Beispiel #16
0
 internal ImmutableArray <TypeSymbolWithAnnotations> GetTypeParametersAsTypeArguments(INonNullTypesContext nonNullTypesContext) =>
 TypeMap.TypeParametersAsTypeSymbolsWithAnnotations(nonNullTypesContext, TypeParameters);
Beispiel #17
0
        internal override bool ApplyNullableTransforms(ImmutableArray <bool> transforms, INonNullTypesContext nonNullTypesContext, ref int position, out TypeSymbol result)
        {
            TypeSymbolWithAnnotations oldPointedAtType = PointedAtType;
            TypeSymbolWithAnnotations newPointedAtType;

            if (!oldPointedAtType.ApplyNullableTransforms(transforms, nonNullTypesContext, ref position, out newPointedAtType))
            {
                result = this;
                return(false);
            }

            if (oldPointedAtType.IsSameAs(newPointedAtType))
            {
                result = this;
            }
            else
            {
                result = new PointerTypeSymbol(newPointedAtType);
            }

            return(true);
        }
Beispiel #18
0
        internal static TypeSymbolWithAnnotations TransformType(TypeSymbolWithAnnotations metadataType, ImmutableArray <bool> nullableTransformFlags, INonNullTypesContext nonNullTypesContext)
        {
            int position = 0;
            TypeSymbolWithAnnotations result;

            if (metadataType.ApplyNullableTransforms(nullableTransformFlags, nonNullTypesContext, ref position, out result) &&
                (nullableTransformFlags.IsDefault || position == nullableTransformFlags.Length))
            {
                return(result);
            }

            // No NullableAttribute applied to the target symbol, or flags do not line-up, return unchanged metadataType.
            return(metadataType);
        }
Beispiel #19
0
 internal LazyMissingNonNullTypesContextForSuppressionDiagnosticInfo(INonNullTypesContext context)
 {
     _context = context;
 }
Beispiel #20
0
        private static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, INonNullTypesContext nonNullTypesContext)
        {
            var featureID = MessageID.IDS_FeatureNullableReferenceTypes;

            if (!compilation.IsFeatureEnabled(featureID))
            {
                LanguageVersion availableVersion = compilation.LanguageVersion;
                LanguageVersion requiredVersion  = featureID.RequiredVersion();

                return(new CSDiagnosticInfo(availableVersion.GetErrorCode(), featureID.Localize(), new CSharpRequiredLanguageVersion(requiredVersion)));
            }
            else if (nonNullTypesContext.NonNullTypes != true)
            {
                return(new CSDiagnosticInfo(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation));
            }

            return(null);
        }
Beispiel #21
0
 /// <summary>
 /// A `?` annotation on a type that isn't a value type causes:
 /// - an error before C# 8.0
 /// - a warning outside of a NonNullTypes context
 /// </summary>
 public static DiagnosticInfo ReportNullableReferenceTypesIfNeeded(CSharpCompilation compilation, INonNullTypesContext context, TypeSymbolWithAnnotations type)
 {
     return(!type.IsNull && (type.IsValueType || type.IsErrorType()) ? null : ReportNullableReferenceTypesIfNeeded(compilation, context));
 }
Beispiel #22
0
 internal LazyMissingNonNullTypesContextDiagnosticInfo(CSharpCompilation compilation, INonNullTypesContext context, TypeSymbolWithAnnotations type)
 {
     _compilation = compilation;
     _context     = context;
     _type        = type;
 }