Follow-up to #1243 (JSpecify nullness support, merged via #4033).
Two gaps were reported in #4035 (comment) (originally posted under #4035 but unrelated to that issue's array-element scope, so splitting out here):
-
Collection-typed property mapping — when the source getter is JSpecify @NonNull (or unannotated in a @NullMarked scope), MapStruct still emits
List<String> list = source.getNonNullListValue();
if ( list != null ) {
target.setValues( new ArrayList<>( list ) );
}
The wrapper should be skipped, mirroring the non-collection property mapping behaviour already in PropertyMapping.setterWrapperNeedsSourceNullCheck.
-
Container mapping methods (Iterable → Iterable, Map → Map, Stream → Stream) — ContainerMappingMethod and MapMappingMethod hardcode a NullPresenceCheck for the source parameter and always emit if ( source == null ) return null;, bypassing the JSpecify-aware PresenceCheckMethodResolver that BeanMappingMethod already uses.
Additionally, when a mapping method's return type is JSpecify @NonNull, generating return null; violates the return contract (e.g. NullAway flags returning @Nullable expression from method with @NonNull return type). The fix should force NullValueMappingStrategy.RETURN_DEFAULT semantics in that case, consistently across BeanMappingMethod, IterableMappingMethod, MapMappingMethod, and StreamMappingMethod.
The user's reproducer is the comment linked above (modifying JSpecifyNullMarkedTest's SourceBean/TargetBean to add a @NonNull List<String> field, plus the List<X> mapAll(List<Y>) shape).
Follow-up to #1243 (JSpecify nullness support, merged via #4033).
Two gaps were reported in #4035 (comment) (originally posted under #4035 but unrelated to that issue's array-element scope, so splitting out here):
Collection-typed property mapping — when the source getter is JSpecify
@NonNull(or unannotated in a@NullMarkedscope), MapStruct still emitsThe wrapper should be skipped, mirroring the non-collection property mapping behaviour already in
PropertyMapping.setterWrapperNeedsSourceNullCheck.Container mapping methods (
Iterable → Iterable,Map → Map,Stream → Stream) —ContainerMappingMethodandMapMappingMethodhardcode aNullPresenceCheckfor the source parameter and always emitif ( source == null ) return null;, bypassing the JSpecify-awarePresenceCheckMethodResolverthatBeanMappingMethodalready uses.Additionally, when a mapping method's return type is JSpecify
@NonNull, generatingreturn null;violates the return contract (e.g. NullAway flagsreturning @Nullable expression from method with @NonNull return type). The fix should forceNullValueMappingStrategy.RETURN_DEFAULTsemantics in that case, consistently acrossBeanMappingMethod,IterableMappingMethod,MapMappingMethod, andStreamMappingMethod.The user's reproducer is the comment linked above (modifying
JSpecifyNullMarkedTest'sSourceBean/TargetBeanto add a@NonNull List<String>field, plus theList<X> mapAll(List<Y>)shape).