diff --git a/src/racer/ast.rs b/src/racer/ast.rs index 14aefa84..d9687a2a 100644 --- a/src/racer/ast.rs +++ b/src/racer/ast.rs @@ -527,7 +527,17 @@ impl<'c, 's, 'ast> visit::Visitor<'ast> for ExprTypeVisitor<'c, 's> { .and_then(|ty| path_to_match(ty, self.session)) } MatchType::Method(ref gen) => { - typeinf::get_return_type_of_function(&m, &m, self.session).and_then( + let mut return_ty = typeinf::get_return_type_of_function(&m, &m, self.session); + // Account for already resolved generics if the return type is Self + // (in which case we return bare type as found in the `impl` header) + if let (Some(Ty::Match(ref mut m)), Some(gen)) = (&mut return_ty, gen) { + for (type_param, arg) in m.generics_mut().zip(gen.args()) { + if let Some(resolved) = arg.resolved() { + type_param.resolve(resolved.clone()); + } + } + } + return_ty.and_then( |ty| { path_to_match_including_generics( ty, diff --git a/src/racer/matchers.rs b/src/racer/matchers.rs index 6868fba8..cf79d9fd 100644 --- a/src/racer/matchers.rs +++ b/src/racer/matchers.rs @@ -425,8 +425,27 @@ fn match_mod_inner( } fn find_generics_end(blob: &str) -> Option { + // Naive version that attempts to skip over attributes + let mut in_attr = false; + let mut attr_level = 0; + let mut level = 0; for (i, b) in blob.as_bytes().into_iter().enumerate() { + // Naively skip attributes `#[...]` + if in_attr { + match b { + b'[' => attr_level += 1, + b']' => { + attr_level -=1; + if attr_level == 0 { + in_attr = false; + continue; + } + }, + _ => continue, + } + } + // ...otherwise just try to find the last `>` match b { b'{' | b'(' | b';' => return None, b'<' => level += 1, @@ -436,6 +455,7 @@ fn find_generics_end(blob: &str) -> Option { return Some(i.into()); } } + b'#' if blob.bytes().nth(i + 1) == Some(b'[') => in_attr = true, _ => {} } } @@ -871,3 +891,24 @@ pub fn match_impl(decl: String, context: &MatchCxt<'_, '_>, offset: BytePos) -> } Some(out) } + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn find_generics_end() { + use super::find_generics_end; + assert_eq!( + find_generics_end("Vec"), + Some(BytePos(64)) + ); + assert_eq!( + find_generics_end("Vec"), + Some(BytePos(27)) + ); + assert_eq!( + find_generics_end("Result, Option<&str>>"), + Some(BytePos(32)) + ); + } +}