Skip to content

Conversation

SomeoneToIgnore
Copy link
Contributor

@SomeoneToIgnore SomeoneToIgnore commented Feb 12, 2020

Unfortunately, for real cases it does not work as spectacular as in the tests.

The main reason for that is type inference:

  • The callee type here is unknown for many cases
  • The trait solution here is also often ambiguous

That results in trait candidates being rejected, and some real cases not supported.
Example: no imports for String::from_str("test")

@matklad
Copy link
Contributor

matklad commented Feb 12, 2020

Also not that I had to expose AssocContainerId in hir since I need to get traits from the

Yeah, this is unfortunate. I feel that we should more actively try to cut a nice API at the ra_hir boundary. Would something like this #3122 work for you?

@SomeoneToIgnore
Copy link
Contributor Author

Maybe as_assoc_item will do the trick, have to check.

@SomeoneToIgnore
Copy link
Contributor Author

Had tried, almost works for me, but needs one more tweak, commented the PR.

@SomeoneToIgnore
Copy link
Contributor Author

No more AssocContainerId exposition 👍

match self.resolve_path(db, &path_to_method)? {
PathResolution::Def(ModuleDef::Adt(adt)) => {
let ty = adt.ty(db);
iterate_method_candidates(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to do this here?

I would expect that we reoslve assoc functions during type inferece, and record the result in the appropriate map in InferenceResult. Perhaps assoc_resolutions are not properly filled in?

Copy link
Contributor Author

@SomeoneToIgnore SomeoneToIgnore Feb 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That actually comes from a very confusing (to me) SourceAnalyzer behavior: when constructed for a module (as it had been done before in auto_import assist code: https://github.com/rust-analyzer/rust-analyzer/pull/3120/files#diff-9f55419f762ae3317cf277aab2d8e37aL36), it does not resolve anything related to the functions' types.

If constructed for a very small path under the coursor (as it is done now), it magically starts to resolve those types.

I've removed the module syntax search completely since it was redundant, but did not realize that this code is not needed anymore.

Copy link
Contributor Author

@SomeoneToIgnore SomeoneToIgnore Feb 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behavior depends on what the source_binder::find_container function returns and I find it a bit strange, I would expect to be able to resolve all types, including the function-related ones when the whole module code is given to the analyzer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this aspect of SourceAnalyzer is kind of a mess, you need to use the right source analyzer. We really should do something like lifting all sa methods to sb, such that they just work.

Not sure how to make that ergonomic though, because the caller would have to pass in InFile<ast::Foo> things instead of just ast::Foo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is something that has annoyed me as well. It would be nice if working with InFile<>s would be more ergonomic in general, and then we could maybe put more API directly on them 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bwaaaa, why dealing with macros in IDE is so annoying :-(

If I just go with the most obvious API, I get this for, for example, goto type definition:

image

That's way to many layers of Functors :c

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't and_then a monad?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could at least e.g. add a cast<A: AstNode>(&self: InFile<SyntaxNode>) -> Option<InFile<A>>...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, we do need full monadic power here :-(

And yeah, for full generality we need ReaderT monad transformer ;(

I wish we could do a simple Roslyn style api: https://github.com/dotnet/roslyn/wiki/Getting-Started-C%23-Semantic-Analysis

@flodiebold
Copy link
Member

flodiebold commented Feb 12, 2020

I checked String::from_str and it seems that there's an inherent from_str method on String that is defined for cfg(test), I guess we pick that up (wrongly) and so there seems to be no need for an import.

@SomeoneToIgnore
Copy link
Contributor Author

Thanks for checking. Funny, intellij-rust does not provide an import for that function also.

@matklad
Copy link
Contributor

matklad commented Feb 13, 2020

there's an inherent from_str method on String that is defined for cfg(test)

Lol, the person who wrote this sits in front of me :D

I wonder if that 's a problem for us though -- we should handle #[cfg(test)]?

@flodiebold
Copy link
Member

we should handle #[cfg(test)]?

Yeah, we should. I assume we don't do it correctly for libraries? (I.e. we want cfg(test) to be active for crates in the workspace, but not for libraries.) I haven't looked into it, but the call clearly resolves to that.

if proposed_imports.is_empty() {
return None;
}

let mut group = ctx.add_assist_group(format!("Import {}", name_to_import));
let assist_group_name = if proposed_imports.len() == 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wonder if we should just automatically flatten singleton grups at the level of AssistCtx or even the code_actions handler?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, we can do all those things on finish() I think.

@matklad
Copy link
Contributor

matklad commented Feb 13, 2020

Yeah, we should. I assume we don't do it correctly for libraries?

I though so as well, but unfortunately the fix is not this simple. We just don't take cfg into account when loweting impls here.

We only use cfgs in CrateDefMap, which I think uses a different, non-ast based infra

@matklad
Copy link
Contributor

matklad commented Feb 13, 2020

bors r+

bors bot added a commit that referenced this pull request Feb 13, 2020
3120: Support trait auto import r=matklad a=SomeoneToIgnore

Unfortunately, for real cases it does not work as spectacular as in the tests.

The main reason for that is type inference:
* The callee type [here](https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_hir_ty/src/method_resolution.rs#L369) is unknown for many cases
* The trait solution [here](https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ra_hir_ty/src/method_resolution.rs#L399) is also often ambiguous

That results in trait candidates being rejected, and some real cases not supported.
Example: no imports for `String::from_str("test")`

Co-authored-by: Kirill Bulatov <[email protected]>
@bors
Copy link
Contributor

bors bot commented Feb 13, 2020

Build succeeded

  • Rust (macos-latest)
  • Rust (ubuntu-latest)
  • Rust (windows-latest)
  • TypeScript

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

Successfully merging this pull request may close these issues.

4 participants