未验证 提交 ea14f717 编写于 作者: C Charles Stoner 提交者: GitHub

Address various PROTOTYPE comments for native integers (#42360)

上级 e0c190bd
......@@ -1404,29 +1404,40 @@ private BoundExpression BindDefaultExpression(DefaultExpressionSyntax node, Diag
}
else
{
if (node.IsKind(SyntaxKind.IdentifierName) && FallBackOnDiscard((IdentifierNameSyntax)node, diagnostics))
expression = null;
if (node is IdentifierNameSyntax identifier)
{
lookupResult.Free();
return new BoundDiscardExpression(node, type: null);
var type = BindNativeIntegerSymbolIfAny(identifier, diagnostics);
if (type is { })
{
expression = new BoundTypeExpression(node, null, type);
}
else if (FallBackOnDiscard(identifier, diagnostics))
{
expression = new BoundDiscardExpression(node, type: null);
}
}
// Otherwise, the simple-name is undefined and a compile-time error occurs.
expression = BadExpression(node);
if (lookupResult.Error != null)
{
Error(diagnostics, lookupResult.Error, node);
}
else if (IsJoinRangeVariableInLeftKey(node))
{
Error(diagnostics, ErrorCode.ERR_QueryOuterKey, node, name);
}
else if (IsInJoinRightKey(node))
{
Error(diagnostics, ErrorCode.ERR_QueryInnerKey, node, name);
}
else
if (expression is null)
{
Error(diagnostics, ErrorCode.ERR_NameNotInContext, node, name);
expression = BadExpression(node);
if (lookupResult.Error != null)
{
Error(diagnostics, lookupResult.Error, node);
}
else if (IsJoinRangeVariableInLeftKey(node))
{
Error(diagnostics, ErrorCode.ERR_QueryOuterKey, node, name);
}
else if (IsInJoinRightKey(node))
{
Error(diagnostics, ErrorCode.ERR_QueryInnerKey, node, name);
}
else
{
Error(diagnostics, ErrorCode.ERR_NameNotInContext, node, name);
}
}
}
......
......@@ -819,26 +819,21 @@ private static bool IsViableType(LookupResult result)
if ((object)qualifierOpt == null &&
!IsViableType(result))
{
switch (node.Identifier.ValueText)
if (node.Identifier.ValueText == "dynamic")
{
case "dynamic":
if ((node.Parent == null ||
node.Parent.Kind() != SyntaxKind.Attribute && // dynamic not allowed as attribute type
SyntaxFacts.IsInTypeOnlyContext(node)) &&
Compilation.LanguageVersion >= MessageID.IDS_FeatureDynamic.RequiredVersion())
{
bindingResult = Compilation.DynamicType;
ReportUseSiteDiagnosticForDynamic(diagnostics, node);
}
break;
case "nint":
bindingResult = getNativeIntType(node, unsigned: false, diagnostics);
break;
case "nuint":
bindingResult = getNativeIntType(node, unsigned: true, diagnostics);
break;
default:
break;
if ((node.Parent == null ||
node.Parent.Kind() != SyntaxKind.Attribute && // dynamic not allowed as attribute type
SyntaxFacts.IsInTypeOnlyContext(node)) &&
Compilation.LanguageVersion >= MessageID.IDS_FeatureDynamic.RequiredVersion())
{
bindingResult = Compilation.DynamicType;
ReportUseSiteDiagnosticForDynamic(diagnostics, node);
}
}
else
{
bindingResult = BindNativeIntegerSymbolIfAny(node, diagnostics);
}
}
......@@ -859,12 +854,28 @@ private static bool IsViableType(LookupResult result)
result.Free();
return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(AreNullableAnnotationsEnabled(node.Identifier), bindingResult);
}
NamedTypeSymbol getNativeIntType(SyntaxNode node, bool unsigned, DiagnosticBag diagnostics)
/// <summary>
/// If the node is "nint" or "nuint", return the corresponding native integer symbol.
/// Otherwise return null.
/// </summary>
private NamedTypeSymbol BindNativeIntegerSymbolIfAny(IdentifierNameSyntax node, DiagnosticBag diagnostics)
{
SpecialType specialType;
switch (node.Identifier.Text)
{
CheckFeatureAvailability(node, MessageID.IDS_FeatureNativeInt, diagnostics);
return this.GetSpecialType(unsigned ? SpecialType.System_UIntPtr : SpecialType.System_IntPtr, diagnostics, node).AsNativeInteger();
case "nint":
specialType = SpecialType.System_IntPtr;
break;
case "nuint":
specialType = SpecialType.System_UIntPtr;
break;
default:
return null;
}
CheckFeatureAvailability(node, MessageID.IDS_FeatureNativeInt, diagnostics);
return this.GetSpecialType(specialType, diagnostics, node).AsNativeInteger();
}
private void ReportUseSiteDiagnosticForDynamic(DiagnosticBag diagnostics, IdentifierNameSyntax node)
......
......@@ -316,6 +316,10 @@ private BoundExpression MakeEqual(BoundExpression loweredLiteral, BoundExpressio
return _localRewriter.MakeBinaryOperator(_factory.Syntax, BinaryOperatorKind.UIntEqual, input, loweredLiteral, booleanType, method: null);
case SpecialType.System_UInt64:
return _localRewriter.MakeBinaryOperator(_factory.Syntax, BinaryOperatorKind.ULongEqual, input, loweredLiteral, booleanType, method: null);
case SpecialType.System_IntPtr when loweredLiteral.Type.IsNativeIntegerType:
return _localRewriter.MakeBinaryOperator(_factory.Syntax, BinaryOperatorKind.NIntEqual, input, loweredLiteral, booleanType, method: null);
case SpecialType.System_UIntPtr when loweredLiteral.Type.IsNativeIntegerType:
return _localRewriter.MakeBinaryOperator(_factory.Syntax, BinaryOperatorKind.NUIntEqual, input, loweredLiteral, booleanType, method: null);
default:
if (loweredLiteral.Type.IsEnumType())
{
......
......@@ -182,7 +182,8 @@ private void VisitNamedTypeWithoutNullability(INamedTypeSymbol symbol)
return;
}
if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.UseSpecialTypes))
if (format.MiscellaneousOptions.IncludesOption(SymbolDisplayMiscellaneousOptions.UseSpecialTypes) ||
(symbol.IsNativeIntegerType && !format.CompilerInternalOptions.IncludesOption(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType)))
{
if (AddSpecialTypeKeyword(symbol))
{
......
......@@ -15,13 +15,15 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols
// PROTOTYPE: Handle retargeting these types.
internal sealed class NativeIntegerTypeSymbol : WrappedNamedTypeSymbol, Cci.IReference
{
internal NativeIntegerTypeSymbol(NamedTypeSymbol underlying) : base(underlying, tupleData: null)
private ImmutableArray<NamedTypeSymbol> _lazyInterfaces;
internal NativeIntegerTypeSymbol(NamedTypeSymbol underlyingType) : base(underlyingType, tupleData: null)
{
Debug.Assert(underlying.TupleData is null);
Debug.Assert(!underlying.IsNativeIntegerType);
Debug.Assert(underlying.SpecialType == SpecialType.System_IntPtr || underlying.SpecialType == SpecialType.System_UIntPtr);
Debug.Assert(this.Equals(underlying));
Debug.Assert(underlying.Equals(this));
Debug.Assert(underlyingType.TupleData is null);
Debug.Assert(!underlyingType.IsNativeIntegerType);
Debug.Assert(underlyingType.SpecialType == SpecialType.System_IntPtr || underlyingType.SpecialType == SpecialType.System_UIntPtr);
Debug.Assert(this.Equals(underlyingType));
Debug.Assert(underlyingType.Equals(this));
}
public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;
......@@ -63,7 +65,7 @@ internal NativeIntegerTypeSymbol(NamedTypeSymbol underlying) : base(underlying,
internal override NamedTypeSymbol GetDeclaredBaseType(ConsList<TypeSymbol> basesBeingResolved) => _underlyingType.GetDeclaredBaseType(basesBeingResolved);
internal override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList<TypeSymbol> basesBeingResolved) => _underlyingType.GetDeclaredInterfaces(basesBeingResolved);
internal override ImmutableArray<NamedTypeSymbol> GetDeclaredInterfaces(ConsList<TypeSymbol> basesBeingResolved) => GetInterfaces(basesBeingResolved);
internal override ImmutableArray<Symbol> GetEarlyAttributeDecodingMembers() => throw ExceptionUtilities.Unreachable;
......@@ -73,9 +75,7 @@ internal NativeIntegerTypeSymbol(NamedTypeSymbol underlying) : base(underlying,
internal override ImmutableArray<NamedTypeSymbol> GetInterfacesToEmit() => throw ExceptionUtilities.Unreachable;
// PROTOTYPE: Include certain interfaces defined on the underlying type, with substitution
// of [U]IntPtr (for instance, IEquatable<nint> rather than IEquatable<IntPtr>).
internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<TypeSymbol>? basesBeingResolved = null) => ImmutableArray<NamedTypeSymbol>.Empty;
internal override ImmutableArray<NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(ConsList<TypeSymbol>? basesBeingResolved = null) => GetInterfaces(basesBeingResolved);
protected override NamedTypeSymbol WithTupleDataCore(TupleExtraData newData) => throw ExceptionUtilities.Unreachable;
......@@ -101,5 +101,41 @@ void Cci.IReference.Dispatch(Cci.MetadataVisitor visitor)
// NativeIntegerTypeSymbol should not be used in emit.
throw ExceptionUtilities.Unreachable;
}
private ImmutableArray<NamedTypeSymbol> GetInterfaces(ConsList<TypeSymbol>? basesBeingResolved)
{
if (_lazyInterfaces.IsDefault)
{
ImmutableInterlocked.InterlockedCompareExchange(ref _lazyInterfaces, makeInterfaces(_underlyingType.InterfacesNoUseSiteDiagnostics(basesBeingResolved)), default(ImmutableArray<NamedTypeSymbol>));
}
return _lazyInterfaces;
// Return IEquatable<n[u]int> if the underlying type implemented IEquatable<System.[U]IntPtr>.
ImmutableArray<NamedTypeSymbol> makeInterfaces(ImmutableArray<NamedTypeSymbol> underlyingInterfaces)
{
Debug.Assert(_underlyingType.SpecialType == SpecialType.System_IntPtr || _underlyingType.SpecialType == SpecialType.System_UIntPtr);
foreach (var underlyingInterface in underlyingInterfaces)
{
// Is the underlying interface IEquatable<System.[U]IntPtr>?
if (underlyingInterface.Name != "IEquatable")
{
continue;
}
var typeArgs = underlyingInterface.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics;
if (typeArgs.Length == 1 && _underlyingType.SpecialType == typeArgs[0].Type.SpecialType)
{
var def = underlyingInterface.OriginalDefinition;
if (def.ContainingSymbol is NamespaceSymbol { Name: "System", ContainingSymbol: NamespaceSymbol { IsGlobalNamespace: true } })
{
// Return IEquatable<n[u]int>.
return ImmutableArray.Create(def.Construct(ImmutableArray.Create(TypeWithAnnotations.Create(this))));
}
}
}
return ImmutableArray<NamedTypeSymbol>.Empty;
}
}
}
}
......@@ -27,20 +27,6 @@ public static bool IsIntegralType(this SpecialType specialType)
}
}
public static bool IsSignedIntegralType(this SpecialType specialType)
{
switch (specialType)
{
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
return true;
default:
return false;
}
}
public static bool CanBeConst(this SpecialType specialType)
{
switch (specialType)
......@@ -65,34 +51,6 @@ public static bool CanBeConst(this SpecialType specialType)
}
}
/// <summary>
/// The type is one of the simple types defined in Dev10 C#, see "predeftype.h"/simple
/// </summary>
public static bool IsIntrinsicType(this SpecialType specialType)
{
switch (specialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_Char:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_Single:
case SpecialType.System_Double:
// NOTE: VB treats System.DateTime as an intrinsic, while C# does not, see "predeftype.h"
//case SpecialType.System_DateTime:
case SpecialType.System_Decimal:
return true;
default:
return false;
}
}
public static bool IsValidVolatileFieldType(this SpecialType specialType)
{
switch (specialType)
......
......@@ -1035,7 +1035,29 @@ internal static bool IsValidV6SwitchGoverningType(this TypeSymbol type, bool isT
public static bool IsIntrinsicType(this TypeSymbol type)
{
return type.SpecialType.IsIntrinsicType();
switch (type.SpecialType)
{
case SpecialType.System_Boolean:
case SpecialType.System_Char:
case SpecialType.System_SByte:
case SpecialType.System_Int16:
case SpecialType.System_Int32:
case SpecialType.System_Int64:
case SpecialType.System_Byte:
case SpecialType.System_UInt16:
case SpecialType.System_UInt32:
case SpecialType.System_UInt64:
case SpecialType.System_IntPtr when type.IsNativeIntegerType:
case SpecialType.System_UIntPtr when type.IsNativeIntegerType:
case SpecialType.System_Single:
case SpecialType.System_Double:
// NOTE: VB treats System.DateTime as an intrinsic, while C# does not.
//case SpecialType.System_DateTime:
case SpecialType.System_Decimal:
return true;
default:
return false;
}
}
public static bool IsPartial(this TypeSymbol type)
......
......@@ -7222,15 +7222,15 @@ class B
static void F4(nint[] x, A<nuint> y) { }
}";
var comp = CreateCompilation(new[] { source }, parseOptions: TestOptions.RegularPreview);
var formatWithoutSpecialTypes = new SymbolDisplayFormat(
var formatWithoutOptions = new SymbolDisplayFormat(
memberOptions: SymbolDisplayMemberOptions.IncludeParameters | SymbolDisplayMemberOptions.IncludeType | SymbolDisplayMemberOptions.IncludeModifiers,
parameterOptions: SymbolDisplayParameterOptions.IncludeType | SymbolDisplayParameterOptions.IncludeName,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters);
var formatWithSpecialTypes = formatWithoutSpecialTypes.AddMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes);
var formatWithUnderlyingTypes = formatWithoutOptions.WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType);
var method = comp.GetMember<MethodSymbol>("B.F1");
Verify(
method.ToDisplayParts(formatWithoutSpecialTypes),
method.ToDisplayParts(formatWithUnderlyingTypes),
"static void F1(IntPtr x, UIntPtr y)",
SymbolDisplayPartKind.Keyword,
SymbolDisplayPartKind.Space,
......@@ -7248,7 +7248,7 @@ class B
SymbolDisplayPartKind.ParameterName,
SymbolDisplayPartKind.Punctuation);
Verify(
method.ToDisplayParts(formatWithSpecialTypes),
method.ToDisplayParts(formatWithoutOptions),
"static void F1(nint x, nuint y)",
SymbolDisplayPartKind.Keyword,
SymbolDisplayPartKind.Space,
......@@ -7265,29 +7265,32 @@ class B
SymbolDisplayPartKind.Space,
SymbolDisplayPartKind.ParameterName,
SymbolDisplayPartKind.Punctuation);
Verify(
method.ToDisplayParts(formatWithoutOptions.AddMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.UseSpecialTypes)),
"static void F1(nint x, nuint y)");
method = comp.GetMember<MethodSymbol>("B.F2");
Verify(
method.ToDisplayParts(formatWithoutSpecialTypes),
method.ToDisplayParts(formatWithUnderlyingTypes),
"static void F2(IntPtr x, IntPtr y)");
Verify(
method.ToDisplayParts(formatWithSpecialTypes),
method.ToDisplayParts(formatWithoutOptions),
"static void F2(nint x, IntPtr y)");
method = comp.GetMember<MethodSymbol>("B.F3");
Verify(
method.ToDisplayParts(formatWithoutSpecialTypes),
method.ToDisplayParts(formatWithUnderlyingTypes),
"static void F3(IntPtr? x, UIntPtr? y)");
Verify(
method.ToDisplayParts(formatWithSpecialTypes),
method.ToDisplayParts(formatWithoutOptions),
"static void F3(nint? x, UIntPtr? y)");
method = comp.GetMember<MethodSymbol>("B.F4");
Verify(
method.ToDisplayParts(formatWithoutSpecialTypes),
method.ToDisplayParts(formatWithUnderlyingTypes),
"static void F4(IntPtr[] x, A<UIntPtr> y)");
Verify(
method.ToDisplayParts(formatWithSpecialTypes),
method.ToDisplayParts(formatWithoutOptions),
"static void F4(nint[] x, A<nuint> y)");
}
}
......
......@@ -454,7 +454,6 @@ internal static ConstantValueTypeDiscriminator GetDiscriminator(SpecialType st)
return ConstantValueTypeDiscriminator.Bad;
}
// PROTOTYPE: Include NInt and NUint.
private static SpecialType GetSpecialType(ConstantValueTypeDiscriminator discriminator)
{
switch (discriminator)
......@@ -467,6 +466,8 @@ private static SpecialType GetSpecialType(ConstantValueTypeDiscriminator discrim
case ConstantValueTypeDiscriminator.UInt32: return SpecialType.System_UInt32;
case ConstantValueTypeDiscriminator.Int64: return SpecialType.System_Int64;
case ConstantValueTypeDiscriminator.UInt64: return SpecialType.System_UInt64;
case ConstantValueTypeDiscriminator.NInt: return SpecialType.System_IntPtr;
case ConstantValueTypeDiscriminator.NUInt: return SpecialType.System_UIntPtr;
case ConstantValueTypeDiscriminator.Char: return SpecialType.System_Char;
case ConstantValueTypeDiscriminator.Boolean: return SpecialType.System_Boolean;
case ConstantValueTypeDiscriminator.Single: return SpecialType.System_Single;
......@@ -508,7 +509,6 @@ private static SpecialType GetSpecialType(ConstantValueTypeDiscriminator discrim
}
}
// PROTOTYPE: Include NInt and NUint.
public static bool IsIntegralType(ConstantValueTypeDiscriminator discriminator)
{
switch (discriminator)
......@@ -521,6 +521,8 @@ public static bool IsIntegralType(ConstantValueTypeDiscriminator discriminator)
case ConstantValueTypeDiscriminator.UInt32:
case ConstantValueTypeDiscriminator.Int64:
case ConstantValueTypeDiscriminator.UInt64:
case ConstantValueTypeDiscriminator.NInt:
case ConstantValueTypeDiscriminator.NUInt:
return true;
default:
......@@ -536,7 +538,6 @@ public bool IsIntegral
}
}
// PROTOTYPE: Include NInt and NUint.
public bool IsNegativeNumeric
{
get
......@@ -548,6 +549,7 @@ public bool IsNegativeNumeric
case ConstantValueTypeDiscriminator.Int16:
return Int16Value < 0;
case ConstantValueTypeDiscriminator.Int32:
case ConstantValueTypeDiscriminator.NInt:
return Int32Value < 0;
case ConstantValueTypeDiscriminator.Int64:
return Int64Value < 0;
......@@ -564,7 +566,6 @@ public bool IsNegativeNumeric
}
}
// PROTOTYPE: Include NInt and NUint.
public bool IsNumeric
{
get
......@@ -582,6 +583,8 @@ public bool IsNumeric
case ConstantValueTypeDiscriminator.UInt16:
case ConstantValueTypeDiscriminator.UInt32:
case ConstantValueTypeDiscriminator.UInt64:
case ConstantValueTypeDiscriminator.NInt:
case ConstantValueTypeDiscriminator.NUInt:
return true;
default:
......@@ -590,7 +593,6 @@ public bool IsNumeric
}
}
// PROTOTYPE: Include NInt and NUint.
public static bool IsUnsignedIntegralType(ConstantValueTypeDiscriminator discriminator)
{
switch (discriminator)
......@@ -599,6 +601,7 @@ public static bool IsUnsignedIntegralType(ConstantValueTypeDiscriminator discrim
case ConstantValueTypeDiscriminator.UInt16:
case ConstantValueTypeDiscriminator.UInt32:
case ConstantValueTypeDiscriminator.UInt64:
case ConstantValueTypeDiscriminator.NUInt:
return true;
default:
......@@ -718,7 +721,6 @@ public bool IsNothing
}
}
// PROTOTYPE: Include NInt and NUint.
public void Serialize(BlobBuilder writer)
{
switch (this.Discriminator)
......
......@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis
{
......@@ -56,5 +55,10 @@ internal enum SymbolDisplayCompilerInternalOptions
/// Display `System.ValueTuple` instead of tuple syntax `(...)`.
/// </summary>
UseValueTuple = 1 << 6,
/// <summary>
/// Display `System.[U]IntPtr` instead of `n[u]int`.
/// </summary>
UseNativeIntegerUnderlyingType = 1 << 7,
}
}
......@@ -131,7 +131,8 @@ private static string GetIndentString(Symbol symbol)
SymbolDisplayMemberOptions.IncludeParameters |
SymbolDisplayMemberOptions.IncludeType |
SymbolDisplayMemberOptions.IncludeRef |
SymbolDisplayMemberOptions.IncludeExplicitInterface);
SymbolDisplayMemberOptions.IncludeExplicitInterface).
WithCompilerInternalOptions(SymbolDisplayCompilerInternalOptions.UseNativeIntegerUnderlyingType);
private void ReportContainingSymbols(Symbol symbol)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册