Skip to content
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

String constant folding (with test) #4083

Merged
merged 6 commits into from Apr 12, 2021
Merged

Conversation

da-woods
Copy link
Collaborator

@da-woods da-woods commented Apr 2, 2021

This just finishes off #3952 by adding a test-case.

It's surprisingly hard to create a test-case for this. I had to allow bytes-to-string comparisons in the TreePath code (allowing bytes constants might be another possibility I think). I've confirmed that it fails on the current master and passes with the patch.

Alphadelta14 and others added 2 commits Dec 22, 2020
Ensure that when StrNode is a BytesLiteral, that we don't coerce it to unicode

Fixes cython#3951
Needed to change the TreePath slightly to allow bytes-to-str
comparison
@@ -834,7 +834,7 @@ def repr_of(self, node):
result += "(name=\"%s\")" % node.name
elif isinstance(node, ExprNodes.AttributeNode):
result += "(type=%s, attribute=\"%s\")" % (repr(node.type), node.attribute)
elif isinstance(node, ExprNodes.ConstNode):
elif isinstance(node, (ExprNodes.ConstNode, ExprNodes.StringNode)):
Copy link
Collaborator Author

@da-woods da-woods Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also snuck in this slight inprovement to PrintTree

Copy link
Contributor

@scoder scoder Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using PyConstNode instead? And maybe using %r for the value instead of "%s"?

@@ -4424,6 +4424,8 @@ def _multiply_string(self, node, string_node, multiplier_node):
string_node.unicode_value = encoded_string(
string_node.unicode_value * multiplier,
string_node.unicode_value.encoding)
if not string_node.value.is_unicode:
build_string = bytes_literal
Copy link
Collaborator Author

@da-woods da-woods Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I understand exactly what's needed from these two comments on the other PR. So I haven't made the changes.

Copy link
Collaborator Author

@da-woods da-woods Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually - I think I do understand so I've made the changes

Copy link
Contributor

@scoder scoder left a comment

Thanks, good changes. Just two nits.

elif (isinstance(attr_value, bytes) and isinstance(value, str) and
attr_value.decode("utf-8") == value):
Copy link
Contributor

@scoder scoder Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't you encode value instead of decoding attr_value? (And only if it's unicode and not just str?)
How do you know that attr_value is really encoded in UTF-8 and not something else?

@@ -834,7 +834,7 @@ def repr_of(self, node):
result += "(name=\"%s\")" % node.name
elif isinstance(node, ExprNodes.AttributeNode):
result += "(type=%s, attribute=\"%s\")" % (repr(node.type), node.attribute)
elif isinstance(node, ExprNodes.ConstNode):
elif isinstance(node, (ExprNodes.ConstNode, ExprNodes.StringNode)):
Copy link
Contributor

@scoder scoder Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using PyConstNode instead? And maybe using %r for the value instead of "%s"?

@da-woods
Copy link
Collaborator Author

da-woods commented Apr 2, 2021

I've made those changes.

I think the failures on Py2.7 are unrelated to this change and possibly to do with a new version of decorator (https://pypi.org/project/decorator/#history) that's incompatible with Python 2.7. But it does mean that this isn't tested on Python 2.7

It isn't necessary to show the bug, but it's worth testing anyway.
elif (isinstance(attr_value, bytes) and isinstance(value, str) and
attr_value.decode("utf-8") == value):
attr_value == value.encode()):
Copy link
Contributor

@scoder scoder Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also not going to work correctly in Py2, where str is bytes and .encode() will .decode() it first. If the value has some encoding other than us-ascii, then this implicit decoding will fail. Thus my suggestion that this should only be done for unicode strings and not Py2 str.

Copy link
Collaborator Author

@da-woods da-woods Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed (I think)

@scoder
Copy link
Contributor

scoder commented Apr 12, 2021

Test failure seems random. Let's get this in and see if it works then.

@scoder scoder merged commit cd6e29d into cython:master Apr 12, 2021
1 check failed
@da-woods da-woods deleted the str_const_folding branch Apr 12, 2021
@scoder scoder added this to the 0.29.23 milestone Apr 14, 2021
scoder pushed a commit that referenced this pull request Apr 14, 2021
* Handle constant folding for LanguageLevel 2 on Python 3. Ensure that when StrNode is a BytesLiteral, that we don't coerce it to unicode.
* Add test for string multiplication bug. Needed to change the TreePath slightly to allow bytes-to-str comparison.

Fixes #3951
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants