/// <summary> /// Substitute types, and return the results without duplicates, preserving the original order. /// Note, all occurrences of 'dynamic' in resulting types will be replaced with 'object'. /// </summary> internal void SubstituteConstraintTypesDistinctWithoutModifiers( TypeParameterSymbol owner, ImmutableArray <TypeWithAnnotations> original, ArrayBuilder <TypeWithAnnotations> result, HashSet <TypeParameterSymbol> ignoreTypesDependentOnTypeParametersOpt) { DynamicTypeEraser dynamicEraser = null; if (original.Length == 0) { return; } else if (original.Length == 1) { var type = original[0]; if (ignoreTypesDependentOnTypeParametersOpt == null || !type.Type.ContainsTypeParameters(ignoreTypesDependentOnTypeParametersOpt)) { result.Add(substituteConstraintType(type)); } } else { var map = PooledDictionary <TypeSymbol, int> .GetInstance(); foreach (var type in original) { if (ignoreTypesDependentOnTypeParametersOpt == null || !type.Type.ContainsTypeParameters(ignoreTypesDependentOnTypeParametersOpt)) { var substituted = substituteConstraintType(type); if (!map.TryGetValue(substituted.Type, out int mergeWith)) { map.Add(substituted.Type, result.Count); result.Add(substituted); } else { result[mergeWith] = ConstraintsHelper.ConstraintWithMostSignificantNullability(result[mergeWith], substituted); } } } map.Free(); } TypeWithAnnotations substituteConstraintType(TypeWithAnnotations type) { if (dynamicEraser == null) { dynamicEraser = new DynamicTypeEraser(owner.ContainingAssembly.CorLibrary.GetSpecialType(SpecialType.System_Object)); } TypeWithAnnotations substituted = SubstituteType(type); return(substituted.WithTypeAndModifiers(dynamicEraser.EraseDynamic(substituted.Type), substituted.CustomModifiers)); } }
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()); }
public override ImmutableArray <TypeParameterConstraintClause> GetTypeParameterConstraintClauses(bool early) { var clauses = _lazyTypeParameterConstraints; if (clauses.IsDefault) { // Early step. var diagnostics = DiagnosticBag.GetInstance(); var constraints = this.MakeTypeParameterConstraintsEarly( _binder, TypeParameters, _syntax.TypeParameterList, _syntax.ConstraintClauses, _syntax.Identifier.GetLocation(), diagnostics); lock (_declarationDiagnostics) { if (_lazyTypeParameterConstraints.IsDefault) { _declarationDiagnostics.AddRange(diagnostics); _lazyTypeParameterConstraints = constraints; } } diagnostics.Free(); clauses = _lazyTypeParameterConstraints; } if (!early && clauses.IsEarly()) { // Late step. var diagnostics = DiagnosticBag.GetInstance(); var constraints = ConstraintsHelper.MakeTypeParameterConstraintsLate(TypeParameters, clauses, diagnostics); Debug.Assert(!constraints.IsEarly()); lock (_declarationDiagnostics) { if (_lazyTypeParameterConstraints.IsEarly()) { _declarationDiagnostics.AddRange(diagnostics); _lazyTypeParameterConstraints = constraints; } } diagnostics.Free(); } return(_lazyTypeParameterConstraints); }
/// <summary> /// Substitute types, and return the results without duplicates, preserving the original order. /// </summary> internal void SubstituteConstraintTypesDistinctWithoutModifiers( ImmutableArray <TypeWithAnnotations> original, ArrayBuilder <TypeWithAnnotations> result, HashSet <TypeParameterSymbol> ignoreTypesDependentOnTypeParametersOpt) { if (original.Length == 0) { return; } else if (original.Length == 1) { var type = original[0]; if (ignoreTypesDependentOnTypeParametersOpt == null || !type.Type.ContainsTypeParameters(ignoreTypesDependentOnTypeParametersOpt)) { result.Add(SubstituteType(type)); } } else { var map = PooledDictionary <TypeSymbol, int> .GetInstance(); foreach (var type in original) { if (ignoreTypesDependentOnTypeParametersOpt == null || !type.Type.ContainsTypeParameters(ignoreTypesDependentOnTypeParametersOpt)) { var substituted = SubstituteType(type); if (!map.TryGetValue(substituted.Type, out int mergeWith)) { map.Add(substituted.Type, result.Count); result.Add(substituted); } else { result[mergeWith] = ConstraintsHelper.ConstraintWithMostSignificantNullability(result[mergeWith], substituted); } } } map.Free(); } }