ID:1996036
 
(See the best response by Lummox JR.)
Code:
    getRefs(var/datum/D)
. = new/list()
var/count = 0
var/list/searched = new/list()
for(var/datum/D2)
searched += D2
for(var/v in D2.vars)
if("[v]" == "vars")continue
if(D2.vars[v] == D)
count ++
.["[count]: [D2]"] = "[v]"
else if(istype(D2.vars[v],/list))
for(var/v2 in D2.vars[v])
if(v2 == D || D2.vars[v][v2] == D)
count ++
.["[count]: [D2]"] = "[v]"

//Found not-in-world datums, now lets find atoms, or anything else weird.
for(var/datum/D2 in world)
if(D2 in searched)continue
searched += D2
for(var/v in D2.vars)
if("[v]" == "vars")continue
if(D2.vars[v] == D)
count ++
.["[count]: [D2]"] = "[v]"
/*
else if(istype(D2.vars[v],/list))
var/list/L = D2.vars[v]
for(var/v2 in L)
if(!(v2 in L))continue
if(v2 == D || L[v2] == D) //I get a bad index error here for some reason
count ++
.["[count]: [D2]"] = "[v]"
*/


Problem description:

Creating a *cough* feasible refList() but for some reason I get a bad index error here.
Using try/catch reveals its the lists verbs and contents etc it can't search through. I understand why it's impractical to search through verbs, but why can't I look through the contents?
Best response
For performance you should assign D.vars[v] to a proc var right away, so that you can refer to it later without having to use the same expression over and over.

You're getting "bad index" because not all of the lists you're looking at are associative, and also v2 may be a number in which case D.vars[v][v2] could potentially be out of bounds. Also, that OR test is incorrect, because you're testing whether the item or the associated value == D, but you're not testing both separately.
I should also add the if(D2 in searched) test is going to get progressively worse for you, since you have to search through the entire list sequentially. An associative list would work better. You also need to account for the reference possibly being in that list (which is why I described it as a thorny problem), to say nothing of global vars and lists.
Right, is there any way at runtime of checking if a list is associative or not? For the most part this works, but I'd really like to be able to catch contents.
You could use \ref to check if the list is a user list type, but that gets expensive really quick.
Right. Well until I get the recursion working, this'll have to do for now

    getRefs(var/datum/D)
. = new/list()
var/count = 0
var/list/searched = new/list()
for(var/datum/D2)
searched += D2
for(var/v in D2.vars)
if("[v]" == "vars")continue
if(D2.vars[v] == D)
count ++
.["[count]: [D2]"] = "[v]"
else if(istype(D2.vars[v],/list))
for(var/v2 in D2.vars[v])
if(v2 == D || D2.vars[v][v2] == D)
count ++
.["[count]: [D2]"] = "[v]"

//Found not-in-world datums, now lets find atoms, or anything else weird.
for(var/datum/D2 in world)
if(D2 in searched)continue
searched += D2
for(var/v in D2.vars)
if("[v]" == "vars")continue
if(D2.vars[v] == D)
count ++
.["[count]: [D2]"] = "[v]"

else if(istype(D2.vars[v],/list))
var/list/L = D2.vars[v]
for(var/v2 in L)
if(v2 == D)
count ++
.["[count]: [D2]"] = "[v]"



It catches contents, so it basically does what I want, but it doesn't do recursion inside of lists, which I was going to use this for

    getRefsListCheck(var/datum/D2,var/list/_list,var/datum/D,var/checkAssoc = 1)
. = new/list()
var/count = 0
for(var/v in _list)
if(v == "vars")continue
if(v == D ||_list[v] == D)
count ++
if(_list == "vars").["[D2] - [count]"] = "[v]"
else .["[D2] (List Var) - [count]"] = "[v]"
else if(istype(_list[v],/list))
. += getRefsListCheck(D2,v,D,checkAssoc)


But this has its own slew of problems and when you're using this is where the lag REALLY starts to kick in, talking 20 second hang when you use this.
In response to Lummox JR
Lummox JR wrote:
You also need to account for the reference possibly being in that list (which is why I described it as a thorny problem), to say nothing of global vars and lists.

Actually since world isn't a datum, and this proc is defined under world, and searched isn't a global, it won't get caught by this.