internal override ImmutableArray <TypeWithAnnotations> GetConstraintTypes(ConsList <TypeParameterSymbol> inProgress, bool canIgnoreNullableContext) { var constraintTypes = ArrayBuilder <TypeWithAnnotations> .GetInstance(); _map.SubstituteConstraintTypesDistinctWithoutModifiers(_underlyingTypeParameter, _underlyingTypeParameter.GetConstraintTypes(inProgress, canIgnoreNullableContext), constraintTypes, null); TypeWithAnnotations bestObjectConstraint = default; // Strip all Object constraints. for (int i = constraintTypes.Count - 1; i >= 0; i--) { TypeWithAnnotations type = constraintTypes[i]; if (ConstraintsHelper.IsObjectConstraint(type, ref bestObjectConstraint)) { constraintTypes.RemoveAt(i); } } if (bestObjectConstraint.HasType) { // See if we need to put Object! or Object~ back in order to preserve nullability information for the type parameter. if (!canIgnoreNullableContext && ConstraintsHelper.IsObjectConstraintSignificant(CalculateIsNotNullableFromNonTypeConstraints(), bestObjectConstraint)) { Debug.Assert(!HasNotNullConstraint && !HasValueTypeConstraint); if (constraintTypes.Count == 0) { if (bestObjectConstraint.NullableAnnotation.IsOblivious() && !HasReferenceTypeConstraint) { bestObjectConstraint = default; } } else { foreach (TypeWithAnnotations constraintType in constraintTypes) { if (!ConstraintsHelper.IsObjectConstraintSignificant(IsNotNullableFromConstraintType(constraintType, out _), bestObjectConstraint)) { bestObjectConstraint = default; break; } } } if (bestObjectConstraint.HasType) { constraintTypes.Insert(0, bestObjectConstraint); } } } return(constraintTypes.ToImmutableAndFree()); }