Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #31135 > unrolled thread

ensuring unreachability

Started byAndreas Leitgeb <avl@auth.logic.tuwien.ac.at>
First post2015-02-17 09:54 +0000
Last post2015-02-18 00:59 +0000
Articles 17 — 10 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  ensuring unreachability Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> - 2015-02-17 09:54 +0000
    Re: ensuring unreachability Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-02-17 08:23 -0500
    Re: ensuring unreachability Leif Roar Moldskred <leifm@huldreskog.localdomain> - 2015-02-17 13:54 -0600
    Re: ensuring unreachability Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-02-17 15:51 -0500
      Re: ensuring unreachability Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> - 2015-02-18 00:40 +0000
        Re: ensuring unreachability Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-02-18 08:49 -0500
          Re: ensuring unreachability Jukka Lahtinen <jtfjdehf@hotmail.com.invalid> - 2015-02-18 16:40 +0200
            Re: ensuring unreachability Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-02-18 10:16 -0500
              Re: ensuring unreachability Jerry Stuckle <jstucklex@attglobal.net> - 2015-02-18 11:02 -0500
                Re: ensuring unreachability Robbie Brown <rob@example.com> - 2015-02-19 09:48 +0000
                  Re: ensuring unreachability Gene Wirchenko <genew@telus.net> - 2015-02-20 09:39 -0800
                Re: ensuring unreachability Robbie Brown <rob@example.com> - 2015-02-19 09:50 +0000
                Re: ensuring unreachability v_borchert@despammed.com (Volker Borchert) - 2015-02-19 18:20 +0000
                  Re: ensuring unreachability Jerry Stuckle <jstucklex@attglobal.net> - 2015-02-19 15:24 -0500
          Re: ensuring unreachability Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> - 2015-02-19 01:28 +0000
    Re: ensuring unreachability Arne Vajhøj <arne@vajhoej.dk> - 2015-02-17 18:49 -0500
    Re: ensuring unreachability Martin Gregorie <martin@address-in-sig.invalid> - 2015-02-18 00:59 +0000

#31135 — ensuring unreachability

FromAndreas Leitgeb <avl@auth.logic.tuwien.ac.at>
Date2015-02-17 09:54 +0000
Subjectensuring unreachability
Message-ID<slrnme63vm.uoi.avl@login.logic.tuwien.ac.at>
Recently I came across a snippet like this:
  switch (someEnumVar) {
    case E1:
      if (...) {
        ...; return;
      } else if (...) {
        ...; throw ...;
      } else {
        ...; continue; // enclosing loop
      }
    case E2: ...
  }

No fall-through is supposed to ever happen from case E1 to case E2.
All branches in "case E1" exit abnormally. But due to the complexity
it isn't overly obvious. Lateron, someone might add another else-if
branch and forget about having it exit abnormally, then it might just
happen that it does fall through, which in the given context is never
ever wanted.

What I'd like to do is set a marker just before case E2.

Obviously, I cannot place any normal statement, because the compiler
would recognize it as unreachable and barf. So, I'd like to have some
kind of anti-statement, that's ok to be unreachable, but would make the
compiler barf if it ever *became* reachable during later development.

PS:
The whole point of this question is about *compile-time* checks.

[toc] | [next] | [standalone]


#31138

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-02-17 08:23 -0500
Message-ID<mbvfbp$cq1$1@dont-email.me>
In reply to#31135
On 2/17/2015 4:54 AM, Andreas Leitgeb wrote:
> Recently I came across a snippet like this:
>    switch (someEnumVar) {
>      case E1:
>        if (...) {
>          ...; return;
>        } else if (...) {
>          ...; throw ...;
>        } else {
>          ...; continue; // enclosing loop
>        }
>      case E2: ...
>    }
>
> No fall-through is supposed to ever happen from case E1 to case E2.
> All branches in "case E1" exit abnormally. But due to the complexity
> it isn't overly obvious. Lateron, someone might add another else-if
> branch and forget about having it exit abnormally, then it might just
> happen that it does fall through, which in the given context is never
> ever wanted.
>
> What I'd like to do is set a marker just before case E2.
>
> Obviously, I cannot place any normal statement, because the compiler
> would recognize it as unreachable and barf. So, I'd like to have some
> kind of anti-statement, that's ok to be unreachable, but would make the
> compiler barf if it ever *became* reachable during later development.

     I'd suggest deleting the final `else' and its brackets:

	case E1:
	   if (...) {
	      ...; return;
	   } else if (...) {
	      ...; throw ...;
	   }
	   ...;
	   continue;
	case E2: ...

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31139

FromLeif Roar Moldskred <leifm@huldreskog.localdomain>
Date2015-02-17 13:54 -0600
Message-ID<9eKdnVlXnYj1AX7JnZ2dnUVZ8vWdnZ2d@giganews.com>
In reply to#31135
Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> wrote:
> Recently I came across a snippet like this:
>  switch (someEnumVar) {
>    case E1:
>      if (...) {
>        ...; return;
>      } else if (...) {
>        ...; throw ...;
>      } else {
>        ...; continue; // enclosing loop
>      }
>    case E2: ...
>  }
> 
> No fall-through is supposed to ever happen from case E1 to case E2.
> All branches in "case E1" exit abnormally. But due to the complexity
> it isn't overly obvious.

I'd read that as an indication that you're working at the wrong level
of abstraction. 

If it's too much work / too brittle to rewrite the whole thing to a 
more manageable form, you could try something like this:

while( ... ) {
 CaseDecision decision;

 switch (someEnumVar) {
  case E1: decision = decideForE1( ... ); break;
  case E2: decision = decideForE2( ... ); break;
  default: throw new RuntimeException( "Program logic error: Not all enums accounted for in switch");
 } // end switch

 switch (decision) {
  case RETURN: return;
  case BREAK: break;
  case CONTINUE: continue;
  default: throw new RuntimeException( "Program logic error: Not all enums accounted for in switch");
 }
} // end loop


-- 
Leif Roar Moldskred

[toc] | [prev] | [next] | [standalone]


#31140

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-02-17 15:51 -0500
Message-ID<mc09k1$3se$1@dont-email.me>
In reply to#31135
On 2/17/2015 5:58 AM, Stefan Ram wrote:
> Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> writes:
>> would recognize it as unreachable and barf. So, I'd like to have some
>> kind of anti-statement, that's ok to be unreachable, but would make the
>
>    There is no such statement.

     It occurs to me that there is, sort of:

	final boolean once;
	switch (someEnumVar) {
	case E1:
	   once = true;
	   if (...) {
	      ...; return;
	   } else if (...) {
	      ...; throw ...;
	   } else {
	      ...; continue; // enclosing loop
	   }
	case E2:
	   once = true; // compiler complains if fall-through possible
	    ...
	case E3:
	   once = true; // ditto
	   ...
	}

IMHO, this particular cure is a lot worse than the disease.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31142

FromAndreas Leitgeb <avl@auth.logic.tuwien.ac.at>
Date2015-02-18 00:40 +0000
Message-ID<slrnme7nt2.uoi.avl@login.logic.tuwien.ac.at>
In reply to#31140
Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
>> Andreas Leitgeb <avl@auth.logic.tuwien.ac.at> writes:
>>> would recognize it as unreachable and barf. So, I'd like to have some
>>> kind of anti-statement, that's ok to be unreachable, but would make the
>  It occurs to me that there is, sort of:
>   final boolean once;
>   switch (someEnumVar) {
>   case E1:
>      once = true;
>      if (...) {
>         ...; return;
>      } else if (...) {
>         ...; throw ...;
>      } else {
>         ...; continue; // enclosing loop
>      }
>   case E2:
>      once = true; // compiler complains if fall-through possible
>       ...
>   case E3:
>      once = true; // ditto
>      ...
>   }
> IMHO, this particular cure is a lot worse than the disease.

Despite your own judgement of it, this is awesome!

Thanks!

[toc] | [prev] | [next] | [standalone]


#31144

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-02-18 08:49 -0500
Message-ID<mc2577$4vj$1@dont-email.me>
In reply to#31142
On 2/17/2015 7:40 PM, Andreas Leitgeb wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
>> [...]
>> IMHO, this particular cure is a lot worse than the disease.
>
> Despite your own judgement of it, this is awesome!

     Now, I wish I hadn't posted it.  It's vile, merely a
curiosity and not a practical solution.  I sincerely hope
you will not use it.

     Remember, the underlying purpose is to guard against a
maintainer who might inadvertently introduce a fall-through.
A maintainer is equally likely to notice that the `once'
variable serves no purpose (many IDE's will tell him so),
and will improve the code by eliminating the useless variable.
Where then will your guard go?

     I believe my other suggestion -- eliminating the last
`else' -- is a far better solution: More direct, more
readable, and more robust.

> Thanks!

     Be sure to thank me again after my ill-conceived gimmick
breaks ...

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31145

FromJukka Lahtinen <jtfjdehf@hotmail.com.invalid>
Date2015-02-18 16:40 +0200
Message-ID<lvh9uj9tal.fsf@saunalahti.fi>
In reply to#31144
Eric Sosman <esosman@comcast-dot-net.invalid> writes:

>     Remember, the underlying purpose is to guard against a
> maintainer who might inadvertently introduce a fall-through.

Why not just insert the break; for every case?
That's what it is for.

-- 
Jukka Lahtinen

[toc] | [prev] | [next] | [standalone]


#31146

FromEric Sosman <esosman@comcast-dot-net.invalid>
Date2015-02-18 10:16 -0500
Message-ID<mc2ab7$p6q$1@dont-email.me>
In reply to#31145
On 2/18/2015 9:40 AM, Jukka Lahtinen wrote:
> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>
>>      Remember, the underlying purpose is to guard against a
>> maintainer who might inadvertently introduce a fall-through.
>
> Why not just insert the break; for every case?
> That's what it is for.

     The original code was oddly structured:

	case E1:
	    if (...) {
	       ...; return;
	    } else if (...) {
	       ...; throw ...;
	    } else {
	       ...; continue;
	    }
	case E2:
	    ...

Inserting a `break' right before the E2 case would provoke a
compile-time error because the statement would be unreachable.

     Andreas worries that someone might add a new alternative
to the `if' ladder, one that doesn't `return' or `throw' or
otherwise exit the `switch', thereby producing an unwanted
fall-through into E2.  I think the most straightforward way to
accomplish this is to eliminate the final `else' and brackets,
putting the `...; continue;' at the "top level" of the case.

-- 
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM

[toc] | [prev] | [next] | [standalone]


#31147

FromJerry Stuckle <jstucklex@attglobal.net>
Date2015-02-18 11:02 -0500
Message-ID<mc2d1a$4r1$1@dont-email.me>
In reply to#31146
On 2/18/2015 10:16 AM, Eric Sosman wrote:
> On 2/18/2015 9:40 AM, Jukka Lahtinen wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>
>>>      Remember, the underlying purpose is to guard against a
>>> maintainer who might inadvertently introduce a fall-through.
>>
>> Why not just insert the break; for every case?
>> That's what it is for.
> 
>     The original code was oddly structured:
> 
>     case E1:
>         if (...) {
>            ...; return;
>         } else if (...) {
>            ...; throw ...;
>         } else {
>            ...; continue;
>         }
>     case E2:
>         ...
> 
> Inserting a `break' right before the E2 case would provoke a
> compile-time error because the statement would be unreachable.
> 
>     Andreas worries that someone might add a new alternative
> to the `if' ladder, one that doesn't `return' or `throw' or
> otherwise exit the `switch', thereby producing an unwanted
> fall-through into E2.  I think the most straightforward way to
> accomplish this is to eliminate the final `else' and brackets,
> putting the `...; continue;' at the "top level" of the case.
> 

I guess I have a different thought here.

While it's nice to try to prevent a maintainer from doing this, it's a
waste of time and effort.

You need to give the maintainer some credit, also.  A maintainer has to
be familiar enough with code that he/she can make the necessary changes.
 This means not only the syntax of the language, but the operation of
the code he/she is changing, and what it can affect in other areas of
the code.  And if he/she does make a change like the OP is concerned
about, then a code review and/or testing should catch it.

I don't think you can prevent a maintainer from making ANY mistakes, and
trying to do so in a case like this will only complicate the code,
increasing the chances for making a mistake.  And that's just the
opposite of what the OP wants.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#31150

FromRobbie Brown <rob@example.com>
Date2015-02-19 09:48 +0000
Message-ID<mc4bfg$t56$1@dont-email.me>
In reply to#31147
On 18/02/15 16:02, Jerry Stuckle wrote:
> On 2/18/2015 10:16 AM, Eric Sosman wrote:
>> On 2/18/2015 9:40 AM, Jukka Lahtinen wrote:
>>> Eric Sosman <esosman@comcast-dot-net.invalid> writes:
>>>
>>>>       Remember, the underlying purpose is to guard against a
>>>> maintainer who might inadvertently introduce a fall-through.
>>>
>>> Why not just insert the break; for every case?
>>> That's what it is for.
>>
>>      The original code was oddly structured:
>>
>>      case E1:
>>          if (...) {
>>             ...; return;
>>          } else if (...) {
>>             ...; throw ...;
>>          } else {
>>             ...; continue;
>>          }
>>      case E2:
>>          ...
>>
>> Inserting a `break' right before the E2 case would provoke a
>> compile-time error because the statement would be unreachable.
>>
>>      Andreas worries that someone might add a new alternative
>> to the `if' ladder, one that doesn't `return' or `throw' or
>> otherwise exit the `switch', thereby producing an unwanted
>> fall-through into E2.  I think the most straightforward way to
>> accomplish this is to eliminate the final `else' and brackets,
>> putting the `...; continue;' at the "top level" of the case.
>>
>
> I guess I have a different thought here.
>
> While it's nice to try to prevent a maintainer from doing this, it's a
> waste of time and effort.
>
> You need to give the maintainer some credit, also.  A maintainer has to
> be familiar enough with code that he/she can make the necessary changes.

...

Sanity at last. There is no way to prevent future foul ups unless the 
original author is present and remembers his state of mind at the time 
of writing (unlikely) or is capable of prescient preemptive time travel.

Alternatively you could always *comment* your code. I know, I know it's 
a subursive idea but it does work.

... but what if someone deletes the comments (jeez) :-)

-- 
Not floundering ... just fishing

[toc] | [prev] | [next] | [standalone]


#31161

FromGene Wirchenko <genew@telus.net>
Date2015-02-20 09:39 -0800
Message-ID<a6seeah7ttourgcdkaevh11l7ip604etc1@4ax.com>
In reply to#31150
On Thu, 19 Feb 2015 09:48:07 +0000, Robbie Brown <rob@example.com>
wrote:

[snip]

>Sanity at last. There is no way to prevent future foul ups unless the 
>original author is present and remembers his state of mind at the time 
>of writing (unlikely) or is capable of prescient preemptive time travel.
>
>Alternatively you could always *comment* your code. I know, I know it's 
>a subursive idea but it does work.
>
>... but what if someone deletes the comments (jeez) :-)

     One argument that I have seen against comments is what if they
are out of date.

     My answer is that you correct the error like any other bug.

Sincerely,

Gene Wirchenko

[toc] | [prev] | [next] | [standalone]


#31151

FromRobbie Brown <rob@example.com>
Date2015-02-19 09:50 +0000
Message-ID<mc4bka$t56$2@dont-email.me>
In reply to#31147
On 18/02/15 16:02, Jerry Stuckle wrote:

subursive/subersive

-- 
Not floundering ... just fishing

[toc] | [prev] | [next] | [standalone]


#31154

Fromv_borchert@despammed.com (Volker Borchert)
Date2015-02-19 18:20 +0000
Message-ID<mc59hi$sm5$1@Gaia.teknon.de>
In reply to#31147
Jerry Stuckle wrote:

> You need to give the maintainer some credit, also.  A maintainer has to
> be familiar enough with code that he/she can make the necessary changes.
>  This means not only the syntax of the language, but the operation of
> the code he/she is changing, and what it can affect in other areas of
> the code.  And if he/she does make a change like the OP is concerned
> about, then a code review and/or testing should catch it.

Where the code review in this case can be done mechanically, e.g.
by findbugs, which would complain about the fallthru.

-- 

"I'm a doctor, not a mechanic." Dr Leonard McCoy <mccoy@ncc1701.starfleet.fed>
"I'm a mechanic, not a doctor." Volker Borchert  <v_borchert@despammed.com>

[toc] | [prev] | [next] | [standalone]


#31155

FromJerry Stuckle <jstucklex@attglobal.net>
Date2015-02-19 15:24 -0500
Message-ID<mc5go3$hul$1@dont-email.me>
In reply to#31154
On 2/19/2015 1:20 PM, Volker Borchert wrote:
> Jerry Stuckle wrote:
> 
>> You need to give the maintainer some credit, also.  A maintainer has to
>> be familiar enough with code that he/she can make the necessary changes.
>>  This means not only the syntax of the language, but the operation of
>> the code he/she is changing, and what it can affect in other areas of
>> the code.  And if he/she does make a change like the OP is concerned
>> about, then a code review and/or testing should catch it.
> 
> Where the code review in this case can be done mechanically, e.g.
> by findbugs, which would complain about the fallthru.
> 

Mechanical code reviews are OK as a first pass, but I've seen them miss
too many logic errors.  I much prefer eyeballing by a different
programmer.  It's how I've run all the projects I've managed over the
last 25 years.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#31149

FromAndreas Leitgeb <avl@auth.logic.tuwien.ac.at>
Date2015-02-19 01:28 +0000
Message-ID<slrnmeaf2h.uoi.avl@login.logic.tuwien.ac.at>
In reply to#31144
Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
> On 2/17/2015 7:40 PM, Andreas Leitgeb wrote:
>> Eric Sosman <esosman@comcast-dot-net.invalid> wrote:
>>> [...]
>>> IMHO, this particular cure is a lot worse than the disease.
>> Despite your own judgement of it, this is awesome!
>      Now, I wish I hadn't posted it.  It's vile, merely a
> curiosity and not a practical solution.  I sincerely hope
> you will not use it.

My amazement about the solution was primarily on a technical level.

I did think I knew Java language pretty well, yet I didn't think to use
a final variable with separate assignments to have the compiler ensure
separateness of switch-case-blocks.

If I really used it, I'd probably give that final variable a real use.
 

[toc] | [prev] | [next] | [standalone]


#31141

FromArne Vajhøj <arne@vajhoej.dk>
Date2015-02-17 18:49 -0500
Message-ID<54e3d388$0$293$14726298@news.sunsite.dk>
In reply to#31135
On 2/17/2015 4:54 AM, Andreas Leitgeb wrote:
> Recently I came across a snippet like this:
>    switch (someEnumVar) {
>      case E1:
>        if (...) {
>          ...; return;
>        } else if (...) {
>          ...; throw ...;
>        } else {
>          ...; continue; // enclosing loop
>        }
>      case E2: ...
>    }
>
> No fall-through is supposed to ever happen from case E1 to case E2.
> All branches in "case E1" exit abnormally. But due to the complexity
> it isn't overly obvious. Lateron, someone might add another else-if
> branch and forget about having it exit abnormally, then it might just
> happen that it does fall through, which in the given context is never
> ever wanted.
>
> What I'd like to do is set a marker just before case E2.
>
> Obviously, I cannot place any normal statement, because the compiler
> would recognize it as unreachable and barf. So, I'd like to have some
> kind of anti-statement, that's ok to be unreachable, but would make the
> compiler barf if it ever *became* reachable during later development.
>
> PS:
> The whole point of this question is about *compile-time* checks.

I don't think there is any construct in Java that result in a compile
time error if it becomes reachable.

If it was to be added then I would expect something like:

@Unreachable
throw new RuntimeException("Get a better compiler that supports 
@Unreachable");

The practical solution for your problem must be to put in some
comments.

Arne

[toc] | [prev] | [next] | [standalone]


#31143

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2015-02-18 00:59 +0000
Message-ID<mc0o4m$ouh$2@dont-email.me>
In reply to#31135
On Tue, 17 Feb 2015 10:58:26 +0000, Stefan Ram wrote:

>   You all know what I would do: Rewrite the whole thing, so that every
>   block has a single exit, which is a the end. Then, divide into several
>   smaller methods.
>
Agreed. A nice compact switch statement, where each case executes a very 
small number of methods, preferably one, is much more readable if the 
methods are properly named and they are organised so their exit 
conditions can be checked by common code that follows the switch 
statement. I think this type of structure is worthwhile even if many of 
the called methods are not used anywhere else.


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web