Skip to content

When defining types in a function, use statement in impl functions causes unrelated type inference to fail #13895

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

Closed
rben01 opened this issue Jan 5, 2023 · 2 comments · Fixed by #13897
Labels
A-hir hir and hir-def related A-ty type system / type inference / traits / method resolution C-bug Category: bug

Comments

@rben01
Copy link

rben01 commented Jan 5, 2023

rust-analyzer version: 0.3.1334-standalone (74ae2dd 2022-12-25)

rustc version: rustc 1.67.0-nightly

relevant settings: None?

Description

In a particular context, type inference fails and RA does not show the type of a variable assigned to a function's return value. This is caused by the presence of a use statement in a function.

Steps to reproduce

  1. Inside an outer function definition...
  2. Define one struct, S1
  3. And give S1 a method get_pair(self) that returns a 2-tuple
  4. Define a second struct, S2, that contains an instance of S1
  5. And give S2 a method that both 1. has a use statement and 2. calls s1.get_pair()

Bug

The presence of the use statement causes type inference of the return type of s1.get_pair() to fail

Code snippet

As far as I know this snippet is minimal.

fn f() {
	struct S1;

	impl S1 {
		fn get_one(self) -> i32 {
			0
		}
		fn get_pair(self) -> (i32, i32) {
			(0, 0)
		}
	}

	struct S2 {
		s1: S1,
	}

	impl S2 {
		fn no_fail_1(self) -> i32 {
			use std::path;
			let x = self.s1.get_one(); // let x: i32
			x
		}

		fn no_fail_2(self) -> i32 {
			let pair = self.s1.get_pair(); // let pair: (i32, i32)
			pair.0
		}

		fn fail(self) -> i32 {
			use std::path;
			let pair = self.s1.get_pair(); // let pair: {unknown}
			pair.0
		}
	}
}

Screenshots

image

image

@bvanjoi
Copy link
Contributor

bvanjoi commented Jan 6, 2023

It maybe that function can't go to its definition correctly. For example, if we change the content of S2::no_fail_1 to:

use std::path;
let x = self.s1.get_one();
1

The type of x will become unkonwn:

image


reducing:

fn f1() {
    struct S1;
    impl S1 {
        fn e() -> () {}
         //^
    }
    fn f2() {
        struct S2;
        S1::e$0();
    }
}

@lowr
Copy link
Contributor

lowr commented Jan 6, 2023

Impl items declared in a block are "otherwise identical in meaning to declaring the item inside a module" but it seems we're only considering those that are decalred in the the nearest ancestor block module that contains items (hence use statement being significant). Relevant function is this.

@lowr lowr added A-ty type system / type inference / traits / method resolution C-bug Category: bug A-hir hir and hir-def related labels Jan 6, 2023
@bors bors closed this as completed in 75877d7 Jan 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-hir hir and hir-def related A-ty type system / type inference / traits / method resolution C-bug Category: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants