Skip to content

Commit

Permalink
Unify nint and IntPtr (#60913)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv authored May 18, 2022
1 parent 86f930e commit 1814273
Show file tree
Hide file tree
Showing 54 changed files with 10,604 additions and 113 deletions.
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ private void CheckDisallowedAttributeDependentType(TypeWithAnnotations typeArgum
var type = typeWithAnnotations.Type;
if (type.IsDynamic()
|| (typeWithAnnotations.NullableAnnotation.IsAnnotated() && !type.IsValueType)
|| type.IsNativeIntegerType
|| type.IsNativeIntegerWrapperType
|| (type.IsTupleType && !type.TupleElementNames.IsDefault))
{
diagnostics.Add(ErrorCode.ERR_AttrDependentTypeNotAllowed, errorLocation, topLevelType.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat));
Expand Down
8 changes: 7 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ private UnaryOperatorAnalysisResult UnaryOperatorOverloadResolution(

if (kind == UnaryOperatorKind.UnaryMinus &&
(object)operand.Type != null &&
(operand.Type.SpecialType == SpecialType.System_UInt64 || (operand.Type.SpecialType == SpecialType.System_UIntPtr && operand.Type.IsNativeIntegerType)))
(operand.Type.SpecialType == SpecialType.System_UInt64 || isNuint(operand.Type)))
{
resultKind = LookupResultKind.OverloadResolutionFailure;
}
Expand Down Expand Up @@ -1422,6 +1422,12 @@ private UnaryOperatorAnalysisResult UnaryOperatorOverloadResolution(

result.Free();
return possiblyBest;

static bool isNuint(TypeSymbol type)
{
return type.SpecialType == SpecialType.System_UIntPtr
&& type.IsNativeIntegerType;
}
}

private static object FoldDecimalBinaryOperators(BinaryOperatorKind kind, ConstantValue valueLeft, ConstantValue valueRight)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ private void GetAllBuiltInOperators(BinaryOperatorKind kind, bool isChecked, Bou
}
else
{
this.Compilation.builtInOperators.GetSimpleBuiltInOperators(kind, operators, skipNativeIntegerOperators: !left.Type.IsNativeIntegerOrNullableNativeIntegerType() && !right.Type.IsNativeIntegerOrNullableNativeIntegerType());
this.Compilation.builtInOperators.GetSimpleBuiltInOperators(kind, operators, skipNativeIntegerOperators: !left.Type.IsNativeIntegerOrNullableThereof() && !right.Type.IsNativeIntegerOrNullableThereof());

// SPEC 7.3.4: For predefined enum and delegate operators, the only operators
// considered are those defined by an enum or delegate type that is the binding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ private void GetAllBuiltInOperators(UnaryOperatorKind kind, bool isChecked, Boun
// specification to match the previous implementation.

var operators = ArrayBuilder<UnaryOperatorSignature>.GetInstance();
this.Compilation.builtInOperators.GetSimpleBuiltInOperators(kind, operators, skipNativeIntegerOperators: !operand.Type.IsNativeIntegerOrNullableNativeIntegerType());
this.Compilation.builtInOperators.GetSimpleBuiltInOperators(kind, operators, skipNativeIntegerOperators: !operand.Type.IsNativeIntegerOrNullableThereof());

GetEnumOperations(kind, operand, operators);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3033,7 +3033,7 @@ private static bool IsSignedIntegralType(TypeSymbol type)
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_IntPtr:
case SpecialType.System_IntPtr when type.IsNativeIntegerType:
return true;

default:
Expand All @@ -3054,7 +3054,7 @@ private static bool IsUnsignedIntegralType(TypeSymbol type)
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_UIntPtr:
case SpecialType.System_UIntPtr when type.IsNativeIntegerType:
return true;

default:
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ private BoundLambda ReallyBind(NamedTypeSymbol delegateType, bool inExpressionTr

if (returnType.HasType)
{
if (returnType.Type.ContainsNativeInteger())
if (compilation.ShouldEmitNativeIntegerAttributes(returnType.Type))
{
compilation.EnsureNativeIntegerAttributeExists(diagnostics, lambdaSymbol.DiagnosticLocation, modifyCompilation: false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3998,6 +3998,11 @@ internal bool EmitNullablePublicOnly
}
}

internal bool ShouldEmitNativeIntegerAttributes()
{
return !Assembly.RuntimeSupportsNumericIntPtr;
}

internal bool ShouldEmitNullableAttributes(Symbol symbol)
{
RoslynDebug.Assert(symbol is object);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;

namespace Microsoft.CodeAnalysis.CSharp
{
Expand All @@ -17,5 +18,10 @@ internal static bool IsFeatureEnabled(this SyntaxNode? syntax, MessageID feature
{
return ((CSharpParseOptions?)syntax?.SyntaxTree.Options)?.IsFeatureEnabled(feature) == true;
}

internal static bool ShouldEmitNativeIntegerAttributes(this CSharpCompilation compilation, TypeSymbol type)
{
return compilation.ShouldEmitNativeIntegerAttributes() && type.ContainsNativeIntegerWrapperType();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ private void CreateEmbeddedAttributesIfNeeded(BindingDiagnosticBag diagnostics)

if ((needsAttributes & EmbeddableAttributes.NativeIntegerAttribute) != 0)
{
Debug.Assert(Compilation.ShouldEmitNativeIntegerAttributes());
CreateAttributeIfNeeded(
ref _lazyNativeIntegerAttribute,
diagnostics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,8 @@ internal SynthesizedAttributeData SynthesizePreserveBaseOverridesAttribute()
internal SynthesizedAttributeData SynthesizeNativeIntegerAttribute(Symbol symbol, TypeSymbol type)
{
Debug.Assert((object)type != null);
Debug.Assert(type.ContainsNativeInteger());
Debug.Assert(type.ContainsNativeIntegerWrapperType());
Debug.Assert(Compilation.ShouldEmitNativeIntegerAttributes());

if ((object)Compilation.SourceModule != symbol.ContainingModule)
{
Expand Down Expand Up @@ -1702,6 +1703,8 @@ internal SynthesizedAttributeData SynthesizeNativeIntegerAttribute(Symbol symbol

internal virtual SynthesizedAttributeData SynthesizeNativeIntegerAttribute(WellKnownMember member, ImmutableArray<TypedConstant> arguments)
{
Debug.Assert(Compilation.ShouldEmitNativeIntegerAttributes());

// For modules, this attribute should be present. Only assemblies generate and embed this type.
// https://github.com/dotnet/roslyn/issues/30062 Should not be optional.
return Compilation.TrySynthesizeAttribute(member, arguments, isOptionalUse: true);
Expand Down Expand Up @@ -1776,6 +1779,7 @@ internal void EnsureNullableContextAttributeExists()

internal void EnsureNativeIntegerAttributeExists()
{
Debug.Assert(Compilation.ShouldEmitNativeIntegerAttributes());
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,15 @@ private void EnsureAttributesExist(TypeCompilationState compilationState)

ParameterHelpers.EnsureIsReadOnlyAttributeExists(moduleBuilder, Parameters);

if (ReturnType.ContainsNativeInteger())
if (moduleBuilder.Compilation.ShouldEmitNativeIntegerAttributes())
{
moduleBuilder.EnsureNativeIntegerAttributeExists();
}
if (ReturnType.ContainsNativeIntegerWrapperType())
{
moduleBuilder.EnsureNativeIntegerAttributeExists();
}

ParameterHelpers.EnsureNativeIntegerAttributeExists(moduleBuilder, Parameters);
ParameterHelpers.EnsureNativeIntegerAttributeExists(moduleBuilder, Parameters);
}

if (compilationState.Compilation.ShouldEmitNullableAttributes(this))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,13 @@ public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatemen
moduleBuilder.EnsureIsUnmanagedAttributeExists();
}

if (hasReturnTypeOrParameter(localFunction, t => t.ContainsNativeInteger()) ||
typeParameters.Any(t => t.ConstraintTypesNoUseSiteDiagnostics.Any(t => t.ContainsNativeInteger())))
if (_compilation.ShouldEmitNativeIntegerAttributes())
{
moduleBuilder.EnsureNativeIntegerAttributeExists();
if (hasReturnTypeOrParameter(localFunction, t => t.ContainsNativeIntegerWrapperType()) ||
typeParameters.Any(t => t.ConstraintTypesNoUseSiteDiagnostics.Any(t => t.ContainsNativeIntegerWrapperType())))
{
moduleBuilder.EnsureNativeIntegerAttributeExists();
}
}

if (_factory.CompilationState.Compilation.ShouldEmitNullableAttributes(localFunction))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ private BoundExpression MakeConversionNodeCore(
rewrittenType: rewrittenType);

case ConversionKind.IntPtr:
return RewriteIntPtrConversion(oldNodeOpt, syntax, rewrittenOperand, conversion, @checked,
return RewriteIntPtrConversion(syntax, rewrittenOperand, conversion, @checked,
explicitCastInCode, constantValueOpt, rewrittenType);

case ConversionKind.ImplicitNullable:
Expand Down Expand Up @@ -1288,7 +1288,6 @@ private BoundExpression RewriteLiftedUserDefinedConversion(
}

private BoundExpression RewriteIntPtrConversion(
BoundConversion? oldNode,
SyntaxNode syntax,
BoundExpression rewrittenOperand,
Conversion conversion,
Expand All @@ -1300,6 +1299,7 @@ private BoundExpression RewriteIntPtrConversion(
Debug.Assert(rewrittenOperand != null);
Debug.Assert((object)rewrittenType != null);
Debug.Assert(rewrittenOperand.Type is { });
Debug.Assert(!_compilation.Assembly.RuntimeSupportsNumericIntPtr);

TypeSymbol source = rewrittenOperand.Type;
TypeSymbol target = rewrittenType;
Expand Down Expand Up @@ -1602,6 +1602,7 @@ private Conversion TryMakeConversion(SyntaxNode syntax, Conversion conversion, T
}
case ConversionKind.IntPtr:
{
Debug.Assert(!_compilation.Assembly.RuntimeSupportsNumericIntPtr);
SpecialMember member = GetIntPtrConversionMethod(fromType, toType);
MethodSymbol method;
if (!TryGetSpecialTypeMethod(syntax, member, out method))
Expand Down
19 changes: 18 additions & 1 deletion src/Compilers/CSharp/Portable/Symbols/AssemblySymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,24 @@ internal bool RuntimeSupportsStaticAbstractMembersInInterfaces
get => RuntimeSupportsFeature(SpecialMember.System_Runtime_CompilerServices_RuntimeFeature__VirtualStaticsInInterfaces);
}

private bool RuntimeSupportsFeature(SpecialMember feature)
/// <summary>
/// Whether the target runtime supports numeric IntPtr types.
/// This test hook should be removed once TargetFramework.Net70 is added.
/// Tracked by https://github.com/dotnet/roslyn/issues/61235
/// </summary>
internal virtual bool RuntimeSupportsNumericIntPtr
{
get
{
// CorLibrary should never be null, but that invariant is broken in some cases for MissingAssemblySymbol.
// Tracked by https://github.com/dotnet/roslyn/issues/61262
return CorLibrary?.RuntimeSupportsNumericIntPtr == true;
}

set => CorLibrary.RuntimeSupportsNumericIntPtr = value;
}

protected bool RuntimeSupportsFeature(SpecialMember feature)
{
Debug.Assert((SpecialType)SpecialMembers.GetDescriptor(feature).DeclaringTypeId == SpecialType.System_Runtime_CompilerServices_RuntimeFeature);
return GetSpecialType(SpecialType.System_Runtime_CompilerServices_RuntimeFeature) is { TypeKind: TypeKind.Class, IsStatic: true } &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ internal void EnsureNullableContextAttributeExists(BindingDiagnosticBag? diagnos

internal void EnsureNativeIntegerAttributeExists(BindingDiagnosticBag? diagnostics, Location location, bool modifyCompilation)
{
Debug.Assert(ShouldEmitNativeIntegerAttributes());
EnsureEmbeddableAttributeExists(EmbeddableAttributes.NativeIntegerAttribute, diagnostics, location, modifyCompilation);
}

Expand Down Expand Up @@ -593,6 +594,7 @@ internal bool CheckIfAttributeShouldBeEmbedded(EmbeddableAttributes attribute, B

case EmbeddableAttributes.NativeIntegerAttribute:
// If the type exists, we'll check both constructors, regardless of which one(s) we'll eventually need.
Debug.Assert(ShouldEmitNativeIntegerAttributes());
return CheckIfAttributeShouldBeEmbedded(
diagnosticsOpt,
locationOpt,
Expand Down Expand Up @@ -983,6 +985,7 @@ internal static class NativeIntegerTransformsEncoder
{
internal static void Encode(ArrayBuilder<bool> builder, TypeSymbol type)
{
Debug.Assert(type.ContainingAssembly?.RuntimeSupportsNumericIntPtr != true);
type.VisitType((typeSymbol, builder, isNested) => AddFlags(typeSymbol, builder), builder);
}

Expand All @@ -992,7 +995,7 @@ private static bool AddFlags(TypeSymbol type, ArrayBuilder<bool> builder)
{
case SpecialType.System_IntPtr:
case SpecialType.System_UIntPtr:
builder.Add(type.IsNativeIntegerType);
builder.Add(type.IsNativeIntegerWrapperType);
break;
}
// Continue walking types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,15 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
{
internal struct NativeIntegerTypeDecoder
{
internal static TypeSymbol TransformType(TypeSymbol type, EntityHandle handle, PEModuleSymbol containingModule)
internal static TypeSymbol TransformType(TypeSymbol type, EntityHandle handle, PEModuleSymbol containingModule, TypeSymbol? containingType)
{
// Note: We avoid any cycles when loading members of System.Runtime.CompilerServices.RuntimeFeature
if (containingType?.SpecialType == SpecialType.System_Runtime_CompilerServices_RuntimeFeature
|| type.ContainingAssembly?.RuntimeSupportsNumericIntPtr == true)
{
return type;
}

return containingModule.Module.HasNativeIntegerAttribute(handle, out var transformFlags) ?
TransformType(type, transformFlags) :
type;
Expand Down Expand Up @@ -111,7 +118,7 @@ private NativeIntegerTypeDecoder(ImmutableArray<bool> transformFlags)
{
throw new UnsupportedSignatureContent();
}
return (_transformFlags[_index++], type.IsNativeIntegerType) switch
return (_transformFlags[_index++], type.IsNativeIntegerWrapperType) switch
{
(false, true) => type.NativeIntegerUnderlyingType,
(true, false) => type.AsNativeInteger(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ internal PEEventSymbol(

const int targetSymbolCustomModifierCount = 0;
var typeSymbol = DynamicTypeDecoder.TransformType(originalEventType, targetSymbolCustomModifierCount, handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol, _containingType);

// We start without annotation (they will be decoded below)
var type = TypeWithAnnotations.Create(typeSymbol);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ private void EnsureSignatureIsLoaded()
ImmutableArray<CustomModifier> customModifiersArray = CSharpCustomModifier.Convert(customModifiers);

typeSymbol = DynamicTypeDecoder.TransformType(typeSymbol, customModifiersArray.Length, _handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, _handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, _handle, moduleSymbol, _containingType);

// We start without annotations
var type = TypeWithAnnotations.Create(typeSymbol, customModifiers: customModifiersArray);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ private NamedTypeSymbol GetDeclaredBaseType(bool skipTransformsIfNecessary)

var moduleSymbol = ContainingPEModule;
TypeSymbol decodedType = DynamicTypeDecoder.TransformType(baseType, 0, _handle, moduleSymbol);
decodedType = NativeIntegerTypeDecoder.TransformType(decodedType, _handle, moduleSymbol);
decodedType = NativeIntegerTypeDecoder.TransformType(decodedType, _handle, moduleSymbol, this);
decodedType = TupleTypeDecoder.DecodeTupleTypesIfApplicable(decodedType, _handle, moduleSymbol);
baseType = (NamedTypeSymbol)NullableTypeDecoder.TransformType(TypeWithAnnotations.Create(decodedType), _handle, moduleSymbol, accessSymbol: this, nullableContext: this).Type;
}
Expand Down Expand Up @@ -539,7 +539,7 @@ private ImmutableArray<NamedTypeSymbol> MakeDeclaredInterfaces()
EntityHandle interfaceHandle = moduleSymbol.Module.MetadataReader.GetInterfaceImplementation(interfaceImpl).Interface;
TypeSymbol typeSymbol = tokenDecoder.GetTypeOfToken(interfaceHandle);

typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, interfaceImpl, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, interfaceImpl, moduleSymbol, ContainingType);
typeSymbol = TupleTypeDecoder.DecodeTupleTypesIfApplicable(typeSymbol, interfaceImpl, moduleSymbol);
typeSymbol = NullableTypeDecoder.TransformType(TypeWithAnnotations.Create(typeSymbol), interfaceImpl, moduleSymbol, accessSymbol: this, nullableContext: this).Type;

Expand Down Expand Up @@ -2376,6 +2376,10 @@ internal override int MetadataArity
internal override NamedTypeSymbol AsNativeInteger()
{
Debug.Assert(this.SpecialType == SpecialType.System_IntPtr || this.SpecialType == SpecialType.System_UIntPtr);
if (ContainingAssembly.RuntimeSupportsNumericIntPtr)
{
return this;
}

return ContainingAssembly.GetNativeIntegerType(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private PEParameterSymbol(
}

var typeSymbol = DynamicTypeDecoder.TransformType(typeWithAnnotations.Type, countOfCustomModifiers, handle, moduleSymbol, refKind);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol);
typeSymbol = NativeIntegerTypeDecoder.TransformType(typeSymbol, handle, moduleSymbol, containingSymbol.ContainingType);
typeWithAnnotations = typeWithAnnotations.WithTypeAndModifiers(typeSymbol, typeWithAnnotations.CustomModifiers);
// Decode nullable before tuple types to avoid converting between
// NamedTypeSymbol and TupleTypeSymbol unnecessarily.
Expand Down
Loading

0 comments on commit 1814273

Please sign in to comment.