"I intentionally avoid retaining self because the Task is meant to be canceled as soon as the ViewModel is deallocated."
As pointed out, the Task will be queued and then immediately executed on MainActor, whereupon you immediately `guard self`, undoing the weak self just as if you'd never done it in the first place.
From that point forward, self is strong. The call to "doSomething" occurs after that point and it doesn't matter how long it takes, you already have a strong self retention.
The VM can't be deallocated. (Disregarding the stream issue.)