-
Notifications
You must be signed in to change notification settings - Fork 7.1k
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
Fix String Parameter Binding for Biginteger numeric literals #11634
Conversation
Makes sense to review all using LanguagePrimitives.IsNumeric() and make the fix more general? |
EDIT: Apparently I was dreaming or something, I'm not seeing a second overload of IsNumeric() now 😕 So yeah, the long and the short of it is that we can't determine from the type code alone whether it's numeric, we'd need to also pass the actual type into the method. Given that, I think the most elegant solution is to add an overload of Probably better for a follow up PR than one to take place here though, I wanna get this fixed for the 7.0 release and not hold it up any with extensive changes. 😁 |
The fix can have a side effects. We should be careful. It is not for 7.0 GA. I think we should review all code paths.
@iSazonov can you elaborate on what side effects you're seeing? 🙂 |
If we'd like to instead do a thorough review of the IsNumeric usages and ensure they all align, we can do that too. I have a second branch live here with a more complete set of changes. If you'd prefer I can PR that instead; was just trying to keep changes minimal to simplify review. 🙂 |
I see above 20 references to IsNumeric() and after first look I have questions for every such reference. |
@iSazonov I agree we should do something along those lines, but I don't think I'd be the right person for that job. Ideally I'd ask someone on the PS team (possibly multiple people) who is familiar with the code path(s) in question. From a brief look through, I would guess we shouldn't see any adverse effects from always handling BigInteger the same way as we do other numeric types; from what I can see, handling it in this way doesn't break anything immediately obvious, and it also solves the issue raised in #11628 The other code paths using IsNumeric(), as you'd expect, all deal with handling numeric values in various scenarios (I see formatting code, remoting code, and parameter binding code, among a couple others). At least intuitively, I think we're best off continuing to handle them uniformly, and adding a standard case in for BigInteger, but as I said... I lack the familiarity others may have to really make a solid call on that. Ultimately, I agree the right solution is to review and handle them all. If we have time to do so prior to 7.0 GA, that'd be my preference. If not, this more minimal change will prevent breaking existing scripts in at least this specific scenario. It mightn't be perfect, but it's a better state than we're sitting in currently. 🙂 |
I've been looking at @vexx32's two branches to see if I could locate any bugs or departures from PS5/6 behavior, and I've found a couple. First, for the more extensive branch with the new
These are caused by calling the new overload from ExtensionMethods.cs. If that change is reverted, the above is fixed. This next issue exists in both branches:
In PS5/6, the first cast converts to a string as expected, while the second cast also fails though with a more clear exception. Treating a BigInteger as though it were a Numeric primitive in I wish I were qualified to comment on whether or not other issues exist... but I thought I'd at least comment on what I'd found so far. |
@gurnec very much appreciate the thorough review on all points! I'll check out your update there this weekend and see if can get it to break or not 😄 I have my doubts any of this will make it in time for v7 but I'll do what I can to get it sorted out properly either way. 💖 |
@vexx32 ping :-) |
I think I have some idea of what to do here... it'll need some modifications to the type converters for numeric types as well as adding biginteger to the types list. The issues @gurnec is finding probably come about because while we told PS that biginteger is a numeric type, we didn't tell it how to handle it as a numeric type. I'm going to tinker a bit in my side branch and when I have everything working I'll merge it back into this branch. Thanks for the ping @iSazonov! 🙂 EDIT: Some tinkering later, and I think @gurnec has the right idea; having PS treat BigInteger as a regular number in all circumstances is not the way to go. It doesn't implement some of the interfaces necessary for those conversion paths to work correctly (most notably |
6522743
to
29c61ec
Compare
@gurnec @iSazonov looks like that should sort everything out. Note: Other fixed conversions:
The other conversion failures @gurnec noted from the other branch never arose in this branch and will continue to work correctly. 🙂 EDIT: Noticed that bool->bigint was failing, pushed a fix and added them to the list. |
29c61ec
to
d2e0825
Compare
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.
@vexx32 I see many style issues.
It is not clear about IsNumeric() method. Should we fix it too?
@iSazonov Yeah, I'm not inclined to go fixing too many style issues in these code sections at the moment. They really need a thorough pass in a separate PR and I'd rather not complicate the commits here too much. A few things seem to have been caught by my autoformatter, I can remove those if we need to, but I've already got plans to do a good style pass on LanguagePrimitives anyway 🙂 I don't think we should incorporate this into The changes as they are allow things to keep treating BigInteger as kind of its own thing, which it is, while also adding the necessary conversion paths for it to appear like a more normal number to users and allow it to be used as such. |
@@ -444,7 +445,8 @@ private static void InitializeGetEnumerableCache() | |||
|
|||
internal static bool IsTypeEnumerable(Type type) | |||
{ | |||
if (type == null) { return false; } | |||
if (type == null) | |||
{ return false; } |
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 mean such style issues. We should either fix or revert.
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'll trim these out for now to keep things simple. 👍
Really there are some IsNumeric() methods and I guess ignoring its does not fix even parameter bindings. |
@iSazonov The current branch here as it is resolves the binding issues with BigInteger values. Reviewing IsNumeric() usages is likely to be a bit of a dead end in my opinion, but might still be valuable to do for some edge cases. EDIT: I've rebased and trimmed the changes down to just the necessary ones for this PR. I think I'll do a style pass in this file afterwards, it really needs it 😁 |
d2e0825
to
757a07c
Compare
@vexx32 I'm afraid there's a regression in your current patch:
or if we want string-to-BigInt conversions to act closer to other string-to-numeric ones, something more complicated will be required like this commit over here. That will fix the immediate issue of This second commit should fix the latter. Whether it makes sense to start down the road of making BigInts more like the other simple numeric types as opposed to keeping things simpler isn't really my call.... |
Huh, really? That's quite odd. I thought I tested that & had that working. Must've broken it again... ah, yeah, I see what you're saying. I don't think it should require quite that complex of a solution though; you'll note the original EDIT: Yeah the issue is essentially that |
@iSazonov @daxian-dbw is there anything still pending on this one? 💖 |
The statement
was intended to be narrow in scope, is that correct? Because otherwise, it should be pointed out that BigInts today behave quite differently than other numerics.
(The patches in the PR don't change any of the above, just the My apologies for the noise if that statement was indeed intended to be narrow in scope. |
@gurnec expecting Some of those I would like to fix (especially the ones involving rounding to bigint), but they will likely have to be addressed on an individual basis. For instance, I don't think it's a good idea (or really possible) for |
Actually it does, or rather it supports all the conversions that the other real-number type I'm not trying to be argumentative though... I completely agree with what you're saying. |
I think this was described incorrectly,
The committee commented on this as a reply to the ask, but this particular issue seems to be out of the scope of the initial purpose of this PR. |
I'll have to take a thorough look at the diffs. I agree that I suppose I can pare that part out if necessary. @daxian-dbw see #12623 for the main casting issues that were addressed here in the second commit. If we need to split it out I think I can manage that well enough, just let me know. |
Yes please, it could be good to separate that fix to another PR. Also, are the changes in |
@daxian-dbw I actually am not entirely sure. I will give it a look without those and get back to you on that this evening. 🙂 |
@daxian-dbw yeah so if I take out the changes in the actual
Looking at pulling off the latest commit now, might need some parts, will need to verify. |
When passing a bigint literal, e.g., `7n` as a bare string to a parameter of type [string], the parameter binder was incorrectly using the direct ToString() conversion unlike other numeric literals, which store the original TokenText in order to properly retrieve the original string that was entered at the command line.
c2b7c97
to
e404363
Compare
@daxian-dbw I've split out the casting-related changes to #12629 |
Co-authored-by: Dongbo Wang <dongbow@microsoft.com>
@vexx32 Some tab completion tests about |
@PoshChan please get failures @daxian-dbw not sure how I can address the codefactor issue tbh. The using directive is in the right place. I think it's a false positive from the fact that there are some additional using directives further down behind some compiler flags. |
@vexx32 Thanks for the clarification on the code factor issue. |
🎉 Handy links: |
PR Summary
When passing a bigint literal, e.g.,
7n
, as a bare string to a parameter of type [string], the parameter binder was incorrectly using the direct ToString() conversion (unlike other numeric literals), whichstore the original TokenText in order to properly retrieve the original string that was entered at the command line.
Fix is to ensure that we're capturing and storing the TokenText value when the value is of type BigInteger (since this type's TypeCode is simply
object
and is not read as being a numeric type by those APIs).I also needed to add BigInteger to the array of numeric types stored in LanguagePrimitives in order for the conversion methods to recognise that BigInteger literals need to be converted to string more carefully.
Quick test case (interactive only):
PR Context
This PR resolves #11626
/cc @SteveL-MSFT
I know y'all are probably up to your necks with the v7 release -- I'm hoping this can pass under the wire for that; would definitely like to have it fixed for the upcoming release. 🙂
I'm not 100% sure the included tests are the best way to test this, but they certainly seem to do the job.
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.