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

Inference replaces bounded type parameter with sole implementer (was: action-at-a-distance regression) #18187

Closed
arielb1 opened this issue Oct 20, 2014 · 5 comments
Assignees

Comments

@arielb1
Copy link
Contributor

arielb1 commented Oct 20, 2014

The following code does not compile:

pub trait ScanCursor {
    fn pop_ws(&self) -> Self;
}

pub struct Cursor;

impl ScanCursor for Cursor {
    fn pop_ws(&self) -> Cursor { unreachable!() }
}

pub trait Scanner {
    fn scan<Cur: ScanCursor>(cursor: &Cur) -> Self;
}

fn main() {
    let cur : Cursor = Cursor;
    // 
    let _tmp = &cur.pop_ws(); // removing this still fails
    // let _ : Stmt = Scanner::scan(_tmp)
    let _ : Stmt = Scanner::scan(&cur.pop_ws());
}

struct Stmt;

// Moving this above main compiles
impl Scanner for Stmt {
    fn scan<Cur: ScanCursor>(cur: &Cur) -> Stmt {
        // Fails to compile
        let _s: Stmt = Scanner::scan(&cur.pop_ws());
        loop{}
   }
}

// Added 2014-10-21
#[cfg(compiles)]
impl ScanCursor for ((),(()),((),(()))) /* or whatever */ {
    fn pop_ws(&self) ->  ((),(()),((),(()))) { unreachable!() }
}

With an error in scan:

<anon>:29:38: 29:51 error: mismatched types: expected `&Cursor`, found `&Cur` (expected struct Cursor, found type parameter)
<anon>:29         let _s: Stmt = Scanner::scan(&cur.pop_ws());
                                               ^~~~~~~~~~~~~
error: aborting due to previous error

However, doing any of the 2 fixes suggested in the comments fixes this, which is strange, as the fixes don't touch the affected function.

The issue started at commit 590a61f788e058d7ae95806f55258bce3ae45567 (2014-10-13), which fixed issue #18019. The code compiles on older version of rustc.

@dwrensha
Copy link
Contributor

Perhaps related to this other action-at-a-distance problem that I recently reported:
#18163

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 21, 2014

@pfalabella encountered a similar issue on IRC, with the code:

use std::num::{One, one};

#[cfg(not(test))]
fn main() {
    let _: Hamming<int> = Hamming::new(0);
}
/// representation of a Hamming number, allows to abstract on how the hamming number is stored
pub trait HammingNumber: Eq + Ord + Mul<Self, Self> + One {
    fn multipliers() -> Self;
}

#[cfg(compiles)]
impl HammingNumber for i64 {
    // returns the multipliers 2, 3 and 5 in the representation for the HammingNumber
    fn multipliers() -> i64 {
        0
    }
}

impl HammingNumber for int {
    // returns the multipliers 2, 3 and 5 in the representation for the HammingNumber
    fn multipliers() -> int {
        0
    }
}

pub struct Hamming<T> {
    // Using a RingBuf as a queue, push to the back, pop from the front
    q2: Vec<T>,
}

impl <T: HammingNumber> Hamming<T> {
    /// Static constructor method
    /// `n` initializes the capacity of the queues
    pub fn new(n: uint) -> Hamming<T> {
        let mut h =
            Hamming{q2: Vec::with_capacity(n),};
        h.q2.push(one());
        h
    }
    /// Pushes the next multiple of `n` (x2, x3, x5) to the queues
    pub fn enqueue(&mut self, n: &T) {
        let two : T = HammingNumber::multipliers();
        self.q2.push(*n * two);
    }
}

Which gives the error

<anon>:44:23: 44:51 error: mismatched types: expected `T`, found `int` (expected type parameter, found int)
<anon>:44         let two : T = HammingNumber::multipliers();

But compiles with --cfg compiles (or if you remove the cfg test).

@arielb1
Copy link
Contributor Author

arielb1 commented Oct 21, 2014

I added a similar #[cfg(compiles)] block to the original code.

The issue seems that when a trait Tr is impl-ed only by a single type A, and you have a function generic over T: Tr, then rustc replaces some of the occurrences of T in the function's body with A.

@arielb1 arielb1 changed the title Inference action-at-a-distance regression Inference replaces bounded type parameter with sole implementer (was: action-at-a-distance regression) Oct 21, 2014
@nrc
Copy link
Member

nrc commented Oct 22, 2014

See #18209 for a much reduced test case

@nikomatsakis nikomatsakis self-assigned this Oct 22, 2014
@nikomatsakis
Copy link
Contributor

Appears to be a dup of #18209, closing. (That is, my patch for #18209 fixes these test cases as well.)

lnicola pushed a commit to lnicola/rust that referenced this issue Oct 8, 2024
Fix: Handle block exprs as modules when finding their parents

Fixes rust-lang#18187
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants