Skip to content

Conversation

@stevearmstrong-dev
Copy link

Summary

Fixes #3909 by ensuring all Set-returning methods in ImmutableGraph, ImmutableValueGraph, and ImmutableNetwork consistently throw UnsupportedOperationException when modification is attempted, even for empty collections.

Changes

  • Wrapped all Set-returning methods with Collections.unmodifiableSet():

    • nodes()
    • edges()
    • adjacentNodes(N node)
    • predecessors(N node)
    • successors(N node)
    • incidentEdges(N node)
  • Applied changes to:

    • ImmutableGraph (JRE and Android)
    • ImmutableValueGraph (JRE and Android)
    • ImmutableNetwork (JRE and Android)
  • Added comprehensive tests demonstrating the fix works for both empty and non-empty graphs

Test Plan

  • Added 8 new test methods to ImmutableValueGraphTest
  • Added 8 new test methods to ImmutableNetworkTest
  • Tests verify UOE is thrown consistently for all Set-returning methods
  • All changes applied to both JRE and Android test modules

This commit addresses issue google#3909 by ensuring that all Set-returning
methods in ImmutableGraph, ImmutableValueGraph, and ImmutableNetwork
consistently throw UnsupportedOperationException when modification is
attempted, regardless of whether the collections are empty or not.

Changes:
- Wrapped all Set-returning methods (nodes(), edges(), adjacentNodes(),
  predecessors(), successors(), incidentEdges()) with
  Collections.unmodifiableSet() in all three immutable graph classes
- Added comprehensive tests demonstrating the fix works for both empty
  and non-empty graphs
- Applied changes to both JRE and Android versions

Fixes google#3909
Enhancements:
- Created ImmutableGraphTest (was missing) with 22 test methods
- Added tests for clear() operations on all Set-returning methods
- Added tests for Iterator.remove() operations
- Enhanced existing ImmutableValueGraphTest and ImmutableNetworkTest

All tests verify UnsupportedOperationException is thrown consistently
for various mutation attempts (add, remove, clear, iterator.remove).

Applied to both JRE and Android test modules.
@jrtom
Copy link
Contributor

jrtom commented Nov 25, 2025

See my comment on the original issue for my thoughts on this.

@stevearmstrong-dev
Copy link
Author

@jrtom Got it - since all graph implementations rely on unmodifiable view Sets to maintain internal consistency, the fix needs to extend beyond just Immutable* classes. I'll update
StandardMutable*, Forwarding*, and abstract base classes to ensure consistent UOE behavior throughout. Appreciate the clarification!

@jrtom
Copy link
Contributor

jrtom commented Nov 25, 2025

@stevearmstrong-dev I should clarify, before you invest more time in this: someone at Google (first candidates: @netdpb or @cpovirk) should sign off on this proposed solution. While I'm certainly an interested party in common.graph (having originated it), and I expect David and Chris to give my opinions regarding it some weight, I no longer have the authority to approve changes to it, as I'm no longer a member of the GitHub "Google" organization.

That said: while it would add a small bit of overhead, I don't think that it would harm anything to make this change across the board, and it might keep someone from making an unfortunate error down the line. So I would approve it if it were up to me. :)

I'll also note that this behavior is arguably implied by this statement in GraphsExplained:

Accessors which return collections return unmodifiable views of the graph

@stevearmstrong-dev
Copy link
Author

Thankyou @jrtom for the heads up. I'll keep track of this for further updates from the team.

@cpovirk
Copy link
Member

cpovirk commented Nov 25, 2025

This does seem reasonable. I forget if even the Collections.unmodifiable* collections are as good about always throwing UOE for mutation operations (e.g., if you call removeAll(emptyCollection)), though that may have improved in recent years. Even if they're not perfect, I'm not sure we'd want to go to the effort to do something perfect.

I am fairly swamped right now but will put this on The List.

@cpovirk cpovirk added type=enhancement Make an existing feature better package=graph P3 no SLO labels Nov 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 no SLO package=graph type=enhancement Make an existing feature better

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Graphs: immutable/unmodifiable operations should consistently throw UOE whether or not data would actually change

3 participants