-
Notifications
You must be signed in to change notification settings - Fork 25.4k
Preserve types during empty container assignment #58911
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
[ghstack-poisoned]
🔗 Helpful links
💊 CI failures summary and remediationsAs of commit 7a9b4f4 (more details on the Dr. CI page):
🕵️ 4 new failures recognized by patternsThe following CI failures do not appear to be due to upstream breakages:
|
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
deferring to @gmagogsfm unless there is a specific thing u want comment on |
@@ -1127,15 +1127,6 @@ void AliasDb::makePointerTo(const Value* from, const Value* to) { | |||
// immutable. `Any` is mutable but can point to an immutable type | |||
// through refinement | |||
if (isMutableTypeInternal(from) != isMutableTypeInternal(to)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't look at any of the other code in here, but we should still be making a pointer if there is any type overlap between the sets. please tag me for changes related to alias analysis. this should actually have been changed as part of the Union changes... maybe you could factor out the code from refinement into a "has type overlap" function or something similar ? it would be nice if we could reuse that logic to peephole optimize away prim::isinstance
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're still making a pointer if there's type overlap; the only thing I deleted was the check leading up to the TORCH_INTERNAL_ASSERT
on line 1137. The reason we need to do this is because, if we don't, the two branches for the unchecked_cast
will falsely throw an error.
Example traceback from the TestUnion.test_union_with_dictliteral
test:
Traceback (most recent call last):
File "/data/users/ansley/pytorch/test/jit/test_union.py", line 705, in test_union_with_dictliteral
self.checkScript(fn, ())
File "/home/ansley/local/miniconda3/envs/pytorch/lib/python3.8/site-packages/torch/testing/_internal/jit_utils.py", line 454, in checkScript
self.checkScript(
File "/home/ansley/local/miniconda3/envs/pytorch/lib/python3.8/site-packages/torch/testing/_internal/jit_utils.py", line 485, in checkScript
script_outputs = scripted_fn(*recording_inputs)
File "/home/ansley/local/miniconda3/envs/pytorch/lib/python3.8/site-packages/torch/testing/_internal/common_utils.py", line 139, in prof_func_call
return prof_callable(func_call, *args, **kwargs)
File "/home/ansley/local/miniconda3/envs/pytorch/lib/python3.8/site-packages/torch/testing/_internal/common_utils.py", line 136, in prof_callable
return callable(*args, **kwargs)
RuntimeError: expected_kindINTERNAL ASSERT FAILED at "../torch/csrc/jit/ir/alias_analysis.cpp":1138, please report a bug to PyTorch. intDict(str, Tensor)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(isMutableTypeInternal(from) != isMutableTypeInternal(to))
we're checking equality not overlap here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the wording choice, I did mean equality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we want to be checking overlap, e.g. Optional[List[int]] should have a pointer to List[int]. If the sometimes/never/always subtyping logic from ir_emitter was factored out we could just check that it's not never
, and then make a pointer
[ghstack-poisoned]
union_type_hint->containedTypes().end(), | ||
std::back_inserter(list_types), | ||
[&](TypePtr type_ptr) { | ||
return type_ptr->isSubtypeOf(AnyListType::get()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check for type_ptr->kind == ListType::Kind
Node* result = graph->insertNode(graph->createList(elem_type, values)); | ||
if (annotated_union_type) { | ||
Node* n = graph->insertNode( | ||
graph->create(prim::unchecked_cast, {result->output()})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline:
This node is inserted because interpreter isn't happy about the type mismatch in assignment.
TODO: Find out why interpreter isn't happy about it
TODO: Find out performance implications (if any) about inserting this unchecked_cast
node into graph.
c10::optional<TypePtr> unified = unifyTypeList( | ||
types, nowhere, /*default_to_union=*/true, element_type_hint); | ||
types, nowhere, /*default_to_union=*/true, known_elem_type); | ||
|
||
if (!type_hint && *unified == AnyType::get()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, this should never trigger when default_to_union=True
.
// We don't want to use `elem_type` as the final argument to | ||
// `unifyTypeList` because there's a chance that `elem_type` is | ||
// the Tensor default | ||
auto known_elem_type = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto known_elem_type = | |
auto elem_type_hint = |
@@ -3789,13 +3837,48 @@ struct to_ir { | |||
// `Any` as a catch-all supertype). Assume `[]` is `List[Tensor]` | |||
TypePtr elem_type = TensorType::get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypePtr elem_type = TensorType::get(); | |
TypePtr inferred_elem_type = TensorType::get(); |
test/jit/test_union.py
Outdated
x["bar"] = torch.tensor(3) | ||
return x | ||
|
||
self.checkScript(fn, ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
Use FileCheck on generated IR to make sure right nodes/types are inserted into graph
[ghstack-poisoned]
[ghstack-poisoned]
Differential Revision: [D30651066](https://our.internmc.facebook.com/intern/diff/D30651066) [ghstack-poisoned]
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
// If the type hint was not `List[T]`, throw an error | ||
throw ErrorReport(ll) << "Expected a List type hint but instead got " | ||
<< type_hint->repr_str(); | ||
// If necessary/possible, make `type_hint` a ListType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The added logic is complex enough to warrant a helper function I think. What do you think?
Differential Revision: [D30785623](https://our.internmc.facebook.com/intern/diff/D30785623) [ghstack-poisoned]
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Differential Revision: [D30785623](https://our.internmc.facebook.com/intern/diff/D30785623) [ghstack-poisoned]
Differential Revision: [D30785623](https://our.internmc.facebook.com/intern/diff/D30785623) [ghstack-poisoned]
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
2 similar comments
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Differential Revision: [D30785623](https://our.internmc.facebook.com/intern/diff/D30785623) [ghstack-poisoned]
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Differential Revision: [D30785623](https://our.internmc.facebook.com/intern/diff/D30785623) [ghstack-poisoned]
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
4 similar comments
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
@ansley has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
Stack from ghstack:
Differential Revision: D30785623