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

Fix Int#downto with unsigned int going down to 0. #6678

Merged
merged 1 commit into from
Sep 10, 2018

Conversation

gmarcais
Copy link
Contributor

@gmarcais gmarcais commented Sep 7, 2018

See issue #6669. When using unsigned integers with the downto method, and the to is equal to 0, the code is an endless loop:

3.downto(0) { |i| p i } # Prints 3, 2, 1, 0
3_u16.downto(0) { |i| p i } # Endless loop printing 3_u16, 2_u16, 1_u16, 0_u16, 65535_u16, ...

Both version of the downto method (with and without a block) are fixed by this patch.

src/int.cr Outdated
x -= 1
end
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrong indent.

@asterite
Copy link
Member

asterite commented Sep 7, 2018

What happens with 3_u16.downto(4_u16).to_a?

@gmarcais
Copy link
Contributor Author

gmarcais commented Sep 7, 2018

Hum. 3_u16.downto(4_u16).to_a does not work. Let me fix the case when it goes up to return an "empty" iterator.

@asterite
Copy link
Member

asterite commented Sep 7, 2018

@gmarcais You can probably do something like @done = true unless @from >= @to in the iterator's constructor.

(edit: changed from false to true)

@gmarcais
Copy link
Contributor Author

gmarcais commented Sep 7, 2018

I modified to @done = !(@from >= @to) in the constructor and in rewind.

@Sija
Copy link
Contributor

Sija commented Sep 7, 2018

@gmarcais Would be good to add a spec for a case mentioned by @asterite.

@gmarcais
Copy link
Contributor Author

gmarcais commented Sep 7, 2018

Added spec cases for .to_a.

@straight-shoota
Copy link
Member

Please also fix #upto at into max (see #6669 (comment))

@gmarcais gmarcais force-pushed the master branch 2 times, most recently from 6bc2488 to a888c8d Compare September 7, 2018 22:20
@gmarcais
Copy link
Contributor Author

gmarcais commented Sep 7, 2018

I don't get that error. It does not seem to have anything to do with the current patch:

 1) Semantic: macro allows declaring class with macro expression
       fork: Cannot allocate memory (Errno)

I changed the comment on the patch. Does this have anything to do with it? (Seems unlikely, but I ask nevertheless). Any idea what went wrong?

@Sija
Copy link
Contributor

Sija commented Sep 8, 2018

It does not seem to have anything to do with the current patch

That's correct, nothing to worry about.

@straight-shoota
Copy link
Member

@gmarcais Why close?

@gmarcais
Copy link
Contributor Author

gmarcais commented Sep 9, 2018

I did not do that. Not sure what happened. Can it be reopened (I personally cannot apparently)? I was still considering fixing the step method and related.

@gmarcais
Copy link
Contributor Author

I added a version of the step method that does not overflow as well.

@gmarcais gmarcais reopened this Sep 10, 2018
@asterite
Copy link
Member

@gmarcais You probably need to rebase your branch against master

@gmarcais
Copy link
Contributor Author

@asterite Yes, I rebased and added the step method. That allowed me to reopen the issue.

I am not yet convinced about my implementation because of the following issue.

The step function is possibly a mess of many different types: self, to, by. They may all be different types. Say self is an Int32 equal to Int32::MAX-2 and to is a UInt32 equal to UInt32::MAX/2 + 2 (which is higher than Int32::MAX), what should the method do? Yield Int32 values up to Int32::MAX? Yield UInt32 values up to to?

One can imagine crazier combination: self is an Int32, by is a Float and to is a Double larger than Int32::MAX.

Should there be some type restrictions?

@straight-shoota
Copy link
Member

I don't think it would hurt to just restrict the arguments to the same type as self.

@asterite
Copy link
Member

Yeah, it's a crazy combination. Right now you can even do:

1.step(to: 3.5, by: 0.5) do |i|
  puts i # => 1.0, 1.5, ...
end

I'm not sure restricting the types is the way to go, but we could try it.

But I'd try to not involve step in this PR because it will make it harder to decide when and how to merge this. Let's focus on downto, and we can fix upto and step in separate PRs (or, well, upto is probably fine in this PR).

@RX14
Copy link
Contributor

RX14 commented Sep 10, 2018

I'd cast to the self type using self.class.new(to), like like the lhs type rule for operators.

But yes, another PR please.

@gmarcais
Copy link
Contributor Author

OK, I reverted the step method changes. The current PR only contains the upto and downto methods. I'll create a new PR for step.

@RX14 RX14 added this to the 0.27.0 milestone Sep 10, 2018
@RX14 RX14 added kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:stdlib labels Sep 10, 2018
@RX14 RX14 merged commit f233f53 into crystal-lang:master Sep 10, 2018
ezrast pushed a commit to ezrast/crystal that referenced this pull request Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants