Builds on #221, because the changes to the OccursCheck error variant would conflict with it if I PR'd it separately. But this is conceptually independent of #221.
Our old occurs-check loop would use the pre-order iterator from dag.rs with the NoSharing adaptor. This would iterate over the full explicit type, which may have exponential size in the program length. The correct algorithm notices when it is done checking a type bound and all its children, and does not check that bound again.
I wasn't able to produce a test vector showing the exponential-time behavior of the old algorithm, but I am hitting this issue in a fuzzing project I'm working on locally, and I think it's clear from the diff what the issue is and how this change fixes it.
Builds on #221, because the changes to the
OccursCheck
error variant would conflict with it if I PR'd it separately. But this is conceptually independent of #221.Our old occurs-check loop would use the pre-order iterator from dag.rs with the
NoSharing
adaptor. This would iterate over the full explicit type, which may have exponential size in the program length. The correct algorithm notices when it is done checking a type bound and all its children, and does not check that bound again.I wasn't able to produce a test vector showing the exponential-time behavior of the old algorithm, but I am hitting this issue in a fuzzing project I'm working on locally, and I think it's clear from the diff what the issue is and how this change fixes it.