There appears to be a bug in how the opaque attribute affects functions that return tuples. In the example below, when Hidden is marked opaque, the first lemma "foo", succeeds when the assertion is an exact match, but bar and baz, which try to do the comparison based on the individual components, fails. I've duplicated the module twice, to show that these examples work when the function is not opaque and when the function is made "effectively opaque" via a fuel setting.
[Example:](http://rise4fun.com/Dafny/GcOpt)
```
module ModOpaque {
function {:opaque} Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
module ModVisible {
function Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
module ModFuel {
function {:fuel 0,0} Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
```
[Example:](http://rise4fun.com/Dafny/GcOpt)
```
module ModOpaque {
function {:opaque} Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
module ModVisible {
function Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
module ModFuel {
function {:fuel 0,0} Hidden(x:int) : (int, int)
{
(5, 7)
}
function Visible(x:int) : (int, int)
{
Hidden(x)
}
lemma foo(x:int, y:int, z:int)
requires (y, z) == Visible(x);
{
assert (y, z) == Hidden(x);
}
lemma bar(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Visible(x);
}
lemma baz(x:int, y:int, z:int)
requires y == Visible(x).0;
requires z == Visible(x).1;
{
assert (y, z) == Hidden(x);
}
}
```