@@ -184,13 +184,26 @@ GeneratorOptions options
184184 if ( options is null )
185185 throw new ArgumentNullException ( nameof ( options ) ) ;
186186
187- static bool HasUnmanagedConstraint ( Type genericParameter )
188- => genericParameter . CustomAttributes . Any (
189- static attr => attr . AttributeType . FullName . Equals ( "System.Runtime.CompilerServices.IsUnmanagedAttribute" , StringComparison . Ordinal )
187+ static bool ConstraintTypesContainsValueType ( Type genericParameter , out IEnumerable < Type > constraintTypesExceptForValueType )
188+ {
189+ var constraintTypes = genericParameter . GetGenericParameterConstraints ( ) ;
190+
191+ var indexOfValueType = Array . FindIndex (
192+ constraintTypes ,
193+ static t => string . Equals ( t . FullName , typeof ( ValueType ) . FullName , StringComparison . Ordinal )
190194 ) ;
191195
192- static bool IsValueType ( Type t ) => string . Equals ( t . FullName , typeof ( ValueType ) . FullName , StringComparison . Ordinal ) ;
193- static bool IsNotValueType ( Type t ) => ! string . Equals ( t . FullName , typeof ( ValueType ) . FullName , StringComparison . Ordinal ) ;
196+ if ( indexOfValueType < 0 ) {
197+ constraintTypesExceptForValueType = constraintTypes ;
198+ return false ;
199+ }
200+
201+ constraintTypesExceptForValueType = constraintTypes
202+ . Take ( indexOfValueType )
203+ . Concat ( constraintTypes . Skip ( indexOfValueType + 1 ) ) ;
204+
205+ return true ;
206+ }
194207
195208 static IEnumerable < string > GetGenericParameterConstraintsOf (
196209 Type genericParameter ,
@@ -199,53 +212,40 @@ bool typeWithNamespace
199212 )
200213 {
201214 var constraintAttrs = genericParameter . GenericParameterAttributes & GenericParameterAttributes . SpecialConstraintMask ;
202- IEnumerable < Type > constraintTypes = genericParameter . GetGenericParameterConstraints ( ) ;
203- IEnumerable < Type > constraintTypesExceptValueType = constraintTypes ;
204-
205- referencingNns ? . UnionWith ( constraintTypes . Where ( IsNotValueType ) . SelectMany ( CSharpFormatter . ToNamespaceList ) ) ;
215+ var hasDefaultConstructorConstraint = constraintAttrs . HasFlag ( GenericParameterAttributes . DefaultConstructorConstraint ) ;
216+ IEnumerable < Type > ? constraintTypes = null ;
206217
207- if (
208- constraintAttrs == GenericParameterAttributes . None &&
209- genericParameter . HasGenericParameterNotNullConstraint ( )
210- ) {
211- yield return "notnull" ;
218+ if ( constraintAttrs == GenericParameterAttributes . None ) {
219+ if ( genericParameter . HasGenericParameterNotNullConstraint ( ) )
220+ yield return "notnull" ;
212221 }
222+ else if ( constraintAttrs . HasFlag ( GenericParameterAttributes . NotNullableValueTypeConstraint ) ) {
223+ yield return genericParameter . HasGenericParameterUnmanagedConstraint ( )
224+ ? "unmanaged"
225+ : "struct" ;
213226
214- if (
215- constraintAttrs . HasFlag ( GenericParameterAttributes . NotNullableValueTypeConstraint ) &&
216- constraintAttrs . HasFlag ( GenericParameterAttributes . DefaultConstructorConstraint ) &&
217- constraintTypes . Any ( IsValueType )
218- ) {
219- constraintAttrs &= ~ GenericParameterAttributes . NotNullableValueTypeConstraint ;
220- constraintAttrs &= ~ GenericParameterAttributes . DefaultConstructorConstraint ;
221- constraintTypesExceptValueType = constraintTypes . Where ( IsNotValueType ) ;
222-
223- if ( HasUnmanagedConstraint ( genericParameter ) )
224- yield return "unmanaged" ;
225- else
226- yield return "struct" ;
227+ if ( hasDefaultConstructorConstraint && ConstraintTypesContainsValueType ( genericParameter , out constraintTypes ) )
228+ hasDefaultConstructorConstraint = false ; // contraint type of System.ValueType implies `new()`
227229 }
228230 else if ( constraintAttrs . HasFlag ( GenericParameterAttributes . ReferenceTypeConstraint ) ) {
229231 yield return genericParameter . GetNullableAttributeMetadataValue ( ) == NullableMetadataValue . Annotated
230232 ? "class?"
231233 : "class" ;
232234 }
233- else if ( constraintAttrs . HasFlag ( GenericParameterAttributes . NotNullableValueTypeConstraint ) ) {
234- if ( HasUnmanagedConstraint ( genericParameter ) )
235- yield return "unmanaged" ;
236- else
237- yield return "struct" ;
238- }
239235
240- var orderedConstraintTypeNames = constraintTypesExceptValueType
236+ constraintTypes ??= genericParameter . GetGenericParameterConstraints ( ) ;
237+
238+ var orderedConstraintTypeNames = constraintTypes
241239 . Select ( constraintType => constraintType . FormatTypeName ( typeWithNamespace : typeWithNamespace ) )
242240 . OrderBy ( static name => name , StringComparer . Ordinal ) ;
243241
244242 foreach ( var ctn in orderedConstraintTypeNames )
245243 yield return ctn ;
246244
247- if ( constraintAttrs . HasFlag ( GenericParameterAttributes . DefaultConstructorConstraint ) )
245+ if ( hasDefaultConstructorConstraint )
248246 yield return "new()" ;
247+
248+ referencingNns ? . UnionWith ( constraintTypes . SelectMany ( CSharpFormatter . ToNamespaceList ) ) ;
249249 }
250250
251251 var constraints = string . Join (
0 commit comments