# HG changeset patch
# User Nils Bruin
# Date 1361747496 28800
# Node ID ebbbaa0cf36900a1c214527592489a4021547b0c
# Parent 364089bc94692df23b65eda676e99929fdb4b93e
#14159: Document that we're introducing a possible memory leak to save writing a very complicated callback. If this proves to be a problem, we'll know what to do
diff git a/sage/categories/homset.py b/sage/categories/homset.py
 a/sage/categories/homset.py
+++ b/sage/categories/homset.py
@@ 220,9 +220,11 @@ def Hom(X, Y, category=None):
except KeyError:
H = None
if H is not None:
 # Are domain or codomain breaking the unique parent condition?
 if H.domain() is X and H.codomain() is Y:
 return H
+ # Note H has just been found using the identities of X and Y as
+ # keys, so if the domain and codomain of H do not match by identity
+ # something went wrong and we want to know about it.
+ assert H.domain() is X and H.codomain() is Y
+ return H
try:
# Apparently X._Hom_ is supposed to be cached
@@ 248,9 +250,9 @@ def Hom(X, Y, category=None):
except KeyError:
H = None
if H is not None:
 # Are domain or codomain breaking the unique parent condition?
 if H.domain() is X and H.codomain() is Y:
 return H
+ # We double check domain and codomain are expected (see above)
+ assert H.domain() is X and H.codomain() is Y
+ return H
# coercing would be incredibly annoying, since the domain and codomain
# are totally different objects
@@ 261,9 +263,19 @@ def Hom(X, Y, category=None):
# For the moment, this is the category, for compatibility with the current implementations
# of Homset in rings, schemes, ...
H = category.hom_category().parent_class(X, Y, category = category)

+
+ #Since H is holding strong references to X,Y,category in the form of
+ #H.domain(), H.codomain(), H.homset_category(), the keyed reference below
+ #should be OK: Even though X,Y,category are only weakly referenced by
+ # _cache, they can't be garbage unless H is as well.
+ #(the callback below isn't safe if _cache[key] would be able to get a
+ #different value because H gets deallocated).
+ #However, just to be safe, we prefer to risk leaving a dead reference
+ #in _cache for now. Should this prove problematic in the future, we
+ #can revisit this and equip the weak reference to H with a suitable callback
+ #see trac #14159
+ #_cache[key] = KeyedRef(H, _cache.eraser, (id(X),id(Y),id(category)))
_cache[key] = ref(H)
 ##_cache[key] = KeyedRef(H, _cache.eraser, (id(X),id(Y),id(category)))
return H
def hom(X, Y, f):