diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index c60be8566a65..657a6e4c2b71 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -213,6 +213,10 @@ module Crystal assert_macro "", "{{5 % 3}}", [] of ASTNode, "2" end + it "preserves integer size (#10713)" do + assert_macro "", "{{ 3000000000u64 % 2 }}", [] of ASTNode, "0_u64" + end + it "executes &" do assert_macro "", "{{5 & 3}}", [] of ASTNode, "1" end diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 36ef41f37e6d..1bdee6ad8030 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -520,18 +520,17 @@ module Crystal end def int_bin_op(op, args) - if @kind == :f32 || @kind == :f64 - raise "undefined method '#{op}' for float literal: #{self}" - end - - NumberLiteral.new(bin_op(op, args) do |me, other| - other_kind = args.first.as(NumberLiteral).kind - if other_kind == :f32 || other_kind == :f64 + result = bin_op(op, args) do |me, other| + if me.is_a?(Int) && other.is_a?(Int) + yield me, other + elsif me.is_a?(Float) + raise "undefined method '#{op}' for float literal: #{self}" + else raise "argument to NumberLiteral##{op} can't be float literal: #{self}" end + end - yield me.to_i, other.to_i - end) + NumberLiteral.new result end def bin_op(op, args)