As a Roblox developer, it is currently too hard to debug code that gives IsDescendantOf() a nil value. This is because, intuitively, I would expect the method to throw an error if given the wrong type. Instead, it simply returns true for every object, leading me to second-guess other parts of my codebase that are not the culprit.
This behavior is documented so it is presumably intentional, but it is so unintuitive I initially assumed it was a bug and filed a bug report:
If this behavior is not intentionally relied upon by any games (which I assume to be the case since a statement that returns “true” 100% of the time is effectively worthless) I recommend it be changed to throw an error.
If Roblox is able to address this issue, it would improve my development experience because I’d be able to catch mistakes I make with IsDescendantOf() much faster.
I suppose it’s because that behavior wouldn’t technically be correct, since theoretically all objects are indeed a descendant of nil. We also already have that not x:IsDescendantOf(game) expression if we want to check if an object is in the datamodel, so an equivalent to that wouldn’t serve much purpose. Considering all that, I think throwing an error is the best case because it’s the most useful to the developer.
the type annotation of IsDescendantOf implies that IsDescendantOf always expects an Instance, nil is obviously not of type Instance so it should just error with something like “Argument 1 missing or nil”.
I disagree, because objects can be children and descendants of nil, if nil is their Parent. Come to think of it, that’s probably why that method returns true - something up in the Instance tree (the DataModel iirc?) has a nil parent.
However, nil has a different meaning when it comes to instances. Usually it’s associated with destroyed or removed instances. This is why for me, it’s intuitive that nil is treated as a separate entity, so x:IsDescendantOf(nil) returns true only if x.Parent == nil.
Both my and your proposals would probably break a huge number of games though, so I don’t expect a change to be made here.
an easier way to catch this is by using t a runtime type checker library, as i don’t think it is worth changing behavior of this
i think the problem here is due to lack of knowledge, by knowing that nil is a parent of game you’d understand that it is correct behavior, though i agree that it is not intuitive
I believe IsDescendantOf(nil) returning true is the proper and correct logic. A Parent can either be an Instance, or it can be nil. At a certain point in the ancestry, every object is a descendant of nil; and so the current implementation makes perfect sense.
This method has existed since the dawn of the API. Altering it now, to start rejecting nil inputs, would be a breaking change for countless algorithms. Consider if a scripter wanted to treat a variable Instance as a blacklist. They might thereby write:
if not Object:IsDescendantOf(Blacklist) then
-- Only if Blacklist has been defined, and Object is not a part of it
end
In these cases, doing nothing until Blacklist has been defined–or otherwise intentionally setting Blacklist to nil as a means of excluding everything, may be entirely desirable.