Skip to content

Commit

Permalink
Merge pull request #44257 from 333fred/test
Browse files Browse the repository at this point in the history
Test plan followup
  • Loading branch information
jaredpar authored May 20, 2020
2 parents 8d99b8b + b8418fb commit 64d1878
Show file tree
Hide file tree
Showing 21 changed files with 1,489 additions and 35 deletions.
1 change: 0 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ private BoundExpression BindInvocationExpression(
}
else if (boundExpression.Type?.Kind == SymbolKind.FunctionPointer)
{
// PROTOTYPE(func-ptr): Test nullable related features
ReportSuppressionIfNeeded(boundExpression, diagnostics);
result = BindFunctionPointerInvocation(node, boundExpression, analyzedArguments, diagnostics);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2966,26 +2966,28 @@ internal bool HasImplicitPointerConversion(TypeSymbol? source, TypeSymbol? desti
return false;
}

if (!hasConversion(sourceParam.RefKind, destinationSig.Parameters[i].Type, sourceSig.Parameters[i].Type, ref useSiteDiagnostics))
if (!hasConversion(sourceParam.RefKind, destinationSig.Parameters[i].TypeWithAnnotations, sourceSig.Parameters[i].TypeWithAnnotations, ref useSiteDiagnostics))
{
return false;
}
}

return sourceSig.RefKind == destinationSig.RefKind
&& hasConversion(sourceSig.RefKind, sourceSig.ReturnType, destinationSig.ReturnType, ref useSiteDiagnostics);
&& hasConversion(sourceSig.RefKind, sourceSig.ReturnTypeWithAnnotations, destinationSig.ReturnTypeWithAnnotations, ref useSiteDiagnostics);

bool hasConversion(RefKind refKind, TypeSymbol sourceType, TypeSymbol destinationType, ref HashSet<DiagnosticInfo>? useSiteDiagnostics)
bool hasConversion(RefKind refKind, TypeWithAnnotations sourceType, TypeWithAnnotations destinationType, ref HashSet<DiagnosticInfo>? useSiteDiagnostics)
{
switch (refKind)
{
case RefKind.None:
return HasIdentityOrImplicitReferenceConversion(sourceType, destinationType, ref useSiteDiagnostics)
|| HasImplicitPointerToVoidConversion(sourceType, destinationType)
|| HasImplicitPointerConversion(sourceType, destinationType, ref useSiteDiagnostics);
return (!IncludeNullability || HasTopLevelNullabilityImplicitConversion(sourceType, destinationType))
&& (HasIdentityOrImplicitReferenceConversion(sourceType.Type, destinationType.Type, ref useSiteDiagnostics)
|| HasImplicitPointerToVoidConversion(sourceType.Type, destinationType.Type)
|| HasImplicitPointerConversion(sourceType.Type, destinationType.Type, ref useSiteDiagnostics));

default:
return HasIdentityConversion(sourceType, destinationType);
return (!IncludeNullability || HasTopLevelNullabilityIdentityConversion(sourceType, destinationType))
&& HasIdentityConversion(sourceType.Type, destinationType.Type);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8888,7 +8888,6 @@ public override BoundNode VisitAwaitableInfo(BoundAwaitableInfo node)
return null;
}

// PROTOTYPE(func-ptr): Test nullable related features
public override BoundNode VisitFunctionPointerInvocation(BoundFunctionPointerInvocation node)
{
_ = Visit(node.InvokedExpression);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ internal bool Equals(FunctionPointerMethodSymbol other, TypeCompareKind compareK

private bool EqualsNoParameters(FunctionPointerMethodSymbol other, TypeCompareKind compareKind, IReadOnlyDictionary<TypeParameterSymbol, bool>? isValueTypeOverride)
=> CallingConvention == other.CallingConvention
&& RefKind == other.RefKind
&& FunctionPointerTypeSymbol.RefKindEquals(compareKind, RefKind, other.RefKind)
&& ((compareKind & TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds) != 0
|| RefCustomModifiers.SequenceEqual(other.RefCustomModifiers))
&& ReturnTypeWithAnnotations.Equals(other.ReturnTypeWithAnnotations, compareKind, isValueTypeOverride);
Expand All @@ -397,7 +397,7 @@ public override int GetHashCode()
}

internal int GetHashCodeNoParameters()
=> Hash.Combine(ReturnType, Hash.Combine(CallingConvention.GetHashCode(), RefKind.GetHashCode()));
=> Hash.Combine(ReturnType, Hash.Combine(CallingConvention.GetHashCode(), FunctionPointerTypeSymbol.GetRefKindForHashCode(RefKind).GetHashCode()));

internal override CallingConvention CallingConvention { get; }
public override bool ReturnsVoid => ReturnTypeWithAnnotations.IsVoidType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ internal bool Equals(FunctionPointerParameterSymbol other, TypeCompareKind compa
&& _containingSymbol.Equals(other._containingSymbol, compareKind, isValueTypeOverride);

internal bool MethodEqualityChecks(FunctionPointerParameterSymbol other, TypeCompareKind compareKind, IReadOnlyDictionary<TypeParameterSymbol, bool>? isValueTypeOverride)
=> RefKind == other.RefKind
=> FunctionPointerTypeSymbol.RefKindEquals(compareKind, RefKind, other.RefKind)
&& ((compareKind & TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds) != 0
|| RefCustomModifiers.SequenceEqual(other.RefCustomModifiers))
&& TypeWithAnnotations.Equals(other.TypeWithAnnotations, compareKind, isValueTypeOverride);
Expand All @@ -60,7 +60,7 @@ public override int GetHashCode()
}

internal int MethodHashCode()
=> Hash.Combine(TypeWithAnnotations.GetHashCode(), RefKind.GetHashCode());
=> Hash.Combine(TypeWithAnnotations.GetHashCode(), FunctionPointerTypeSymbol.GetRefKindForHashCode(RefKind).GetHashCode());

public override ImmutableArray<Location> Locations => ImmutableArray<Location>.Empty;
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => ImmutableArray<SyntaxReference>.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,24 @@ internal override TypeSymbol SetNullabilityForReferenceTypes(Func<TypeWithAnnota
return this;
}

/// <summary>
/// For scenarios such as overriding with differing ref kinds (such as out vs in or ref)
/// we need to compare function pointer parameters assuming that Ref matches RefReadonly/In
/// and Out. This is done because you cannot overload on ref vs out vs in in regular method
/// signatures, and we are disallowing similar overloads in source with function pointers.
/// </summary>
internal static bool RefKindEquals(TypeCompareKind compareKind, RefKind refKind1, RefKind refKind2)
=> (compareKind & TypeCompareKind.FunctionPointerRefMatchesOutInRefReadonly) != 0
? (refKind1 == RefKind.None) == (refKind2 == RefKind.None)
: refKind1 == refKind2;

/// <summary>
/// For scenarios such as overriding with differing ref kinds (such as out vs in or ref)
/// we need to compare function pointer parameters assuming that Ref matches RefReadonly/In
/// and Out. For that reason, we must also ensure that GetHashCode returns equal hashcodes
/// for types that only differ by the type of ref they have.
/// </summary>
internal static RefKind GetRefKindForHashCode(RefKind refKind)
=> refKind == RefKind.None ? RefKind.None : RefKind.Ref;
}
}
13 changes: 7 additions & 6 deletions src/Compilers/CSharp/Portable/Symbols/MemberSignatureComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ internal class MemberSignatureComparer : IEqualityComparer<Symbol>
considerTypeConstraints: false,
considerCallingConvention: false,
considerRefKindDifferences: false,
typeComparison: TypeCompareKind.AllIgnoreOptions); //shouldn't actually matter for source members
typeComparison: TypeCompareKind.AllIgnoreOptions);

/// <summary>
/// This instance is used to determine if a partial method implementation matches the definition.
Expand Down Expand Up @@ -313,6 +313,12 @@ private MemberSignatureComparer(
_considerCallingConvention = considerCallingConvention;
_considerRefKindDifferences = considerRefKindDifferences;
_typeComparison = typeComparison;
Debug.Assert((_typeComparison & TypeCompareKind.FunctionPointerRefMatchesOutInRefReadonly) == 0,
$"Rely on the {nameof(considerRefKindDifferences)} flag to set this to ensure all cases are handled.");
if (!considerRefKindDifferences)
{
_typeComparison |= TypeCompareKind.FunctionPointerRefMatchesOutInRefReadonly;
}
}

#region IEqualityComparer<Symbol> Members
Expand Down Expand Up @@ -456,11 +462,6 @@ public int GetHashCode(Symbol member)

#endregion

public static bool HaveSameReturnTypes(MethodSymbol member1, MethodSymbol member2, TypeCompareKind typeComparison)
{
return HaveSameReturnTypes(member1, GetTypeMap(member1), member2, GetTypeMap(member2), typeComparison);
}

private static bool HaveSameReturnTypes(Symbol member1, TypeMap typeMap1, Symbol member2, TypeMap typeMap2, TypeCompareKind typeComparison)
{
RefKind refKind1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE
/// </code>
/// </example>
/// </summary>
// PROTOTYPE(func-ptr): Implement and test in function pointers. Also dynamic and nullable
internal struct TupleTypeDecoder
{
private readonly ImmutableArray<string?> _elementNames;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy

Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)); // Same custom modifiers as source type.

Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic, nullability and tuple names as destination type.
// Same object/dynamic, nullability and tuple names as destination type.
Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds));

return resultType;
}
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Symbols/Symbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ public bool CanBeReferencedByName

case SymbolKind.ArrayType:
case SymbolKind.PointerType:
case SymbolKind.FunctionPointer:
case SymbolKind.Assembly:
case SymbolKind.DynamicType:
case SymbolKind.NetModule:
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ public static bool IsTypeOrTypeAlias(this Symbol symbol)
case SymbolKind.ErrorType:
case SymbolKind.NamedType:
case SymbolKind.PointerType:
case SymbolKind.FunctionPointer:
case SymbolKind.TypeParameter:
return true;
case SymbolKind.Alias:
Expand Down
48 changes: 48 additions & 0 deletions src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,13 @@ private static bool NormalizeTaskTypesInType(CSharpCompilation compilation, ref
type = pointerType;
return changed;
}
case SymbolKind.FunctionPointer:
{
var functionPointerType = (FunctionPointerTypeSymbol)type;
var changed = NormalizeTaskTypesInFunctionPointer(compilation, ref functionPointerType);
type = functionPointerType;
return changed;
}
}
return false;
}
Expand Down Expand Up @@ -1722,6 +1729,47 @@ private static bool NormalizeTaskTypesInPointer(CSharpCompilation compilation, r
return true;
}

private static bool NormalizeTaskTypesInFunctionPointer(CSharpCompilation compilation, ref FunctionPointerTypeSymbol funcPtrType)
{
var returnType = funcPtrType.Signature.ReturnTypeWithAnnotations;
var madeChanges = NormalizeTaskTypesInType(compilation, ref returnType);

var paramTypes = ImmutableArray<TypeWithAnnotations>.Empty;

if (funcPtrType.Signature.ParameterCount > 0)
{
var paramsBuilder = ArrayBuilder<TypeWithAnnotations>.GetInstance(funcPtrType.Signature.ParameterCount);
bool madeParamChanges = false;
foreach (var param in funcPtrType.Signature.Parameters)
{
var paramType = param.TypeWithAnnotations;
madeParamChanges |= NormalizeTaskTypesInType(compilation, ref paramType);
paramsBuilder.Add(paramType);
}

if (madeParamChanges)
{
madeChanges = true;
paramTypes = paramsBuilder.ToImmutableAndFree();
}
else
{
paramTypes = funcPtrType.Signature.ParameterTypesWithAnnotations;
paramsBuilder.Free();
}
}

if (madeChanges)
{
funcPtrType = funcPtrType.SubstituteTypeSymbol(returnType, paramTypes, refCustomModifiers: default, paramRefCustomModifiers: default);
return true;
}
else
{
return false;
}
}

internal static Cci.TypeReferenceWithAttributes GetTypeRefWithAttributes(
this TypeWithAnnotations type,
Emit.PEModuleBuilder moduleBuilder,
Expand Down
Loading

0 comments on commit 64d1878

Please sign in to comment.