Repository: racer-rust/racer (language: rust)

Issue:
racer crashes on standard library completion
Apologies in advance if this is something I did fundamentally wrong.

The following code:

    fn main() {
        let s = "Foo".as_bytes(); 
        let t: std::slice::Iter = s.
    }

Fails to produce any autocompletion for the `s.` part. Completion for string "Foo" and the std::slice:Iter parts work correctly. 
RUST_SRC_PATH is set to ~/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/src as intended.
I am using the latest build of racer on MacOS and racer produces the following backtrace:

> thread 'searcher' panicked at 'load file successfully: Os { code: 2, kind: NotFound, message: "No such file or directory" }', libcore/result.rs:1009:5
> note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
>    0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
>    1: std::sys_common::backtrace::_print
>    2: std::panicking::default_hook::{{closure}}
>    3: std::panicking::default_hook
>    4: std::panicking::rust_panic_with_hook
>    5: std::panicking::continue_panic_fmt
>    6: rust_begin_unwind
>    7: core::panicking::panic_fmt
>    8: core::result::unwrap_failed
>    9: racer::core::FileCache::load_file
>   10: <racer::core::Session<'c> as racer::core::SessionExt>::load_source_file
>   11: racer::nameres::search_for_impls
>   12: racer::nameres::search_for_impl_methods
>   13: <racer::ast::ExprTypeVisitor<'c, 's> as syntax::visit::Visitor<'ast>>::visit_expr
>   14: <racer::ast::LetTypeVisitor<'c, 's> as syntax::visit::Visitor<'ast>>::visit_local
>   15: <scoped_tls::ScopedKey<T>>::set
>   16: syntax::with_globals
>   17: racer::typeinf::get_type_of_match
>   18: <racer::ast::ExprTypeVisitor<'c, 's> as syntax::visit::Visitor<'ast>>::visit_expr
>   19: <scoped_tls::ScopedKey<T>>::set
>   20: syntax::with_globals
>   21: racer::ast::get_type_of
>   22: racer::core::complete_from_file_
>   23: racer::run_the_complete_fn
> ERROR 2018-11-21T17:51:33.469582000Z: racer: Search thread paniced: Any
> END

Is it something on my end?



Discussion / hints:
Hello, I'm facing the same issue - I get the same 

> thread 'searcher' panicked at 'load file successfully: Os { code: 2, kind: NotFound, message: "No such file or directory" }', libcore/result.rs:1009:5

error.
Following are a couple more examples where auto-complete fails, in case further illustration is necessary:
```
fn f0(s: &str) {
    for l in s.lines {
        // does not auto complete:
        if l.
    }
}

fn f1(s: &String) {
    for l in s.lines() {
        // auto completes
        if l.c
    }
}

fn main() {
    let s = String::from("");
    for l in s.lines() {
        //auto completes:
        if l.c
    }
}
```
@btoninho 
Really thanks for opening this issue!
More precise debug info:
```
thread 'searcher' panicked at 'Failed load file "": Os { code: 2, kind: NotFound, message: "No such file or directory" }', libcore/result.rs:1009:5
```
It looks racer searches a file named "" :thinking: 

Fix patch:
diff --git a/src/racer/ast.rs b/src/racer/ast.rs
index 74321b67..5357c323 100644
--- a/src/racer/ast.rs
+++ b/src/racer/ast.rs
@@ -616,13 +616,11 @@ impl<'c, 's, 'ast> visit::Visitor<'ast> for ExprTypeVisitor<'c, 's> {
                 self.visit_expr(objexpr);
                 let result = self.result.take();
                 let get_method_output_ty = |contextm: Match| {
-                    let matching_methods = nameres::search_for_impl_methods(
-                        &contextm,
+                    let matching_methods = nameres::search_for_fields_and_methods(
+                        contextm.clone(),
                         &methodname,
-                        contextm.point,
-                        &contextm.filepath,
-                        contextm.local,
                         core::SearchType::ExactMatch,
+                        true,
                         self.session,
                     );
                     matching_methods
@@ -788,7 +786,9 @@ impl<'c, 's, 'ast> visit::Visitor<'ast> for ExprTypeVisitor<'c, 's> {
                 self.visit_expr(right);
                 let right_expr_type = match self.result.take() {
                     Some(Ty::Match(m)) => Some(m.matchstr),
-                    Some(Ty::PathSearch(ps)) => ps.resolve_as_match(self.session).map(|m| m.matchstr),
+                    Some(Ty::PathSearch(ps)) => {
+                        ps.resolve_as_match(self.session).map(|m| m.matchstr)
+                    }
                     _ => None,
                 };
                 self.result = nameres::resolve_binary_expr_type(
diff --git a/src/racer/core.rs b/src/racer/core.rs
index e09266f1..c16f1492 100644
--- a/src/racer/core.rs
+++ b/src/racer/core.rs
@@ -783,7 +783,7 @@ impl FileCache {
         let source = self
             .loader
             .load_file(filepath)
-            .expect("load file successfully");
+            .expect(&format!("Failed load file {:?}", filepath));
         let source = Rc::new(RawSource::new(source));
         self.raw_map
             .borrow_mut()
diff --git a/src/racer/nameres.rs b/src/racer/nameres.rs
index 7889e9c4..d713a44e 100644
--- a/src/racer/nameres.rs
+++ b/src/racer/nameres.rs
@@ -1775,7 +1775,8 @@ pub fn resolve_path(
                     namespace,
                     session,
                     import_info,
-                ).unwrap_or_else(Vec::new);
+                )
+                .unwrap_or_else(Vec::new);
             }
             _ => {}
         }
@@ -1854,16 +1855,13 @@ fn resolve_global_path(
     );
     for (i, seg) in segs {
         let cxt = context.into_iter().next()?;
-        let is_last =  i + 1 == path.segments.len();
-        let stype = if is_last { search_type } else { SearchType::ExactMatch };
-        context = resolve_following_path(
-            cxt,
-            seg,
-            namespace,
-            stype,
-            import_info,
-            session
-        );
+        let is_last = i + 1 == path.segments.len();
+        let stype = if is_last {
+            search_type
+        } else {
+            SearchType::ExactMatch
+        };
+        context = resolve_following_path(cxt, seg, namespace, stype, import_info, session);
     }
     Some(context)
 }
@@ -2181,10 +2179,11 @@ fn collect_inherited_traits(trait_match: Match, s: &Session) -> Vec<Match> {
     res
 }
 
-pub fn search_for_field_or_method(
+pub fn search_for_fields_and_methods(
     context: Match,
     searchstr: &str,
     search_type: SearchType,
+    only_methods: bool,
     session: &Session,
 ) -> Vec<Match> {
     let m = context;
@@ -2195,8 +2194,10 @@ pub fn search_for_field_or_method(
                 "got a struct, looking for fields and impl methods!! {}",
                 m.matchstr
             );
-            for m in search_struct_fields(searchstr, &m, search_type, session) {
-                out.push(m);
+            if !only_methods {
+                for m in search_struct_fields(searchstr, &m, search_type, session) {
+                    out.push(m);
+                }
             }
             for m in search_for_impl_methods(
                 &m,
@@ -2329,9 +2330,9 @@ pub(crate) fn get_field_matches_from_ty(
     session: &Session,
 ) -> Vec<Match> {
     match ty {
-        Ty::Match(m) => search_for_field_or_method(m, searchstr, stype, session),
+        Ty::Match(m) => search_for_fields_and_methods(m, searchstr, stype, false, session),
         Ty::PathSearch(paths) => paths.resolve_as_match(session).map_or_else(Vec::new, |m| {
-            search_for_field_or_method(m, searchstr, stype, session)
+            search_for_fields_and_methods(m, searchstr, stype, false, session)
         }),
         Ty::Self_(scope) => {
             let msrc = session.load_source_file(&scope.filepath);
@@ -2343,7 +2344,9 @@ pub(crate) fn get_field_matches_from_ty(
                 session,
             );
             match ty {
-                Some(Ty::Match(m)) => search_for_field_or_method(m, searchstr, stype, session),
+                Some(Ty::Match(m)) => {
+                    search_for_fields_and_methods(m, searchstr, stype, false, session)
+                }
                 _ => Vec::new(),
             }
         }
@@ -2355,7 +2358,7 @@ pub(crate) fn get_field_matches_from_ty(
         Ty::Array(_, _) | Ty::Slice(_) => {
             let mut m = primitive::PrimKind::Slice.to_module_match().unwrap();
             m.matchstr = "[T]".to_owned();
-            search_for_field_or_method(m, searchstr, stype, session)
+            search_for_fields_and_methods(m, searchstr, stype, false, session)
         }
         Ty::TraitObject(traitbounds) => traitbounds
             .into_iter()
diff --git a/src/racer/typeinf.rs b/src/racer/typeinf.rs
index b88a49be..12e3b2ea 100644
--- a/src/racer/typeinf.rs
+++ b/src/racer/typeinf.rs
@@ -1,7 +1,6 @@
 //! Type inference
 //! THIS MODULE IS ENTIRELY TOO UGLY SO REALLY NEADS REFACTORING(kngwyu)
 use ast;
-use syntax::ast::BinOpKind;
 use ast_types::{Pat, Ty};
 use core;
 use core::{
@@ -12,6 +11,7 @@ use nameres;
 use primitive::PrimKind;
 use scopes;
 use std::path::Path;
+use syntax::ast::BinOpKind;
 use util::{self, txt_matches};
 
 // Removes the body of the statement (anything in the braces {...}), leaving just


Test patch:
diff --git a/tests/system.rs b/tests/system.rs
index 734a34e5..6cc8cc77 100644
--- a/tests/system.rs
+++ b/tests/system.rs
@@ -3820,3 +3820,15 @@ fn test_resolve_global_path_in_modules() {
         assert_eq!(got.matchstr, "new");
     })
 }
+
+#[test]
+fn completes_methods_for_as_bytes() {
+    let src = r#"
+fn main() {
+    let s = "Foo".as_bytes(); 
+    let t = s.conca~
+}
+"#;
+    let got = get_only_completion(src, None);
+    assert_eq!(got.matchstr, "concat");
+}