Rework task dependency inference so that `Provider` implementations use the same `TaskDependencyContainer` interface that most other things use to declare their producer task to the task resolution infrastructure, rather than having special knowledge sprinkled around various places. Cleaned up a bunch of `Provider` and `Property` implementations so that more logic is reused rather than reimplemented.
Support propagation of the producer task for provider instances that are created using `Provider.map()`. Now, when a provider represents a task or task output, whether mapped or not, that task is taken as the producer of the value and the mapping function is not called. Otherwise, the value of the provider is unpacked and resolved, as it previously was.
Rework the protocol by which providers communicate their build dependencies to consumers.