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

[FOLLOW UP] Type check #996

Open
1 of 3 tasks
Y-Nak opened this issue Apr 23, 2024 · 0 comments
Open
1 of 3 tasks

[FOLLOW UP] Type check #996

Y-Nak opened this issue Apr 23, 2024 · 0 comments
Labels
v2 Issues in v2 implementation

Comments

@Y-Nak
Copy link
Collaborator

Y-Nak commented Apr 23, 2024


  • Integrate method selection into type inference context properly. For example, s.foo should be resolved to Trait<u32>::method without any ambiguity. (Resolved in Tabled trait resolution #1007)
trait Trait<T> {
    fn method(self) -> T
}

struct S {}

impl Trait<i32> for S {
    fn method(self) -> i32 {
        1
    }
}

impl Trait<u32> for S {
    fn method(self) -> u32 {
        1
    }
}

fn foo() -> u32 {
    let s = S {};
    s.method()
}

This could be achieved by maintaining the mapping between a canonical type and a given receiver type in a call site.
Also, the method selector needs to return a TraitInst that relates to the receiver type. In the above example, it will be Canonical<Trait<S, ?0>>. The below one is a more complex case,

trait Default {
    fn default() -> Self
}

trait Foo<T, U> {
    fn foo(self) -> (T, U)
}

struct S<T> {
    t: T,
}

impl<T> S<T> {
    fn new() -> Self
    where
        T: Default,
    {
        Self { t: T::default() }
    }
}

impl<T> Foo<i32, T> for S<T> {
    fn foo(self) -> (i32, T) {
        (1, self.t)
    }
}

impl<T> Foo<u32, T> for S<T> {
    fn foo(self) -> (u32, T) {
        (1, self.t)
    }
}

fn bar() -> (u32, i32) {
    let s = S::new()
    s.foo()
}

In this case, assuming the type of s is S<?10> in the inference context and its canonical form is Canonical<S<?0>>, then the method selector needs to return Canonical<Trait<S<?0>, ?1, ?0>> as a candidate for s.foo. Then, it should be decanonicalized to Trait<S<?10>, ?fresh, ?10> in the inference context, where ?fresh is a new type variable.


  • Improve error message when function call doesn't satisfy constraints.
    Currently, the error message is not so good when function argument/return type doesn't satisfy the constraints.
    e.g.,
fn foo<T: Copy>(t: Option<T>, u: T) {}

fn bar() {
    let opt = Some("FOO")
    foo(t: opt, u: "FOO")
}

emits the below error currently.

error[6-0003]: trait bound is not satisfied
   ┌─ foo.fe:12:5
   │
12 │     foo(t: opt, u: "FOO")
   │     ^^^ `String<3>` doesn't implement `Copy`

To address this issue generally, we need to maintain how the generic parameter relates to the argument/return type given by the call site in the type inference phase.

@Y-Nak Y-Nak added the v2 Issues in v2 implementation label Apr 23, 2024
@Y-Nak Y-Nak mentioned this issue Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v2 Issues in v2 implementation
Projects
None yet
Development

No branches or pull requests

1 participant