intellij-rust / intellij-rust

Rust plugin for the IntelliJ Platform
https://intellij-rust.github.io
MIT License
4.54k stars 381 forks source link

Type inference error #6686

Open lovefqy opened 3 years ago

lovefqy commented 3 years ago

Environment

Problem description

Type inference error like this:

use std::cell::RefCell;
use std::rc::Rc;

#[test]
fn foo() {
    struct Item {
        value: usize
    }
    let item: Rc<RefCell<Item>> = Rc::from(RefCell::from(Item { value: 0 as usize }));
//Insert it in to a map
    let key = 0;
    let mut cache = std::collections::HashMap::with_capacity(1);
    cache.insert(key, item.clone());
//and get it as &item
    if let Some(item) = cache.get(&key) {
//IDEA Tips
//mismatched types [E0308] expected `usize`, found `&Item`
//But val is a usize!
        let val: usize = item.borrow().value;
    }
}

Steps to reproduce

In the editor

kumbayo commented 3 years ago

This is an interaction between automatic dereferencing and 2 fields having the same name while one is not accessible. Intellij rust resolves to both of the value fields while rustc ignores the inaccessible of the two. Simplified code:

mod refcell2 { // Necessary to make Ref2.value inaccessible
    use std::ops::Deref;

    pub struct Ref2<'b, T:'b> {
        value: &'b T, //Overlaps with Item.value but is inaccessible
    }

    impl<T> Deref for Ref2<'_, T> {
        type Target = T;

        fn deref(&self) -> &T {
            self.value
        }
    }
}
use refcell2::Ref2;

struct Item {
    value: usize, //Overlaps with Ref2.value but is accessible
}

fn test(r: Ref2<Item>) {
    //OK
    let _val1: usize = (*r).value;

    //mismatched types [E0308] expected `usize`, found `&Item`
    //because it resolves to Item.value and the inaccessible Ref2.value
    let _val2: usize = r.value;
}

image

image

kumbayo commented 3 years ago

This is likely a similar issue as in #6139