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

Inline fn fails to inline, but only if it's not called and @typeInfo has analysed it #3958

Closed
cshenton opened this issue Dec 21, 2019 · 2 comments
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Milestone

Comments

@cshenton
Copy link
Contributor

This is a bit awkward to explain, here's the repro, it was hard to make it smaller since this bug is quite strange, on 0.5.0+62c817420:

Try the following test with zig test repro.zig

  • manually expect succeeds
  • automatic expectEqual fails with an unrelated inline error
  • if the "failed to inline" functions are actually called the inline error goes away 🤔

This is probably related to #3893 since expectEqual calls @typeInfo under the hood.

// repro.zig
const std = @import("std");
const sqrt = std.math.sqrt;

/// Mathematical vector type
fn Vector(comptime d: usize) type {
    return struct {
        vals: [d]f32,

        const Self = @This();

        pub inline fn zeros() Self {
            var vals: [d]f32 = undefined;
            comptime var i = 0;
            inline while (i < d) : (i += 1) {
                vals[i] = 0;
            }
            return Self{ .vals = vals };
        }

        pub inline fn sum(self: Self) f32 {
            var total: f32 = 0.0;
            for (self.vals) |val| {
                total += val;
            }
            return total;
        }

        pub inline fn mul(self: Self, other: Self) Self {
            const vs: @Vector(d, f32) = self.vals;
            const vo: @Vector(d, f32) = other.vals;

            return Self{ .vals = vs * vo };
        }

        pub inline fn dot(self: Self, other: Self) f32 {
            const product = self.mul(other);
            return product.sum();
        }
    };
}

const Vec2 = Vector(2);

// Tests

const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;

test "Inline failure" {
    // This works as it should
    const v = Vec2.zeros();
    expect(v.vals[0] == 0);
    expect(v.vals[1] == 0);

    // Uncommenting this causes an inline error
    // expectEqual(v, Vec2{ .vals = [2]f32{ 0, 0 }});

    // Uncommenting this gets rid of the error!?!?
    // const result = v.dot(v);
    // expect(result == 0);
}
@cshenton
Copy link
Contributor Author

cshenton commented Dec 21, 2019

More details:

  • This seems to only affect inline functions that are called by other member functions (the calling function can be inline or not, the problem, still occurs)
  • Compilation succeeds so long as the inline fn call is somewhere in the compilation unit (so a call in another test would be fine)

@daurnimator daurnimator added bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend. labels Dec 22, 2019
@andrewrk andrewrk added this to the 0.7.0 milestone Dec 31, 2019
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Aug 13, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
@Vexu
Copy link
Member

Vexu commented Dec 28, 2022

Inlining now happens during semantic analysis.

@Vexu Vexu closed this as completed Dec 28, 2022
@andrewrk andrewrk modified the milestones: 0.12.0, 0.11.0 Dec 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend.
Projects
None yet
Development

No branches or pull requests

4 participants