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

Operator overloading should attempt eager resolution #3743

Closed
nikomatsakis opened this issue Oct 12, 2012 · 2 comments
Closed

Operator overloading should attempt eager resolution #3743

nikomatsakis opened this issue Oct 12, 2012 · 2 comments
Labels
A-typesystem Area: The type system C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@nikomatsakis
Copy link
Contributor

This test fails to infer

struct Vec2 {
    x: float,
    y: float
}

// methods we want to export as methods as well as operators
impl Vec2 {
#[inline(always)]
    pure fn vmul(other: float) -> Vec2 {
        Vec2 { x: self.x * other, y: self.y * other }
    }
}

// Right-hand-side operator visitor pattern
trait RhsOfVec2Mul<Result> { pure fn mul_vec2_by(lhs: &Vec2) -> Result; }

// Vec2's implementation of Mul "from the other side" using the above trait
impl<Res, Rhs: RhsOfVec2Mul<Res>> Vec2: Mul<Rhs,Res> {
    pure fn mul(rhs: &Rhs) -> Res { rhs.mul_vec2_by(&self) }
}

// Implementation of 'float as right-hand-side of Vec2::Mul'
impl float: RhsOfVec2Mul<Vec2> {
    pure fn mul_vec2_by(lhs: &Vec2) -> Vec2 { lhs.vmul(self) }
}

// Usage with failing inference
fn main() {
    let a = Vec2 { x: 3f, y: 4f };

    // the following compiles and works properly
    let v1: Vec2 = a * 3f;
    io::println(fmt!("%f %f", v1.x, v1.y));

    // the following compiles but v2 will not be Vec2 yet and
    // using it later will cause an error that the type of v2
    // must be known
    let v2 = a * 3f;
    io::println(fmt!("%f %f", v2.x, v2.y)); // error regarding v2's type
}

but it works if you desugar a * 3f to a.mul(&3f). This is because (I think) operator overloading does not attempt eager resolution. I'd like to refactor this whole system as described in #3742 but this would be a quick and (relatively) easy fix for this particular problem.

@catamorphism
Copy link
Contributor

This compiles successfully now. Updated test case (which I'll check in):

struct Vec2 {
    x: float,
    y: float
}

// methods we want to export as methods as well as operators
impl Vec2 {
#[inline(always)]
    fn vmul(self, other: float) -> Vec2 {
        Vec2 { x: self.x * other, y: self.y * other }
    }
}

// Right-hand-side operator visitor pattern
trait RhsOfVec2Mul<Result> { fn mul_vec2_by(&self, lhs: &Vec2) -> Result; }

// Vec2's implementation of Mul "from the other side" using the above trait
impl<Res, Rhs: RhsOfVec2Mul<Res>> Mul<Rhs,Res> for Vec2 {
    fn mul(&self, rhs: &Rhs) -> Res { rhs.mul_vec2_by(self) }
}

// Implementation of 'float as right-hand-side of Vec2::Mul'
impl RhsOfVec2Mul<Vec2> for float {
    fn mul_vec2_by(&self, lhs: &Vec2) -> Vec2 { lhs.vmul(*self) }
}

// Usage with failing inference
fn main() {
    let a = Vec2 { x: 3f, y: 4f };

    // the following compiles and works properly
    let v1: Vec2 = a * 3f;
    io::println(fmt!("%f %f", v1.x, v1.y));

    // the following compiles but v2 will not be Vec2 yet and
    // using it later will cause an error that the type of v2
    // must be known
    let v2 = a * 3f;
    io::println(fmt!("%f %f", v2.x, v2.y)); // error regarding v2's type
}

@ghost ghost assigned catamorphism May 22, 2013
@huonw
Copy link
Member

huonw commented Aug 4, 2013

Test case added by aac1298.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

3 participants