Skip to content

Commit

Permalink
Handle cycles in IsValueType and IsReferenceType binding constraints (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
cston authored Sep 25, 2020
1 parent f33a0fd commit 1f53c66
Show file tree
Hide file tree
Showing 38 changed files with 411 additions and 143 deletions.
4 changes: 4 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/Binder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ internal bool AreNullableAnnotationsEnabled(SyntaxTree syntaxTree, int position)
internal bool AreNullableAnnotationsEnabled(SyntaxToken token)
{
RoslynDebug.Assert(token.SyntaxTree is object);
if ((Flags & BinderFlags.IgnoreNullableContext) != 0)
{
return false;
}
return AreNullableAnnotationsEnabled(token.SyntaxTree, token.SpanStart);
}

Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/Binder/BinderFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ internal enum BinderFlags : uint
/// </summary>
InEEMethodBinder = 1 << 30,

/// <summary>
/// Assume '#nullable disable' context.
/// </summary>
IgnoreNullableContext = 1u << 31,

// Groups

AllClearedAtExecutableCodeBoundary = InLockBody | InCatchBlock | InCatchFilter | InFinallyBlock | InTryBlockOfTryCatch | InNestedFinallyBlock,
Expand Down
11 changes: 7 additions & 4 deletions src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ internal ImmutableArray<TypeParameterConstraintClause> BindTypeParameterConstrai
ImmutableArray<TypeParameterSymbol> typeParameters,
TypeParameterListSyntax typeParameterList,
SyntaxList<TypeParameterConstraintClauseSyntax> clauses,
bool canIgnoreNullableContext,
ref IReadOnlyDictionary<TypeParameterSymbol, bool> isValueTypeOverride,
DiagnosticBag diagnostics,
bool isForOverride = false)
Expand Down Expand Up @@ -66,7 +67,8 @@ internal ImmutableArray<TypeParameterConstraintClause> BindTypeParameterConstrai
Debug.Assert(ordinal >= 0);
Debug.Assert(ordinal < n);

(TypeParameterConstraintClause constraintClause, ArrayBuilder<TypeConstraintSyntax>? typeConstraintNodes) = this.BindTypeParameterConstraints(typeParameterList.Parameters[ordinal], clause, isForOverride, diagnostics);
(TypeParameterConstraintClause constraintClause, ArrayBuilder<TypeConstraintSyntax>? typeConstraintNodes) =
this.BindTypeParameterConstraints(typeParameterList.Parameters[ordinal], clause, isForOverride, canIgnoreNullableContext: canIgnoreNullableContext, diagnostics);
if (results[ordinal] == null)
{
results[ordinal] = constraintClause;
Expand Down Expand Up @@ -117,7 +119,8 @@ internal ImmutableArray<TypeParameterConstraintClause> BindTypeParameterConstrai
/// <summary>
/// Bind and return a single type parameter constraint clause along with syntax nodes corresponding to type constraints.
/// </summary>
private (TypeParameterConstraintClause, ArrayBuilder<TypeConstraintSyntax>?) BindTypeParameterConstraints(TypeParameterSyntax typeParameterSyntax, TypeParameterConstraintClauseSyntax constraintClauseSyntax, bool isForOverride, DiagnosticBag diagnostics)
private (TypeParameterConstraintClause, ArrayBuilder<TypeConstraintSyntax>?) BindTypeParameterConstraints(
TypeParameterSyntax typeParameterSyntax, TypeParameterConstraintClauseSyntax constraintClauseSyntax, bool isForOverride, bool canIgnoreNullableContext, DiagnosticBag diagnostics)
{
var constraints = TypeParameterConstraintKind.None;
ArrayBuilder<TypeWithAnnotations>? constraintTypes = null;
Expand Down Expand Up @@ -307,7 +310,7 @@ internal ImmutableArray<TypeParameterConstraintClause> BindTypeParameterConstrai
Debug.Assert(!isForOverride ||
(constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType));

return (TypeParameterConstraintClause.Create(constraints, constraintTypes?.ToImmutableAndFree() ?? ImmutableArray<TypeWithAnnotations>.Empty), syntaxBuilder);
return (TypeParameterConstraintClause.Create(constraints, constraintTypes?.ToImmutableAndFree() ?? ImmutableArray<TypeWithAnnotations>.Empty, canIgnoreNullableContext), syntaxBuilder);

static void reportOverrideWithConstraints(ref bool reportedOverrideWithConstraints, TypeParameterConstraintSyntax syntax, DiagnosticBag diagnostics)
{
Expand Down Expand Up @@ -390,7 +393,7 @@ private static TypeParameterConstraintClause RemoveInvalidConstraints(

if (constraintTypeBuilder.Count < n)
{
return TypeParameterConstraintClause.Create(constraintClause.Constraints, constraintTypeBuilder.ToImmutableAndFree());
return TypeParameterConstraintClause.Create(constraintClause.Constraints, constraintTypeBuilder.ToImmutableAndFree(), constraintClause.IgnoresNullableContext);
}

constraintTypeBuilder.Free();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ private static bool IsNamedTypeAccessible(NamedTypeSymbol type, Symbol within, r
{
// type parameters are always accessible, so don't check those (so common it's
// worth optimizing this).
if (typeArg.Type.Kind != SymbolKind.TypeParameter && !IsSymbolAccessibleCore(typeArg.Type, within, null, out unused, compilation, ref useSiteDiagnostics, basesBeingResolved))
if (typeArg.DefaultType.TypeKind != TypeKind.TypeParameter && !IsSymbolAccessibleCore(typeArg.Type, within, null, out unused, compilation, ref useSiteDiagnostics, basesBeingResolved))
{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters
get { return _typeParameters; }
}

public sealed override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses()
public sealed override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool canIgnoreNullableContext)
=> ImmutableArray<TypeParameterConstraintClause>.Empty;

internal override int ParameterCount
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,11 @@ public override VarianceKind Variance
get { return VarianceKind.None; }
}

internal override void EnsureAllConstraintsAreResolved()
internal override void EnsureAllConstraintsAreResolved(bool canIgnoreNullableContext)
{
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
return ImmutableArray<TypeWithAnnotations>.Empty;
}
Expand Down
9 changes: 6 additions & 3 deletions src/Compilers/CSharp/Portable/Symbols/ConstraintsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,13 @@ public static TypeParameterBounds ResolveBounds(
ConsList<TypeParameterSymbol> inProgress,
ImmutableArray<TypeWithAnnotations> constraintTypes,
bool inherited,
bool ignoresNullableContext,
CSharpCompilation currentCompilation,
DiagnosticBag diagnostics)
{
var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
var bounds = typeParameter.ResolveBounds(corLibrary, inProgress, constraintTypes, inherited, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);
var bounds = typeParameter.ResolveBounds(corLibrary, inProgress, constraintTypes, inherited, ignoresNullableContext: ignoresNullableContext, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);

if (useSiteDiagnosticsBuilder != null)
{
Expand All @@ -97,6 +98,7 @@ public static TypeParameterBounds ResolveBounds(
ConsList<TypeParameterSymbol> inProgress,
ImmutableArray<TypeWithAnnotations> constraintTypes,
bool inherited,
bool ignoresNullableContext,
CSharpCompilation currentCompilation,
ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder,
ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder)
Expand Down Expand Up @@ -295,7 +297,7 @@ public static TypeParameterBounds ResolveBounds(
return null;
}

var bounds = new TypeParameterBounds(constraintTypes, interfaces, effectiveBaseClass, deducedBaseType);
var bounds = new TypeParameterBounds(constraintTypes, interfaces, effectiveBaseClass, deducedBaseType, ignoresNullableContext);

// Additional constraint checks for overrides.
if (inherited)
Expand All @@ -312,7 +314,7 @@ internal static ImmutableArray<TypeParameterConstraintClause> MakeTypeParameterC
ImmutableArray<TypeParameterSymbol> typeParameters,
TypeParameterListSyntax typeParameterList,
SyntaxList<TypeParameterConstraintClauseSyntax> constraintClauses,
Location location,
bool canIgnoreNullableContext,
DiagnosticBag diagnostics)
{
if (typeParameters.Length == 0)
Expand All @@ -334,6 +336,7 @@ internal static ImmutableArray<TypeParameterConstraintClause> MakeTypeParameterC

IReadOnlyDictionary<TypeParameterSymbol, bool> isValueTypeOverride = null;
return binder.BindTypeParameterConstraintClauses(containingSymbol, typeParameters, typeParameterList, constraintClauses,
canIgnoreNullableContext,
ref isValueTypeOverride,
diagnostics);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ public override bool IsImplicitlyDeclared
}
}

internal override void EnsureAllConstraintsAreResolved()
internal override void EnsureAllConstraintsAreResolved(bool canIgnoreNullableContext)
{
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
return ImmutableArray<TypeWithAnnotations>.Empty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,18 +568,19 @@ public override VarianceKind Variance
}
}

internal override void EnsureAllConstraintsAreResolved()
internal override void EnsureAllConstraintsAreResolved(bool canIgnoreNullableContext)
{
if (!_lazyBounds.IsSet())
canIgnoreNullableContext = false; // Resolve bounds eagerly.
if (!_lazyBounds.HasValue(canIgnoreNullableContext))
{
var typeParameters = (_containingSymbol.Kind == SymbolKind.Method) ?
((PEMethodSymbol)_containingSymbol).TypeParameters :
((PENamedTypeSymbol)_containingSymbol).TypeParameters;
EnsureAllConstraintsAreResolved(typeParameters);
EnsureAllConstraintsAreResolved(typeParameters, canIgnoreNullableContext);
}
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
var bounds = this.GetBounds(inProgress);
return (bounds != null) ? bounds.ConstraintTypes : ImmutableArray<TypeWithAnnotations>.Empty;
Expand Down Expand Up @@ -634,7 +635,7 @@ private TypeParameterBounds GetBounds(ConsList<TypeParameterSymbol> inProgress)
var diagnostics = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
bool inherited = (_containingSymbol.Kind == SymbolKind.Method) && ((MethodSymbol)_containingSymbol).IsOverride;
var bounds = this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited, currentCompilation: null,
var bounds = this.ResolveBounds(this.ContainingAssembly.CorLibrary, inProgress.Prepend(this), constraintTypes, inherited, ignoresNullableContext: false, currentCompilation: null,
diagnosticsBuilder: diagnostics, useSiteDiagnosticsBuilder: ref useSiteDiagnosticsBuilder);
DiagnosticInfo errorInfo = null;

Expand Down Expand Up @@ -670,7 +671,7 @@ private TypeParameterBounds GetBounds(ConsList<TypeParameterSymbol> inProgress)

internal override DiagnosticInfo GetConstraintsUseSiteErrorInfo()
{
EnsureAllConstraintsAreResolved();
EnsureAllConstraintsAreResolved(canIgnoreNullableContext: false);
Debug.Assert(!ReferenceEquals(_lazyConstraintsUseSiteErrorInfo, CSDiagnosticInfo.EmptyErrorInfo));
return _lazyConstraintsUseSiteErrorInfo;
}
Expand Down
9 changes: 7 additions & 2 deletions src/Compilers/CSharp/Portable/Symbols/NamedTypeSymbol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ internal ImmutableArray<TypeWithAnnotations> TypeArgumentsWithDefinitionUseSiteD

foreach (var typeArgument in result)
{
typeArgument.Type.OriginalDefinition.AddUseSiteDiagnostics(ref useSiteDiagnostics);
AddDefinitionUseSiteDiagnostics(typeArgument, ref useSiteDiagnostics);
}

return result;
Expand All @@ -72,10 +72,15 @@ internal ImmutableArray<TypeWithAnnotations> TypeArgumentsWithDefinitionUseSiteD
internal TypeWithAnnotations TypeArgumentWithDefinitionUseSiteDiagnostics(int index, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
var result = TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[index];
result.Type.OriginalDefinition.AddUseSiteDiagnostics(ref useSiteDiagnostics);
AddDefinitionUseSiteDiagnostics(result, ref useSiteDiagnostics);
return result;
}

private static void AddDefinitionUseSiteDiagnostics(TypeWithAnnotations type, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
{
type.DefaultType.OriginalDefinition.AddUseSiteDiagnostics(ref useSiteDiagnostics);
}

/// <summary>
/// Returns the type symbol that this type was constructed from. This type symbol
/// has the same containing type (if any), but has type arguments that are the same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ internal override ModuleSymbol ContainingModule
}
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetConstraintTypes(inProgress));
return this.RetargetingTranslator.Retarget(_underlyingTypeParameter.GetConstraintTypes(inProgress, canIgnoreNullableContext));
}

internal override bool? IsNotNullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
}
}

internal override void EnsureAllConstraintsAreResolved()
internal override void EnsureAllConstraintsAreResolved(bool canIgnoreNullableContext)
{
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
return ImmutableArray<TypeWithAnnotations>.Empty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,11 @@ public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
}
}

internal override void EnsureAllConstraintsAreResolved()
internal override void EnsureAllConstraintsAreResolved(bool canIgnoreNullableContext)
{
}

internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress)
internal override ImmutableArray<TypeWithAnnotations> GetConstraintTypes(ConsList<TypeParameterSymbol> inProgress, bool canIgnoreNullableContext)
{
return ImmutableArray<TypeWithAnnotations>.Empty;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ internal override bool GenerateDebugInfo

internal override bool IsInitOnly => false;

public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses() => ImmutableArray<TypeParameterConstraintClause>.Empty;
public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool canIgnoreNullableContext) => ImmutableArray<TypeParameterConstraintClause>.Empty;

internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,9 @@ private ImmutableArray<SourceMethodTypeParameterSymbol> MakeTypeParameters(Diagn
return result.ToImmutableAndFree();
}

public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses()
public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool canIgnoreNullableContext)
{
if (_lazyTypeParameterConstraints.IsDefault)
if (!_lazyTypeParameterConstraints.HasValue(canIgnoreNullableContext))
{
var syntax = Syntax;
var diagnostics = DiagnosticBag.GetInstance();
Expand All @@ -472,13 +472,17 @@ public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterCo
TypeParameters,
syntax.TypeParameterList,
syntax.ConstraintClauses,
syntax.Identifier.GetLocation(),
canIgnoreNullableContext,
diagnostics);
lock (_declarationDiagnostics)
{
if (_lazyTypeParameterConstraints.IsDefault)
canIgnoreNullableContext = constraints.IgnoresNullableContext();
if (!_lazyTypeParameterConstraints.HasValue(canIgnoreNullableContext))
{
_declarationDiagnostics.AddRange(diagnostics);
if (!canIgnoreNullableContext)
{
_declarationDiagnostics.AddRange(diagnostics);
}
_lazyTypeParameterConstraints = constraints;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public sealed override ImmutableArray<TypeParameterSymbol> TypeParameters
get { return ImmutableArray<TypeParameterSymbol>.Empty; }
}

public sealed override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses()
public sealed override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool canIgnoreNullableContext)
=> ImmutableArray<TypeParameterConstraintClause>.Empty;

public override RefKind RefKind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public override ImmutableArray<TypeParameterSymbol> TypeParameters
}
}

public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses()
public override ImmutableArray<TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool canIgnoreNullableContext)
=> ImmutableArray<TypeParameterConstraintClause>.Empty;

public sealed override TypeWithAnnotations ReturnTypeWithAnnotations
Expand Down
Loading

0 comments on commit 1f53c66

Please sign in to comment.