Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ private static boolean constructibleBy(final Class<?> cls) {
THROW_CONVERSION = lk.findStatic(
MhIso.class,
"throwConversion",
MethodType.methodType(Object.class, Throwable.class, Object.class, Class.class, Class.class)
MethodType.methodType(Object.class, Throwable.class, Class.class, Class.class)
);
} catch (final ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
Expand Down Expand Up @@ -235,31 +235,14 @@ public static <S, T> Iso<S, T> pair(
* per element, and label a per-element failure with {@link #sourceClass()} / {@link
* #targetClass()}.
*/
private static final class Leaf<S, T> implements Iso<S, T> {

private final Class<S> sourceClass;
private final Class<T> targetClass;
private final Function<S, T> forward;
private final Function<T, S> backward;
private final MethodHandle rawFwd;
private final MethodHandle rawBwd;

Leaf(
final Class<S> sourceClass,
final Class<T> targetClass,
final Function<S, T> forward,
final Function<T, S> backward,
final MethodHandle rawFwd,
final MethodHandle rawBwd
) {
this.sourceClass = sourceClass;
this.targetClass = targetClass;
this.forward = forward;
this.backward = backward;
this.rawFwd = rawFwd;
this.rawBwd = rawBwd;
}

private record Leaf<S, T>(
Class<S> sourceClass,
Class<T> targetClass,
Function<S, T> forward,
Function<T, S> backward,
MethodHandle rawFwd,
MethodHandle rawBwd
) implements Iso<S, T> {
@Override
public T to(final S source) {
return forward.apply(source);
Expand All @@ -277,14 +260,6 @@ MethodHandle rawForward() {
MethodHandle rawBackward() {
return rawBwd;
}

Class<S> sourceClass() {
return sourceClass;
}

Class<T> targetClass() {
return targetClass;
}
}

/**
Expand Down Expand Up @@ -620,7 +595,10 @@ private static MethodHandle guardElement(final MethodHandle rawElem) {
* so the fused handle stays one composed tree with no SAM boundary; the happy path pays nothing.
*/
private static MethodHandle labelFailures(final MethodHandle raw, final Class<?> from, final Class<?> to) {
final MethodHandle handler = MethodHandles.insertArguments(THROW_CONVERSION, 2, from, to);
// THROW_CONVERSION is (Throwable, Class, Class) -> Object; binding from/to at positions 1,2
// leaves (Throwable) -> Object — a legal catchException handler (the handler may accept just
// the exception and an empty prefix of the target's parameters).
final MethodHandle handler = MethodHandles.insertArguments(THROW_CONVERSION, 1, from, to);
return MethodHandles.catchException(
raw.asType(MethodType.methodType(Object.class, Object.class)),
Throwable.class,
Expand All @@ -629,11 +607,11 @@ private static MethodHandle labelFailures(final MethodHandle raw, final Class<?>
}

/**
* {@code (Throwable, Object) -> Object} catch handler (bound to {@code from}/{@code to}): always
* throws, relabelling the failure via {@link #rethrow}. The {@code Object} argument is the leaf's
* input, ignored — it only aligns the handler arity with the guarded handle.
* {@code (Throwable, Class, Class) -> Object} catch handler; {@code from}/{@code to} are bound as
* constants at combinator-build time, leaving a {@code (Throwable) -> Object} handler that always
* throws, relabelling the failure via {@link #rethrow}.
*/
private static Object throwConversion(final Throwable t, final Object input, final Class<?> from, final Class<?> to) {
private static Object throwConversion(final Throwable t, final Class<?> from, final Class<?> to) {
throw rethrow(from, to, t);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
Expand Down Expand Up @@ -127,7 +128,7 @@ public static <A> Affine<Optional<A>, A> eachOptional() {
// A null Optional FIELD (not an empty Optional) focuses nothing, matching every other
// container traversal's null-source contract; the write side likewise leaves null alone.
return Affine.of(
source -> source == null ? Optional.empty() : source,
source -> Objects.requireNonNullElse(source, Optional.empty()),
(source, a) -> source != null && source.isPresent() ? Optional.of(a) : source
);
}
Expand Down Expand Up @@ -168,16 +169,22 @@ public boolean visitWhile(final C source, final Predicate<? super E> visitor) {

@Override
public C modify(final C source, final Function<? super E, ? extends E> f) {
if (source == null) return null;
if (source instanceof final List<?> list) {
final var out = new ArrayList<E>(list.size());
for (final var e : source) out.add(f.apply(e));
return (C) Collections.unmodifiableList(out);
}
if (source instanceof final Set<?> set) {
final var out = new LinkedHashSet<E>(set.size());
for (final var e : source) out.add(f.apply(e));
return (C) Collections.unmodifiableSet(out);
switch (source) {
case null -> {
return null;
}
case final List<?> list -> {
final var out = new ArrayList<E>(list.size());
for (final var e : source) out.add(f.apply(e));
return (C) Collections.unmodifiableList(out);
}
case final Set<?> set -> {
final var out = new LinkedHashSet<E>(set.size());
for (final var e : source) out.add(f.apply(e));
return (C) Collections.unmodifiableSet(out);
}
default -> {
}
}
// No safe rebuild for other Iterable shapes — the (C) cast would succeed on a List but
// throw ClassCastException downstream when callers store it into a field typed as e.g.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public enum Kind {
}

public ContainerView {
if ((keyType != null) != (kind == Kind.MAP_VALUES)) {
if ((keyType == null) == (kind == Kind.MAP_VALUES)) {
throw new IllegalArgumentException(
"keyType is required for MAP_VALUES and forbidden otherwise (kind=" + kind + ")"
);
Expand Down
Loading