Closed ScottCarda-MS closed 4 years ago
The related runtime issue to remove this circuit is found here: https://github.com/microsoft/qsharp-runtime/issues/343
If this bug is fixed, would
function GenRecursionPartial<'T>(x : 'T, cnt : Int) : 'T {
if (cnt == 0) {
return x;
}
else {
let fct = GenRecursionPartial<'T>(_, cnt - 1);
return fct(x);
}
}
still be a valid program?
@samarsha No it would not. The linked issue for in the runtime repo is for removing that test case.
My example is different from that test case: it adds a <'T>
after the second GenRecursionPartial
.
My example is different from that test case: it adds a
<'T>
after the secondGenRecursionPartial
.
Oh sorry I didn't notice that it was different. Yes your example would work fine, as the 'T
in that context could only refer to the calling context's GenRecursionPartial.T
.
@ScottCarda-MS The issue has nothing to do with the representation - it is merely a bug in the implementation (I simply forgot). https://github.com/microsoft/qsharp-compiler/pull/576 contains the fix.
In the runtime repo, there is a circuit defined as follows:
This circuit shouldn't be allowed because we don't support capturing unresolved generic references. The
fct
is doing exactly that by capturing the recursive call omitting the argument that would have resolved its type parameter. After having captured this generic, one would now expect to be able to do:But of course this is not allowed as we don't handle captured generics like this in the language.
The reason this is happening is because of the ambiguity in the data structure that represents the type parameter resolution, and the way we represent an unresolved type parameter. The data structure only contains the name of the callable to which the type parameter belongs, the name of the type parameter, and the resolving type. This is not enough information to be able to determine which instance of the type parameter is being resolved. In this case the compiler is getting confused because it can't tell the difference between a reference to the context's
GenRecursionPartial.T
and a reference to the recursive call'sGenRecursionPartial.T
.The way unresolved type parameters are represented is that the type parameter is shown to resolve to itself, i.e.
Foo.T -> Foo.T
means thatFoo.T
is unresolved. In this case, however theGenRecursionPartial.T -> GenRecursionPartial.T
, which is supposed to indicate thatGenRecursionPartial.T
is unresolved is mistakenly being interpreted as the call'sGenRecursionPartial.T
being resolved to the context'sGenRecursionPartial.T
, which is not the case. This is causing the definition offct
to be incorrectly resolved without the appropriate error.