Focusing too much on the call site is probably misleading, which is why most production-quality immediate-mode UI libraries generally don't rely on __FILE__/__LINE or stack walks or anything else like that. The issue isn't just loops. As soon as you wrap code in a function for reuse, the proximate call site no longer has anything to do with the widget ID; in the extreme case, your entire immediate-mode UI is data driven and there's nothing in the code paths that indicate anything at all about the widget IDs.
The real hack is implicit IDs, not the ID stack (which is just a way of implementing a hierarchical namespace like file system paths or URLs). Implicit IDs just work 99% of the time and rarely require manual intervention, so seeking a 100% solution is a tempting siren song. But once you actually start writing UIs like this, the 99% solution is just fine.
> As soon as you wrap code in a function for reuse, the proximate call site no longer has anything to do with the widget ID.
That's a good point.
(a) hash the entire call stack (though that might produce false negatives, i.e. consider two UI elements that should be the same distinct?)?
(b) put the burden on the reusable function to mark itself as such by pushing/popping an identifier of its own call site on the ID stack?
> The real hack is implicit IDs, not the ID stack (which is just a way of implementing a hierarchical namespace like file system paths or URLs). The fact that implicit IDs just work 99% of the time and only require manual intervention 1% of the time is a false siren song into letting you believe a 100% solution is desirable (you have to consider the marginal cost of what it would entail).
Well, this is just the standard problem of library design, isn't it? You always have to figure out the appropriate tradeoff between supporting rare cases and making common ones easy. (Of course, you can often do both; in this case, you probably could both give "explicit ID" and "call site ID" versions of each UI element API.)
Yeah, a mixture of implicit and explicit IDs is fine and what everyone does in one form or another. That's what I had in mind as the 99% solution. You don't want the default implicit ID scheme to be too clever or opaque so the programmer can easily diagnose what went wrong when it inevitably does. I was just cautioning against relying too much on ever fancier implicit schemes because of those failure modes; I went down that path a few times when I first started experimenting with immediate-mode UIs years ago.
The real hack is implicit IDs, not the ID stack (which is just a way of implementing a hierarchical namespace like file system paths or URLs). Implicit IDs just work 99% of the time and rarely require manual intervention, so seeking a 100% solution is a tempting siren song. But once you actually start writing UIs like this, the 99% solution is just fine.