[darcs-users] "replace" patch type (was: bug or inconsistency in darcs replace)

David Roundy droundy at abridgegame.org
Sat Mar 27 19:53:30 UTC 2004

On Sat, Mar 27, 2004 at 09:59:09AM -0800, Kevin Smith wrote:
> It is probably worse when renaming variables. Local variables or 
> parameters within each method often use ordinary names that are not 
> distinct. Again, a line number constraint would help.

Yes, but the specific name of a local variable or parameter doesn't matter
in any language that I'm familiar with, so I don't see how this could
introduce a bug, although it certainly could be surprising.

> A bigger problem is that a replace in class Foo of member Bar cannot 
> distinguish between references to aFoo.Bar and aNonFoo.Bar. If 
> aNonFoo.Bar actually exists, it might be difficult to detect this error. 
> Not all projects have test suites, unfortunately.

True, and not all languages have static checking either, which is
worse... Projects which involve naming different members of different
classes with the same name probably shouldn't be using replace on those

As I understand it, your scenario is we want to rename Foo.Bar to Foo.Baz,
but there also exists a NonFoo.Bar *and* and NonFoo.Baz.  I run a

darcs replace Bar Baz foo.cpp

and when I do so, foo.cpp doesn't contain a reference to either NonFoo.bar
or NonFoo.Baz.

Meanwhile, you have added a reference to NonFoo.Bar to foo.cpp.  Then when
you merge with my change, your NonFoo.Bar becomes NonFoo.Baz, which alas
causes no compile error because NonFoo.Baz actually exists, and a nasty bug
is the result.  This would indeed be unfortunate.

Incidentally, one *could* accomplish an analagous bug with hunk patches
alone (at least in some languages), it just requires the same sort of a
situation in reverse.  For example, if I rename a variable to the same name
as a variable you introduce (separately) it is pretty easy to see how we
could get a bug introduced with no compile error, at least in languages
like perl or python where you don't need to declare your variables.  In
this case, a replace patch would have given a conflict, while the hunk
patch silently introduces a bug upon merge.  The moral of the story is that
when you merge your changes with someone else's changes, you need to look
to see what their changes are.

> But probably my biggest concern is that the change extends unbounded 
> through time and space. A "replace" that does exactly what I want in my 
> repo today might do something unexpected and unwanted in a different 
> repo, or at some point in the future.

Ah, but it is bounded, provided the "replace" patch gets merged.  The only
way it would be unbounded is if other users never pull from your repo--that
is, if you make a change that is never merged into other repositories.  As
long as there is a merge, the effects of the replace will be "frozen in".

e.g. a recent replace patch in darcs itself was:

replace ./Depends.lhs [A-Za-z_0-9] pi pinfo

(which got rid of a warning in Depends, which was because pi is equal to
3.14159, so I was redefining pi)

This patch is already in the central darcs repo, so if someone gets a copy
of darcs and makes some changes to Depends.lhs, this patch won't be merged
with their changes.

The only time when it will have an effect is if someone who *hasn't* got
"[more -Wall cleaning.
David Roundy <droundy at abridgegame.org>**20040304131042]" in their
repository adds some code to Depends.lhs with either pi or pinfo in it.  If
they have a pi, it will get replaced with pinfo when merged with the main
repo.  If they have a pinfo in their patch, a conflict will happen (and
need to be resolved) when they merge with the main repo, either by pushing
to me or pulling my changes.

In short, the only time darcs replace will do "interesting" things is while
you are merging the replace patch with other changes.  This is precisely
the time when you *expect* code to break if both changes modify the same
file in incompatible ways, and so the potential breakage is bounded "in
time" in precisely the same manner that a boring old hunk patch.  "In
space", it is less bounded than a hunk patch, because the replace patch
affects an entire file, but I wouldn't consider it unbounded in space
either, since it certainly won't affect any other file.

> I would feel better if we could instead (later) offer more sophisticated 
> refactoring patch types for specific languages. For statically typed 
> languages, these could be far safer and more effective.

The catch with refactoring patch types is that they would be *very* hard to
define.  For example, what would a refactoring patch do when merged with a
patch that made the file uncompilable?  On the other hand, I definitely
agree that if feasible, refactoring patches would be very nice.  And that
they are definite post-1.0 material...
David Roundy

More information about the darcs-users mailing list