Propagate per-instance fields through slice operations in the Python front-end
#359 opened on Apr 14, 2026
Repository metrics
- Stars
- (27 stars)
- PR merge metrics
- (PR metrics pending)
Description
Problem
WALA Python's loader produces a fresh InstanceKey for the result of a slice expression (x[a:b], x[..., None], x[i], etc.) that does not inherit the per-instance fields of the receiver. This breaks the "class-per-function" dispatch pattern used by XML summaries (see e.g., tensorflow/data/Dataset method chains in tensorflow.xml) as soon as a user inserts a slice in the middle of a method chain.
Concrete symptom from wala/ML#356: in the GAN tutorial reproducer
train_images = train_images[..., None].astype(np.float32)
the .astype(np.float32) call's receiver is the slice result, which has no astype field even when we put one on the pre-slice receiver. So the .astype(...) call falls back to the generic <PythonLoader,LCodeBody> dispatch target instead of resolving to Lnumpy/ndarray/astype.
The ML analysis currently sidesteps this with a duck-typing fallback in TensorGeneratorFactory (see dispatchByPropertyName / PROPERTY_NAME_GENERATORS) that matches on the property-read member name regardless of the receiver's tracked fields. That's sound for Python semantics but doesn't leverage the XML modeling work, and it has to be extended by hand for every new instance method we want to dispatch.
The underlying gap
WALA fields are keyed by (InstanceKey, FieldReference). A slice result has a distinct allocation site from its source, so it gets a distinct instance key. There's no automatic field inheritance. For the Dataset chain to work, every Dataset method's XML summary explicitly inlines a <new> and re-populates all the method fields (see the "duplicated intentionally" comment in tensorflow/data/shuffle.do in tensorflow.xml). That pattern works because every link in the chain is an XML-summarized method — slice expressions are not summarized anywhere, so there's no place to re-populate the fields.
Three implementation approaches
1. Copy fields at slice time
When the loader produces a slice result instance key, iterate the receiver's fields and add (sliceResult, field) -> receiverValue to the heap graph for every field the receiver has.
Pros: Conceptually simple, preserves existing allocation-site semantics (distinct instance keys).
Cons: Expensive if receivers have many fields. Requires iterating the heap graph's field schema at loader time. May not interact well with lazy/incremental pointer analysis.
2. Proxy lookup
Field access on a slice result falls back to the source's fields when a direct lookup misses. Effectively adds an "inheritance" edge in the heap model between the slice result's instance key and its source.
Pros: No enumeration, no eager copy. Only touches the read path.
Cons: Requires a new mechanism in the heap model (or at least in the points-to lookup logic). Could interact surprisingly with cycles or deeply-nested slices.
3. Share instance-key identity
The slice result reuses the same allocation site (and hence the same instance key) as its source — i.e., slicing is treated as an identity operation at the heap level, even though it's a new SSA value.
Pros: Cheapest; no new mechanism at all. Slice results automatically inherit every field via identity.
Cons: Semantic change. Analyses that rely on distinct allocation sites for distinct SSA values (e.g., shape inference that tracks x[..., None] as a different shape from x) would break. Probably breaks the existing SliceOperation generator which computes new shapes from the slice arguments.
Recommended next step
Before picking an approach, do a short spike into com.ibm.wala.cast.python.loader and the CAst translation for PythonPropertyRead / slice syntax:
- Where in the loader does the slice result's allocation site get created? (Identify the exact file / method.)
- What's the existing pattern for passing receiver metadata to the slice result?
- Do other languages' WALA front-ends have an analogous mechanism?
- Is there a WALA-level concept of "field inheritance" across instance keys already?
That spike should produce either a small targeted PR implementing one of the three options above, or a well-informed "this is harder than it looks, here's why" writeup that feeds back into this issue. Budget: half a day.
Tests affected
testGanTutorial, testGanTutorial2, and testModelCallConsume (wala/ML#358's reproducer) are the most direct beneficiaries. The testAutoencoder* / testNeuralNetwork* / testTensorboardExample / testEagerExecution families probably also benefit to varying degrees — any test whose Keras/numpy code includes slice operations on tensors.
Related
- wala/ML#267 (parent — initial tensor shapes not always accurate).
- wala/ML#356 (shape/dtype through Python binop chains feeding
from_tensor_slices). - wala/ML#358 (
testModelCallminimal reproducer — symptom of the same class of problem). - ponder-lab/ML commit
df0ceb56(adds the duck-typing fallback and thePROPERTY_NAME_GENERATORSregistry as a workaround).