[ntuple] Bad state after attempting to make field for virtual type
Check duplicate issues.
- [X] Checked for duplicates
Description
If a code attempts to create a field in an RNTuple for a virtual object type, it rightfully fails, but not with a very clear warning as to why (as compared to constructing the object on the interpreter). However, after the failure, types that should be OK to make fields from now fail. So I guess some internal data structure gets corrupted.
Reproducer
import ROOT
ROOT.gInterpreter.Declare("""\
class Abstract {
public:
Abstract() : data1_(3) {};
virtual ~Abstract() {};
virtual int method() = 0;
private:
int data1_;
};
class Derived : public Abstract {
public:
Derived() : Abstract() {};
int method() override { return data2_; };
private:
int data2_;
};
""")
model = ROOT.Experimental.RNTupleModel.Create()
# Derived can be constructed without complaint
# obj1 = model.MakeField["Derived"]("test1")
# If we attempt (foolishly) to make Abstract, and
# catch the exception, then later attempts to make Derived now fail
# with puzzling JIT errors
try:
obj1 = model.MakeField["Abstract"]("test1")
except ValueError as ex:
print(ex)
obj2 = model.MakeField["Derived"]("test2")
ROOT version
master (6.31.01+)
Installation method
CMSSW IB (/cvmfs/cms-ib.cern.ch/sw/x86_64/nweek-02807/el8_amd64_gcc12/cms/cmssw/CMSSW_13_3_ROOT6_X_2023-10-18-2300)
Operating system
EL8
Additional context
No response
The same symptom also appears if I try to make a field for a class with no default constructor:
import ROOT
ROOT.gInterpreter.Declare("""\
class NoDefaultCtor {
public:
NoDefaultCtor(int x) : data1_(x) {};
private:
int data1_;
};
""")
model = ROOT.Experimental.RNTupleModel.Create()
try:
model.MakeField["NoDefaultCtor"]("test")
except ValueError as ex:
print(ex)
# fails
model.MakeField["std::vector<float>"]("test2")
There, I even get
cling JIT session error: Failed to materialize symbols: { (main, { _ZSt7forwardIRPN4ROOT12Experimental6Detail10RFieldBaseEEOT_RNSt16remove_referenceIS6_E4typeE }) }
which is very weird, why would we be making the symbol
ROOT::Experimental::Detail::RFieldBase*& std::forward<ROOT::Experimental::Detail::RFieldBase*&>(std::remove_reference<ROOT::Experimental::Detail::RFieldBase*&>::type&)
After a quick look, this appears to a be a DeclUnloader problem because of the failed transaction. On the C++ prompt, both cases (abstract class and class without default constructor) work, only some warnings (again related to DeclUnloader)...