Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Iterator::map not recognized on Chars
![image](https://user-images.githubusercontent.com/308347/71561669-2dc19d80-2a82-11ea-9d3b-eeb65b5212ab.png)

![image](https://user-images.githubusercontent.com/308347/71561674-3914c900-2a82-11ea-95f9-519cb3f58ed4.png)

Possibly related: `Vec::iter` shows up as `{unknown}`, but `Vec::into_iter` works. `map` works on both (!).

![image](https://user-images.githubusercontent.com/308347/71561680-4df15c80-2a82-11ea-8b33-34b342b1296b.png)

EDIT: Actually no, `into_iter` doesn't give the type either.

Pull request:
Fix various names, e.g. Iterator not resolving in core prelude
Basically, `Iterator` is re-exported via several steps, which happened to not be
resolved yet when we got to the prelude import, but since the name resolved to
the reexport from `core::iter` (just to no actual items), we gave up trying to
resolve it further.

Maybe part of the problem is that we can have
`PartialResolvedImport::Unresolved` or `PartialResolvedImport::Indeterminate`
with `None` in all namespaces, and handle them differently.

Fixes #2683.

Patch:
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 35b852ee21..7499dff313 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -328,7 +328,7 @@ where
             );
 
             let def = res.resolved_def;
-            if res.reached_fixedpoint == ReachedFixedPoint::No {
+            if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
                 return PartialResolvedImport::Unresolved;
             }
 


Test patch:
diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
index e800cc68e4..22103ab290 100644
--- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs
@@ -52,6 +52,51 @@ fn nested_module_resolution() {
     "###);
 }
 
+#[test]
+fn nested_module_resolution_2() {
+    let map = def_map(
+        "
+        //- /lib.rs
+        mod prelude;
+        mod iter;
+
+        //- /prelude.rs
+        pub use crate::iter::Iterator;
+
+        //- /iter.rs
+        pub use self::traits::Iterator;
+        mod traits;
+
+        //- /iter/traits.rs
+        pub use self::iterator::Iterator;
+        mod iterator;
+
+        //- /iter/traits/iterator.rs
+        pub trait Iterator;
+        ",
+    );
+
+    assert_snapshot!(map, @r###"
+    crate
+    iter: t
+    prelude: t
+    
+    crate::iter
+    Iterator: t
+    traits: t
+    
+    crate::iter::traits
+    Iterator: t
+    iterator: t
+    
+    crate::iter::traits::iterator
+    Iterator: t
+    
+    crate::prelude
+    Iterator: t
+    "###);
+}
+
 #[test]
 fn module_resolution_works_for_non_standard_filenames() {
     let map = def_map(
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 6c5d39549a..aa948dcbfb 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -2,6 +2,8 @@ use insta::assert_snapshot;
 use test_utils::covers;
 
 use super::infer;
+use crate::test_db::TestDB;
+use ra_db::fixture::WithFixture;
 
 #[test]
 fn bug_484() {
@@ -399,3 +401,55 @@ fn test() {
     "###
     );
 }
+
+#[test]
+fn issue_2683_chars_impl() {
+    let (db, pos) = TestDB::with_position(
+        r#"
+//- /main.rs crate:main deps:std
+fn test() {
+    let chars: std::str::Chars<'_>;
+    (chars.next(), chars.nth(1))<|>;
+}
+
+//- /std.rs crate:std
+#[prelude_import]
+use prelude::*;
+
+pub mod prelude {
+    pub use crate::iter::Iterator;
+    pub use crate::option::Option;
+}
+
+pub mod iter {
+    pub use self::traits::Iterator;
+    pub mod traits {
+        pub use self::iterator::Iterator;
+
+        pub mod iterator {
+            pub trait Iterator {
+                type Item;
+                fn next(&mut self) -> Option<Self::Item>;
+                fn nth(&mut self, n: usize) -> Option<Self::Item> {}
+            }
+        }
+    }
+}
+
+pub mod option {
+    pub enum Option<T> {}
+}
+
+pub mod str {
+    pub struct Chars<'a> {}
+    impl<'a> Iterator for Chars<'a> {
+        type Item = char;
+        fn next(&mut self) -> Option<char> {}
+    }
+}
+"#,
+    );
+
+    // should be Option<char>, but currently not because of Chalk ambiguity problem
+    assert_eq!("(Option<{unknown}>, Option<{unknown}>)", super::type_at_pos(&db, pos));
+}