Bug 16421 - infinite recursion in automatic "coerce<-" method
Summary: infinite recursion in automatic "coerce<-" method
Status: UNCONFIRMED
Alias: None
Product: R
Classification: Unclassified
Component: S4methods (show other bugs)
Version: R-devel (trunk)
Hardware: All All
: P5 critical
Assignee: R-core
URL:
Depends on:
Blocks:
 
Reported: 2015-06-12 08:54 UTC by Hervé Pagès
Modified: 2015-06-16 12:28 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hervé Pagès 2015-06-12 08:54:21 UTC
It happens for example with the following class hierarchy:

  setClass("A", representation(aa="character"))
  setClass("B", contains="A", representation("VIRTUAL"))
  setClass("C", contains="B")

Then:

  c <- new("C")
  as(c, "A") <- new("A")  # "node stack overflow" error!

Problem is in the definition of the automatic coerce<-,C,A method:

  > selectMethod("coerce<-", c("C", "A"))
  Method Definition:
  function (from, to = "A", value) 
  {
    .value <- as(from, "B", TRUE)
    as(.value, "A") <- value
    value <- .value
    {
        if (!is(value, "B")) 
            stop(gettextf("the computation: 'as(object,\"%s\") <- value' is valid when object has class %s only if 'is(value, \"%s\")' is TRUE ('class(value)' was %s)\n", 
                "B", dQuote("C"), "B", dQuote(class(value))), 
                domain = NA)
        value
    }
  }

The 1st line tries to turn 'from' into a B instance which is impossible because
B is a virtual class so the coercion is actually a no-op, and, as a result
'.value' is the same as 'from'. Then the 2nd line calls the coerce<-,C,A method
again leading to infinite recursion.
Note that the remaining lines in the body don't seem to make much sense.

If B is not virtual, the automatic coerce<-,C,A method is:

  > selectMethod("coerce<-", c("C", "A"))
  Method Definition:
  function (from, to = "A", value) 
  {
    .value <- as(from, "B", TRUE)
    as(.value, "A") <- value
    value <- .value
    {
        for (what in "aa") slot(from, what) <- slot(value, what)
        from
    }
  }

and it works.

Any reason why these automatic methods aren't just doing something like:

  for (what in slotNames("<to-class>")) slot(from, what) <- slot(value, what)
  from

Wouldn't this always work? Even when some intermediate class (i.e. a class
between the from and the to classes) is virtual?

Thanks,
H.