Just to add some reference links regarding how Lists in the IR are interpreted:

  
      github.com
  
  
    pytorch/pytorch/blob/ac00e85e36c236f141d0621bfbbbbe8c9ffeefd1/torch/csrc/jit/script/compiler.cpp#L2224

  // if the list is non-empty use type_of(list[0])
  // otherwise assume it is List[Tensor]
  TypePtr elem_type = TensorType::get();
  if (type_hint && type_hint->kind() == TypeKind::ListType) {
    elem_type = type_hint->expect<ListType>()->getElementType();
  } else if (!values.empty()) {
    elem_type = values.at(0)->type();
  }
  for (auto v : values) {
    if (!v->type()->isSubtypeOf(elem_type)) {
      throw ErrorReport(tree)
          << "Lists must contain only a single type, expected: "
          << *elem_type << " but found " << *v->type() << " instead";
    }
  }
  Value* result =
      graph->insertNode(graph->createList(elem_type, values))->output();
  return result;
} break;
case TK_TUPLE_LITERAL: {
  auto ll = TupleLiteral(tree);



  
  
    
    
  
  



  
      github.com
  
  
    pytorch/pytorch/blob/ac00e85e36c236f141d0621bfbbbbe8c9ffeefd1/torch/csrc/jit/ir.cpp#L1237

n->i_(attr::end, end);
std::vector<TypePtr> output_types;
for (auto i = beg; i < end; ++i) {
  output_types.push_back(tuple_type->elements().at(i));
}
auto tt = TupleType::create(std::move(output_types));
n->output()->setType(tt);
return n;
}


Node* Graph::createList(const TypePtr& elem_type, at::ArrayRef<Value*> values) {
auto n = create(prim::ListConstruct, values);
for (const auto& v : values) {
  AT_ASSERT(v->type()->isSubtypeOf(elem_type));
}
n->output()->setType(ListType::create(elem_type));
return n;
}
Node* Graph::createListUnpack(Value* v, size_t size) {
ListTypePtr list_type = v->type()->expect<ListType>();
TypePtr elem_type = list_type->getElementType();