-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Better inlay hints in 'for' loops #5997
Conversation
This test uses the IntoIterator trait functionality that is a part of stdlib. There are existing ways to emulate the functionality you need: https://github.com/rust-analyzer/rust-analyzer/blob/251ef93ac3bbb138a2eedf6090f2f56f1a15d898/crates/hir_ty/src/tests/traits.rs#L164-L201 So I wonder, if you can reuse this somehow. |
Well, after a bit of shallow experimenting (like code below, + several different attempts to play with Sad to admit, but I need more assistance on that matter. #[test]
fn complete_for_hint() {
check(
r#"
//- /main.rs crate:main deps:core,alloc
fn main() {
let mut data = Vec::new();
data.push("foo");
for i in data {
//^ &str
i;
//^ &str
}
}
//- /core.rs crate:core
#[prelude_import] use iter::*;
mod iter {
trait IntoIterator {
type Item;
}
}
//- /alloc.rs crate:alloc deps:core
mod collections {
struct Vec<T> {}
impl<T> Vec<T> {
fn new() -> Self { Vec {} }
fn push(&mut self, t: T) { }
}
impl<T> IntoIterator for Vec<T> {
type Item=T;
}
}
"#,
); |
In this case the best bet would be to ping Matklad next week after his vacation. I might try to take a stab at this later, but cannot guarantee anything now alas. |
Sure, it's not an emergency :) |
I've checked your test a bit, looks like there was an issue with the compilation. #[test]
fn complete_for_hint() {
check(
r#"
//- /main.rs crate:main deps:core
pub struct Vec<T> {}
impl<T> Vec<T> {
pub fn new() -> Self { Vec {} }
pub fn push(&mut self, t: T) {}
}
impl<T> IntoIterator for Vec<T> {
type Item=T;
}
fn main() {
let mut data = Vec::new();
//^^^^^^^^ Vec<&str>
data.push("foo");
for i in data {
let z = i;
//^ &str
}
} The test fails still, it appears to me that it happens due to the trait solving: the actual I see the following options:
|
Thanks for that info! Unfortunately, after some experimenting I was still unable to make I guess I'll just wait for Matklad to get back from vacation, and implement whatever he'll find appropriate. |
@matklad , any approach you can think of? I think there should be a test, but the most feasible one seems to be the slow test. |
Yeah, I plan to look into this today. The TL;DR is that #5997 (comment) should work, but we probably should fix our testing infra to at least not have two independent testing infras :-) |
Here's somewhat similar demand for the Iterator : https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/.233750 So we might need to come up with some good way to test the iterators' hints. |
Didn't get to making core-aware tests easier per se, but I've at least removed duplication between IDE and hir tests: #6123. After this, I think #5997 (comment) should work. |
Nice! Will check that tomorrow. |
Yup, the following test now works: #[test]
fn complete_for_hint() {
check(
r#"
//- /main.rs crate:main deps:core
pub struct Vec<T> {}
impl<T> Vec<T> {
pub fn new() -> Self { Vec {} }
pub fn push(&mut self, t: T) {}
}
impl<T> IntoIterator for Vec<T> {
type Item=T;
}
fn main() {
let mut data = Vec::new();
//^^^^^^^^ Vec<&str>
data.push("foo");
for i in data {
//^ &str
let z = i;
//^ &str
}
}
//- /core.rs crate:core
#[prelude_import] use iter::*;
mod iter {
trait IntoIterator {
type Item;
}
}
//- /alloc.rs crate:alloc deps:core
mod collections {
struct Vec<T> {}
impl<T> Vec<T> {
fn new() -> Self { Vec {} }
fn push(&mut self, t: T) { }
}
impl<T> IntoIterator for Vec<T> {
type Item=T;
}
}
"#,
);
} |
9241698
to
a58441a
Compare
Yay, it works! I also had to remove Hopefully, new |
@@ -249,6 +251,14 @@ fn should_not_display_type_hint( | |||
return it.condition().and_then(|condition| condition.pat()).is_some() | |||
&& pat_is_enum_variant(db, bind_pat, pat_ty); | |||
}, | |||
ast::ForExpr(it) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nit: I think we can make it more readable by writing something like
// We *should* display hint only if user provided "in {expr}" and we know the type of expr (and it's not unit).
// Type of expr should be iterable.
return it.in_token().is_none() ||
it.iterable()
.and_then(|iterable_expr|sema.type_of_expr(&iterable_expr))
.map(|iterable_ty| iterable_ty.is_unknown() || iterable_ty.is_unit())
.unwrap_or(true)
Thanks for a good motivation to fix our testing infra, I've managed to submit a long stalled PR because of this. bors d+ |
✌️ popzxc can now approve this pull request. To approve and merge a pull request, simply reply with |
Interesting, I get the It looks like RA takes |
Yeah, I thought about this case and was not sure if such a situation should be handled at all. Once
These examples are roughly equivalent, and the meaning (and expected behavior) is not expressed in the code, it's just in the head of code author. In my opinion, once Otherwise we can stuck writing exceptions for heuristics. |
bors r+ |
6262: Do not spawn redundant hints r=SomeoneToIgnore a=popzxc Closes #5206 This is a second part of the fix (first was #5997). This PR adds a new method to the `CompletionContext`: `no_completion_required`. If this method returns `true`, it essentially means that user is unlikely to expect any hints from the IDE at this cursor position. Currently, checks for the following cases were added: - Previous item is `fn`: user creates a new function, names of existing functions won't be helpful. Exception for this case is `impl Foo for Bar` -- we must suggest trait function names. - User entered `for _ i<|>`: it's obviously going to be `in` keyword, any hints here will be confusing. More checks may be added there later, but currently I've only figured two cases. ![no_redundant_hints](https://user-images.githubusercontent.com/12111581/96332088-da4d2a00-106a-11eb-89a1-1159ece18f9d.png) Co-authored-by: Igor Aleksanov <[email protected]>
For #5206 (one part of the fix).
This PR refines the logic of spawning an inlay hints in
for
loops. We only must provide a hint if the following criteria are met:in
keyword.However: I don't know why, but I was unable to make
complete_for_hint
test work. Either without or with my changes, I was always getting this test failed because no hint was spawned for the loop variable.This change works locally, so I would really appreciate an explanation why this test isn't working now and how to fix it.