Change:
when executing:
I'm seeing this as well as of last night. Its preceded by many warnings about : But the first error is the one about . I went back, and I get a good install as late as commit

Discussion:
RECORD_TRACE = CodeTemplate(""" if (jit::tracer::isTracing({ ${tensor_args} })) { <del> jit::Node *n = jit::tracer::recordTrace( "${api_name}", { ${tensor_args} }, ${return_name} ); </del> <ins> jit::Node *n = jit::tracer::recordTrace( "${api_name}", ${trace_inputs}, ${trace_outputs} ); </ins> ${record_attributes} } """)

return res def emit_record_trace(env, declaration): <ins> # Note [clang-802.0.42 tuple overload bug] # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Originally, my plan for emit_$ecord_trace was to keep it as # simple as possible, if at the expense of some somewhat ugly # overloads.  So this meant we had a 'recordTrace' function # with overloads like this: # #   recordTrace(..., const Variable& out) #   recordTrace(..., const std::tuple<Variable, Variable>& out) # # Unfortunately, this triggers a bug in clang-802.0.42 # (widely used in macOS Sierra 10.12.6) wherein a Variable is # implicitly convertible into a std::tuple<Variable, Variable>; # a minimal repro can be seen below here: # #   #include <tuple> #   struct T {}; #   void f(const std::tuple<T, T>&) {} #   void g(T& x) { f(x); } # # To work around this bug, the code generator is a bit more # complicated, and is taught how to handle this situation. </ins> local = {} <ins> arguments = declaration['arguments'] tensor_args = [arg for arg in arguments if arg['simple_type'] in {'Tensor', 'TensorList'}] if len(tensor_args) == 1 and tensor_args[0]['simple_type'] == 'TensorList': # Special case for TensorList.  This only works when there # is a single argument local['trace_inputs'] = "cast_tensor_list({})".format(declaration['arguments'][0]['name']) else: local['trace_inputs'] = CodeTemplate("{ ${tensor_args} }").substitute(env) </ins> local['record_attributes'] = [] for arg in declaration['arguments']: if arg['simple_type'] in {'Tensor', 'TensorList'}:

if declaration['inplace']: env['return_value'] = 'self' <del> env['return_name'] = 'self' </del> env['result'] = 'static_cast<Variable&>(self)' <ins> env['trace_outputs'] = '{ self }' </ins> else: env['return_value'] = '{}(std::move(ret))'.format(declaration['return_type']) <del> env['return_name'] = 'ret' </del> env['result'] = 'std::get<0>(ret)' if len(declaration['returns']) > 1 else 'ret' <ins> if len(declaration['returns']) > 1: # NB: This won't work if we get heterogenous outputs outs = ['std::get<{}>(ret)'.format(i) for i, v in enumerate(declaration['returns']) if v['type'] == 'Tensor'] else: outs = ['ret'] env['trace_outputs'] = CodeTemplate("{ ${outs} }").substitute(outs=outs) </ins> if any(arg['simple_type'] in {'Generator', 'Storage'} for arg in arguments): env['record_trace'] = []

using TensorRef = std::reference_wrapper<const Tensor>; using TensorRefList = std::initializer_list<TensorRef>; <ins> // ArrayRef is not covariant, which means there is no // implicit conversion between TensorList (aka ArrayRef<Tensor>) // and ArrayRef<Variable>.  What we do instead is manually // construct a variable_list, which itself is implicitly convertible // into an ArrayRef<Variable> (but don't return an ArrayRef<Variable>; // ArrayRef is non-owning!) static variable_list cast_tensor_list(const TensorList& tensors) { // TODO: Eliminate the intermediate vector allocation return variable_list(tensors.begin(), tensors.end()); } </ins> static VariableFlags compute_flags(const TensorRefList& tensors) { return compute_flags_tmpl(tensors); }

} private: <del> friend class VariableVersion; </del> <ins> friend struct VariableVersion; </ins> int expected_version; std::shared_ptr<VersionBlock> version_block;  // may be null };

std::make_shared<autograd::Eval>()->replaceSubgraph(inputs, outputs); } <del> Node* recordTraceHelper(std::string op, // TODO: make this a Symbol at::ArrayRef<Variable> inputs, at::ArrayRef<Variable> outputs) { </del> <ins> Node* recordTrace(std::string op, // TODO: make this a Symbol at::ArrayRef<Variable> inputs, at::ArrayRef<Variable> outputs) { </ins> auto state = getTracingState(inputs); auto& graph = state->graph; // TODO: Technically, we could reduce the scope of the lock, but since we

return !was_null && requires_grad == var.requires_grad() && is_volatile == var.is_volatile(); } <del> Node* recordTraceHelper(std::string op, at::ArrayRef<Variable> inputs, at::ArrayRef<Variable> outputs); // These overloads are intended to simplify code generation inline Node* recordTrace(std::string op, std::initializer_list<Variable> inputs, const Variable& output) { return recordTraceHelper(op, inputs, {output}); } inline Node* recordTrace(std::string op, std::initializer_list<Variable> inputs, const std::tuple<Variable, Variable>& outputs) { return recordTraceHelper(op, inputs, {std::get<0>(outputs), std::get<1>(outputs)}); } inline Node* recordTrace(std::string op, std::initializer_list<Variable> inputs, const std::tuple<Variable, Variable, Variable>& outputs) { return recordTraceHelper(op, inputs, {std::get<0>(outputs), std::get<1>(outputs), std::get<2>(outputs)}); } inline Node* recordTrace(std::string op, at::TensorList inputs, const Variable& output) { // TODO: Eliminate the intermediate vector allocation return recordTraceHelper(op, variable_list(inputs.begin(), inputs.end()), {output}); } </del> <ins> Node* recordTrace(std::string op, at::ArrayRef<Variable> inputs, at::ArrayRef<Variable> outputs); </ins> }}} // namespace torch::jit::tracer