Browse Source

Nullability of type parameters "where T : class?"

pull/1425/head
Daniel Grunwald 6 years ago
parent
commit
bbbfe81c25
  1. 6
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  2. 5
      ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs
  3. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs
  4. 8
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs
  5. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs
  6. 33
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
  7. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs

6
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -1724,7 +1724,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1724,7 +1724,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Constraint c = new Constraint();
c.TypeParameter = new SimpleType (tp.Name);
if (tp.HasReferenceTypeConstraint) {
c.BaseTypes.Add(new PrimitiveType("class"));
if (tp.NullabilityConstraint == Nullability.Nullable) {
c.BaseTypes.Add(new PrimitiveType("class").MakeNullableType());
} else {
c.BaseTypes.Add(new PrimitiveType("class"));
}
} else if (tp.HasValueTypeConstraint) {
c.BaseTypes.Add(new PrimitiveType("struct"));
}

5
ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs

@ -86,6 +86,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -86,6 +86,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Gets if the type parameter has the 'struct' constraint.
/// </summary>
bool HasValueTypeConstraint { get; }
/// <summary>
/// Nullability of the reference type constraint. (e.g. "where T : class?").
/// </summary>
Nullability NullabilityConstraint { get; }
}
/// <summary>

3
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs

@ -158,7 +158,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -158,7 +158,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public abstract bool HasDefaultConstructorConstraint { get; }
public abstract bool HasReferenceTypeConstraint { get; }
public abstract bool HasValueTypeConstraint { get; }
public abstract Nullability NullabilityConstraint { get; }
public TypeKind Kind {
get { return TypeKind.TypeParameter; }
}

8
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultTypeParameter.cs

@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -26,6 +26,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly bool hasValueTypeConstraint;
readonly bool hasReferenceTypeConstraint;
readonly bool hasDefaultConstructorConstraint;
readonly Nullability nullabilityConstraint;
readonly IReadOnlyList<IType> constraints;
readonly IReadOnlyList<IAttribute> attributes;
@ -35,12 +36,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -35,12 +36,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
VarianceModifier variance = VarianceModifier.Invariant,
IReadOnlyList<IAttribute> attributes = null,
bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false,
IReadOnlyList<IType> constraints = null)
IReadOnlyList<IType> constraints = null, Nullability nullabilityConstraint = Nullability.Oblivious)
: base(owner, index, name, variance)
{
this.hasValueTypeConstraint = hasValueTypeConstraint;
this.hasReferenceTypeConstraint = hasReferenceTypeConstraint;
this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint;
this.nullabilityConstraint = nullabilityConstraint;
this.constraints = constraints ?? EmptyList<IType>.Instance;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
}
@ -51,12 +53,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -51,12 +53,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
VarianceModifier variance = VarianceModifier.Invariant,
IReadOnlyList<IAttribute> attributes = null,
bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false,
IReadOnlyList<IType> constraints = null)
IReadOnlyList<IType> constraints = null, Nullability nullabilityConstraint = Nullability.Oblivious)
: base(compilation, ownerType, index, name, variance)
{
this.hasValueTypeConstraint = hasValueTypeConstraint;
this.hasReferenceTypeConstraint = hasReferenceTypeConstraint;
this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint;
this.nullabilityConstraint = nullabilityConstraint;
this.constraints = constraints ?? EmptyList<IType>.Instance;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
}
@ -66,6 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -66,6 +69,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasValueTypeConstraint => hasValueTypeConstraint;
public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint;
public override bool HasDefaultConstructorConstraint => hasDefaultConstructorConstraint;
public override Nullability NullabilityConstraint => nullabilityConstraint;
public override IEnumerable<IType> DirectBaseTypes {
get {

4
ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs

@ -174,5 +174,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -174,5 +174,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool ITypeParameter.HasValueTypeConstraint {
get { return false; }
}
Nullability ITypeParameter.NullabilityConstraint {
get { return Nullability.Oblivious; }
}
}
}

33
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs

@ -35,6 +35,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -35,6 +35,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded:
IReadOnlyList<IType> constraints;
const byte nullabilityNotYetLoaded = 255;
byte nullabilityConstraint = nullabilityNotYetLoaded;
public static ITypeParameter[] Create(MetadataModule module, ITypeDefinition copyFromOuter, IEntity owner, GenericParameterHandleCollection handles)
{
@ -112,6 +114,37 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -112,6 +114,37 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasReferenceTypeConstraint => (attr & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
public override bool HasValueTypeConstraint => (attr & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
public override Nullability NullabilityConstraint {
get {
if (nullabilityConstraint == nullabilityNotYetLoaded) {
nullabilityConstraint = (byte)LoadNullabilityConstraint();
}
return (Nullability)nullabilityConstraint;
}
}
Nullability LoadNullabilityConstraint()
{
if ((module.TypeSystemOptions & TypeSystemOptions.NullabilityAnnotations) == 0)
return Nullability.Oblivious;
var metadata = module.metadata;
var gp = metadata.GetGenericParameter(handle);
foreach (var handle in gp.GetCustomAttributes()) {
var customAttribute = metadata.GetCustomAttribute(handle);
if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.Nullable)) {
var attrVal = customAttribute.DecodeValue(module.TypeProvider);
if (attrVal.FixedArguments.Length == 1) {
if (attrVal.FixedArguments[0].Value is byte b && b <= 2) {
return (Nullability)b;
}
}
}
}
return Nullability.Oblivious;
}
public override IEnumerable<IType> DirectBaseTypes {
get {
var constraints = LazyInit.VolatileRead(ref this.constraints);

4
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs

@ -253,7 +253,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -253,7 +253,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override bool HasDefaultConstructorConstraint {
get { return baseTp.HasDefaultConstructorConstraint; }
}
public override Nullability NullabilityConstraint => baseTp.NullabilityConstraint;
public override IEnumerable<IType> DirectBaseTypes {
get {
return baseTp.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution));

Loading…
Cancel
Save