Missing compile warning

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Missing compile warning

tom kelly-2
Hi List,

Here's a stripped down & renamed version of some code I just copied from
our system. I may have been staring at this for too long but I've convinced
myself that the second function clause in both of these functions can never
be executed because they are both covered by the first function clause:


-module(no_warn).
-compile(export_all).

-record(my_rec,{field1, field2}).

my_function1(#my_rec{field1 = {tag, _}, field2 = f2}) -> 1;
my_function1(#my_rec{field1 = {tag, 1}, field2 = f2}) -> 2; % line 7
my_function1(_) -> 3.

my_function2(#my_rec{field1 = {tag, _}}) -> 1;
my_function2(#my_rec{field1 = {tag, 1}}) -> 2; % line11
my_function2(_) -> 3.


Except, that when I compile this (R16B03-1) the compiler only warns me
about one of them:


no_warn.erl:11: Warning: this clause cannot match because a previous clause
at line 10 always matches


Surely line 7 should give an identical warning? Or do I need to go lie down
for a little while?

//TTom.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140228/8f4df0fc/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Vlad Dumitrescu-5
Hi!

On Fri, Feb 28, 2014 at 7:54 PM, tom kelly <ttom.kelly> wrote:

> -module(no_warn).
> -compile(export_all).
>
> -record(my_rec,{field1, field2}).
>
> my_function1(#my_rec{field1 = {tag, _}, field2 = f2}) -> 1;
> my_function1(#my_rec{field1 = {tag, 1}, field2 = f2}) -> 2; % line 7
> my_function1(_) -> 3.
>
> my_function2(#my_rec{field1 = {tag, _}}) -> 1;
> my_function2(#my_rec{field1 = {tag, 1}}) -> 2; % line11
> my_function2(_) -> 3.
>

Looks like a bug to me, especially since changing the first clause to
my_function1(#my_rec{field1 = {tag, _}, field2 = _}) -> 1;
gives a warning for the first function too.

regards,
Vlad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140228/d5cf05f5/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Björn Gustavsson-3
On Fri, Feb 28, 2014 at 10:08 PM, Vlad Dumitrescu <vladdu55> wrote:

> Hi!
>
> On Fri, Feb 28, 2014 at 7:54 PM, tom kelly <ttom.kelly> wrote:
>>
>> -module(no_warn).
>> -compile(export_all).
>>
>> -record(my_rec,{field1, field2}).
>>
>> my_function1(#my_rec{field1 = {tag, _}, field2 = f2}) -> 1;
>> my_function1(#my_rec{field1 = {tag, 1}, field2 = f2}) -> 2; % line 7
>> my_function1(_) -> 3.
>>
>> my_function2(#my_rec{field1 = {tag, _}}) -> 1;
>> my_function2(#my_rec{field1 = {tag, 1}}) -> 2; % line11
>> my_function2(_) -> 3.
>
>
> Looks like a bug to me, especially since changing the first clause to
> my_function1(#my_rec{field1 = {tag, _}, field2 = _}) -> 1;
> gives a warning for the first function too.
>

It is perhaps a documentation bug.

Some warnings can be trusted 100 per cent.
For example, if there are no warnigs for unused variables
there are no unused variables.

The absence of warnings for clauses that
don't match does *not* mean that that all clauses
can be matched. It merely means that
the compiler (during optimisation and
pattern matching compilation) did not find
any clauses that obviously would not be
reached.

/Bjorn


--
Bj?rn Gustavsson, Erlang/OTP, Ericsson AB

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Vlad Dumitrescu-5
On Mon, Mar 3, 2014 at 5:49 PM, Bj?rn Gustavsson <bjorn> wrote:

> > On Fri, Feb 28, 2014 at 7:54 PM, tom kelly <ttom.kelly> wrote:
> >>
> >> -module(no_warn).
> >> -compile(export_all).
> >>
> >> -record(my_rec,{field1, field2}).
> >>
> >> my_function1(#my_rec{field1 = {tag, _}, field2 = f2}) -> 1;
> >> my_function1(#my_rec{field1 = {tag, 1}, field2 = f2}) -> 2; % line 7
> >> my_function1(_) -> 3.
> >>
> >> my_function2(#my_rec{field1 = {tag, _}}) -> 1;
> >> my_function2(#my_rec{field1 = {tag, 1}}) -> 2; % line11
> >> my_function2(_) -> 3.
>
> It is perhaps a documentation bug.
>
> Some warnings can be trusted 100 per cent.
> For example, if there are no warnigs for unused variables
> there are no unused variables.
>
> The absence of warnings for clauses that
> don't match does *not* mean that that all clauses
> can be matched. It merely means that
> the compiler (during optimisation and
> pattern matching compilation) did not find
> any clauses that obviously would not be
> reached.
>
>
Hi,

I'm not sure if I can agree with this. Non-matchable clauses should in my
opinion be marked as errors, because they expose a logical flaw (usually a
misordering of the clauses), and in this case I would have them be 100%
accurate.

Given clauses without guards like f(A)->ok; f(B)->ok. then I think we
should get a warning/error if B is the same as or more specific than A.
This probably applies when there are guards too. If that's the case, it
shouldn't be too difficult to implement.

What am I missing? Is it difficult just because it is done after some
optimization passes that might mess things up? Or is there some other issue?

best regards,
Vlad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140303/f007f333/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Björn Gustavsson-3
On Mon, Mar 3, 2014 at 6:16 PM, Vlad Dumitrescu <vladdu55> wrote:

> What am I missing? Is it difficult just because it is done after some
> optimization passes that might mess things up? Or is there some other issue?

I don't know how difficult it would be. The
warnings for unreachable clauses are there
because they are easy to emit when clauses
are discarded during optimisation and pattern
matching compilation. We have not really
looked at the problem of finding all unreachable
clauses; depending on how hard the problem
is, it might be more suitable to let Dialyzer do
it.

/Bjorn

--
Bj?rn Gustavsson, Erlang/OTP, Ericsson AB

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Vlad Dumitrescu-5
On Mon, Mar 3, 2014 at 6:37 PM, Bj?rn Gustavsson <bjorn> wrote:

> On Mon, Mar 3, 2014 at 6:16 PM, Vlad Dumitrescu <vladdu55>
> wrote:
>
> > What am I missing? Is it difficult just because it is done after some
> > optimization passes that might mess things up? Or is there some other
> issue?
>
> I don't know how difficult it would be. The
> warnings for unreachable clauses are there
> because they are easy to emit when clauses
> are discarded during optimisation and pattern
> matching compilation. We have not really
> looked at the problem of finding all unreachable
> clauses; depending on how hard the problem
> is, it might be more suitable to let Dialyzer do
> it.


I see. I would like to make a case for including this on the list of
improvements. To me it is important to be able to rely on this
warning/error - it saved me in several occasions.

What other warnings have less than 100% coverage?

/Vlad
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140303/9e3901de/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Erik Søe Sørensen-3
In reply to this post by Vlad Dumitrescu-5
As for including guards, it is not possible to warn about all cases where a
clause cannot be matched.

Consider:
f (X, Y, Z) when X*X*X+Y*Y*Y==Z*Z*Z, is_integer(X), is_integer(Y),
is_integer(Z), X>0, Y>0, Z>0 ->
... you get the picture. :)

Linear patterns would be doable.
Non-linear patterns perhaps too, but probably less straightforward.
Den 03/03/2014 18.16 skrev "Vlad Dumitrescu" <vladdu55>:

> On Mon, Mar 3, 2014 at 5:49 PM, Bj?rn Gustavsson <bjorn> wrote:
>
>> > On Fri, Feb 28, 2014 at 7:54 PM, tom kelly <ttom.kelly>
>> wrote:
>> >>
>> >> -module(no_warn).
>> >> -compile(export_all).
>> >>
>> >> -record(my_rec,{field1, field2}).
>> >>
>> >> my_function1(#my_rec{field1 = {tag, _}, field2 = f2}) -> 1;
>> >> my_function1(#my_rec{field1 = {tag, 1}, field2 = f2}) -> 2; % line 7
>> >> my_function1(_) -> 3.
>> >>
>> >> my_function2(#my_rec{field1 = {tag, _}}) -> 1;
>> >> my_function2(#my_rec{field1 = {tag, 1}}) -> 2; % line11
>> >> my_function2(_) -> 3.
>>
>> It is perhaps a documentation bug.
>>
>> Some warnings can be trusted 100 per cent.
>> For example, if there are no warnigs for unused variables
>> there are no unused variables.
>>
>> The absence of warnings for clauses that
>> don't match does *not* mean that that all clauses
>> can be matched. It merely means that
>> the compiler (during optimisation and
>> pattern matching compilation) did not find
>> any clauses that obviously would not be
>> reached.
>>
>>
> Hi,
>
> I'm not sure if I can agree with this. Non-matchable clauses should in my
> opinion be marked as errors, because they expose a logical flaw (usually a
> misordering of the clauses), and in this case I would have them be 100%
> accurate.
>
> Given clauses without guards like f(A)->ok; f(B)->ok. then I think we
> should get a warning/error if B is the same as or more specific than A.
> This probably applies when there are guards too. If that's the case, it
> shouldn't be too difficult to implement.
>
> What am I missing? Is it difficult just because it is done after some
> optimization passes that might mess things up? Or is there some other issue?
>
> best regards,
> Vlad
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20140303/33299c33/attachment.html>

Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Richard A. O'Keefe
In reply to this post by Vlad Dumitrescu-5

On 4/03/2014, at 6:16 AM, Vlad Dumitrescu wrote:
>
> I'm not sure if I can agree with this. Non-matchable clauses should in my opinion be marked as errors, because they expose a logical flaw (usually a misordering of the clauses), and in this case I would have them be 100% accurate.

Consider a function with two clauses.

        f(X, ...) when G1 -> B1;
        f(X, ...) when G2 -> B2.
 
where X, ... stands for the same sequence of distinct
variables in both clauses.

The second clause is unmatchable iff G1 and G2 are
equivalent.  Now G1 and G2 may contain arithmetic
expressions, let's say they are E1 > 0 and E2 > 0
respectively.

If memory serves me correctly, determining whether
two arbitrary arithmetic expressions are equal is
unsolvable.

If I'm wrong about that, let G1 and G2 be Boolean
expressions.  Determining whether G1 and G2 are
equivalent is then the standard NP-complete problem.

There are clearly going to be some special cases
that can be handled:  guards that are pure
conjunctions (,) of type tests and
Variable Relop Constant should be doable, for example.

It might be an interesting research project for someone
to determine the exact complexity of determining when
one Erlang guard implies another.

If user-defined guards were ever admitted into Erlang
the task would become obviously impossible.




Reply | Threaded
Open this post in threaded view
|

Missing compile warning

Björn Gustavsson-3
In reply to this post by Vlad Dumitrescu-5
On Mon, Mar 3, 2014 at 6:50 PM, Vlad Dumitrescu <vladdu55> wrote:
>
> What other warnings have less than 100% coverage?

Warnings for arithmetic expressions that will fail such as
x+42 and 1/0. Guards that will always fail.

Those warnings are emitted when the optimiser tries
to evaluate expressions at compile time. So although
there will be a warning for 1/0, there will be no warning
for X/0.

There is some documentation about this, at the end
of the description of compile:file/2:

http://www.erlang.org/doc/man/compile.html

/Bjorn

--
Bj?rn Gustavsson, Erlang/OTP, Ericsson AB