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

Poor interaction between int fallback and other flow of type information #23545

Open
aturon opened this Issue Mar 20, 2015 · 8 comments

Comments

Projects
None yet
7 participants
@aturon
Copy link
Member

aturon commented Mar 20, 2015

A reduced example:

use std::ops::Shl;

struct Foo<T>(T);

impl<T> Shl<usize> for Foo<T> {
    type Output = Foo<T>;
    fn shl(self, _: usize) -> Foo<T> { self }
}

impl<T> Shl<i32> for Foo<T> {
    type Output = Foo<T>;
    fn shl(self, _: i32) -> Foo<T> { self }
}

fn main() {
    let _ = Foo(0u32) << 2; // works fine

    let _ = (Foo(0u32) << 2).0; // does not work

    let x = Foo(0u32) << 2; // does not work
    let _ = x.0;

    let x: Foo<u32> = Foo(0u32) << 2; // works
    let _ = x.0;
}

generates the following error:

<anon>:18:13: 18:31 error: the type of this value must be known in this context
<anon>:18     let _ = (Foo(0u32) << 2).0; // does not work
                      ^~~~~~~~~~~~~~~~~~
<anon>:21:13: 21:16 error: the type of this value must be known in this context
<anon>:21     let _ = x.0;
                      ^~~

I suspect what is happening here is that the fallback isn't being triggered early enough -- in particular, before the projection is generating the error. Note that the same problem occurs with a normal struct.

(This may be one reason that Shl/Shr are only implemented on usize for Wrapping<T>.)

@aturon

This comment has been minimized.

Copy link
Member Author

aturon commented Mar 20, 2015

@aturon aturon added the A-typesystem label Mar 20, 2015

@aturon

This comment has been minimized.

Copy link
Member Author

aturon commented Mar 20, 2015

Another example, with the new inherent methods:

fn main() {
    let _ = 32_u8.count_zeros();  // works
    let _ = 32.count_zeros(); // does not work
}
@pnkfelix

This comment was marked as resolved.

Copy link
Member

pnkfelix commented Apr 1, 2015

cc me

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Apr 4, 2015

These examples so far seem to be "working as designed". That is, we do not do fallback early in the cycle, but only after we've gotten to the end, and we currently do require some type-directed actions (like field access) to have resolved types, for better or worse. We could do work on the type system to make it less... eager. In other words, it should generate deferred constraints and try to solve them. That is sort of the general fix to this problem I guess.

@bluss

This comment has been minimized.

Copy link
Contributor

bluss commented May 3, 2015

This code says

let x = 1.;
let y = x.min(2.); // error: type `_` does not implement any method in scope named `min`

The last line puzzled me the most here. I went about to tell Rust a type to use, still no dice.

[1., 2., 3.].iter().fold(1./0., |acc, &x| f32::min(acc, x)); // OK
[1., 2., 3.].iter().fold(1./0., |acc, &x| acc.min(x)); // error: type `_` does not implement any method in scope named `min`
[1.0_f32, 2., 3.].iter().fold(1./0., |acc, &x| acc.min(x)); // error: type `_` does not implement any method in scope named `min`
@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Jan 5, 2016

@nikomatsakis The interesting thing about 32.count_zeros() is that it would totally work if count_zeroes came from a trait because we coalesce those into one signature (the trait's view of the method).

Couldn't we do something similar for an inherent method present on multiple integer types?

I guess we would need a way to represent <_>::count_zeroes, not fully selected, which we currently don't have (trait methods are easy because they have HIR nodes and DefIds).

@nikomatsakis

This comment has been minimized.

Copy link
Contributor

nikomatsakis commented Jan 6, 2016

On Tue, Jan 05, 2016 at 02:27:31PM -0800, Eduard-Mihai Burtescu wrote:

@nikomatsakis The interesting thing about 32.count_zeros() is that it would totally work if count_zeroes came from a trait because we coalesce those into one signature (the trait's view of the method).

Couldn't we do something similar for an inherent method present on multiple integer types?

Possibly, but it'd be very hard-coded.

I guess we would need a way to represent <_>::count_zeroes, not fully selected, which we currently don't have (trait methods are easy because they have HIR nodes and DefIds).

Yes. I suspect this is eminently doable. I've been thinking about it
in the context of wanting to do a ground-up rewrite of typeck, but of
course that's an ambitious (and perhaps foolhardy) way of going about
things, perhaps I should look to see if we could do something more
targeted. The current setup is certainly a common source of annoyance.

@steveklabnik

This comment has been minimized.

Copy link
Member

steveklabnik commented Sep 24, 2018

Triage: no change

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.