1 use crate::ast_types::Path as RacerPath;
2 use crate::ast_types::{
3     self, GenericsArgs, ImplHeader, Pat, PathAlias, PathAliasKind, TraitBounds, Ty,
4 };
5 use crate::core::{self, BytePos, ByteRange, Match, MatchType, Scope, Session, SessionExt};
6 use crate::nameres;
7 use crate::typeinf;
8 
9 use std::path::Path;
10 use std::rc::Rc;
11 
12 use rustc_ast::ast::{self, ExprKind, FnRetTy, ItemKind, PatKind, UseTree, UseTreeKind};
13 use rustc_ast::{self, visit};
14 use rustc_data_structures::sync::Lrc;
15 use rustc_errors::emitter::Emitter;
16 use rustc_errors::{Diagnostic, Handler};
17 use rustc_parse::new_parser_from_source_str;
18 use rustc_parse::parser::{ForceCollect, Parser};
19 use rustc_session::parse::ParseSess;
20 use rustc_span::edition::Edition;
21 use rustc_span::source_map::{self, FileName, SourceMap};
22 use rustc_span::Span;
23 
24 struct DummyEmitter;
25 
26 impl Emitter for DummyEmitter {
emit_diagnostic(&mut self, _db: &Diagnostic)27     fn emit_diagnostic(&mut self, _db: &Diagnostic) {}
source_map(&self) -> Option<&Lrc<SourceMap>>28     fn source_map(&self) -> Option<&Lrc<SourceMap>> {
29         None
30     }
should_show_explain(&self) -> bool31     fn should_show_explain(&self) -> bool {
32         false
33     }
34 }
35 
36 /// construct parser from string
37 // From syntax/util/parser_testing.rs
string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_>38 pub fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> {
39     new_parser_from_source_str(ps, FileName::Custom("racer-file".to_owned()), source_str)
40 }
41 
42 /// Get parser from string s and then apply closure f to it
43 // TODO: use Result insated of Option
with_error_checking_parse<F, T>(s: String, f: F) -> Option<T> where F: FnOnce(&mut Parser<'_>) -> Option<T>,44 pub fn with_error_checking_parse<F, T>(s: String, f: F) -> Option<T>
45 where
46     F: FnOnce(&mut Parser<'_>) -> Option<T>,
47 {
48     // FIXME: Set correct edition based on the edition of the target crate.
49     rustc_span::with_session_globals(Edition::Edition2018, || {
50         let codemap = Rc::new(SourceMap::new(source_map::FilePathMapping::empty()));
51         // We use DummyEmitter here not to print error messages to stderr
52         let handler = Handler::with_emitter(false, None, Box::new(DummyEmitter {}));
53         let parse_sess = ParseSess::with_span_handler(handler, codemap);
54 
55         let mut p = string_to_parser(&parse_sess, s);
56         f(&mut p)
57     })
58 }
59 
60 /// parse string source_str as statement and then apply f to it
61 /// return false if we can't parse s as statement
62 // TODO: make F FnOnce(&ast::Stmt) -> Result<Something, Error>
with_stmt<F>(source_str: String, f: F) -> bool where F: FnOnce(&ast::Stmt),63 pub fn with_stmt<F>(source_str: String, f: F) -> bool
64 where
65     F: FnOnce(&ast::Stmt),
66 {
67     with_error_checking_parse(source_str, |p| {
68         let stmt = match p.parse_stmt(ForceCollect::No) {
69             Ok(Some(stmt)) => stmt,
70             _ => return None,
71         };
72         f(&stmt);
73         Some(())
74     })
75     .is_some()
76 }
77 
destruct_span(span: Span) -> (u32, u32)78 pub(crate) fn destruct_span(span: Span) -> (u32, u32) {
79     let source_map::BytePos(lo) = span.lo();
80     let source_map::BytePos(hi) = span.hi();
81     (lo, hi)
82 }
83 
get_span_start(span: Span) -> u3284 pub(crate) fn get_span_start(span: Span) -> u32 {
85     let source_map::BytePos(lo) = span.lo();
86     lo
87 }
88 
89 /// collect paths from syntax::ast::UseTree
90 #[derive(Debug)]
91 pub struct UseVisitor {
92     pub path_list: Vec<PathAlias>,
93     pub contains_glob: bool,
94 }
95 
96 impl<'ast> visit::Visitor<'ast> for UseVisitor {
visit_item(&mut self, i: &ast::Item)97     fn visit_item(&mut self, i: &ast::Item) {
98         // collect items from use tree recursively
99         // returns (Paths, contains_glab)
100         fn collect_nested_items(
101             use_tree: &UseTree,
102             parent_path: Option<&ast_types::Path>,
103         ) -> (Vec<PathAlias>, bool) {
104             let mut res = vec![];
105             let mut path = if let Some(parent) = parent_path {
106                 let relative_path = RacerPath::from_ast_nogen(&use_tree.prefix);
107                 let mut path = parent.clone();
108                 path.extend(relative_path);
109                 path
110             } else {
111                 RacerPath::from_ast_nogen(&use_tree.prefix)
112             };
113             let mut contains_glob = false;
114             match use_tree.kind {
115                 UseTreeKind::Simple(rename, _, _) => {
116                     let ident = use_tree.ident().name.to_string();
117                     let rename_pos: Option<BytePos> =
118                         rename.map(|id| destruct_span(id.span).0.into());
119                     let kind = if let Some(last_seg) = path.segments.last() {
120                         //` self` is treated normaly in libsyntax,
121                         //  but we distinguish it here to make completion easy
122                         if last_seg.name == "self" {
123                             PathAliasKind::Self_(ident, rename_pos)
124                         } else {
125                             PathAliasKind::Ident(ident, rename_pos)
126                         }
127                     } else {
128                         PathAliasKind::Ident(ident, rename_pos)
129                     };
130                     if let PathAliasKind::Self_(..) = kind {
131                         path.segments.pop();
132                     }
133                     res.push(PathAlias {
134                         kind,
135                         path,
136                         range: ByteRange::from(use_tree.span),
137                     });
138                 }
139                 UseTreeKind::Nested(ref nested) => {
140                     nested.iter().for_each(|(ref tree, _)| {
141                         let (items, has_glob) = collect_nested_items(tree, Some(&path));
142                         res.extend(items);
143                         contains_glob |= has_glob;
144                     });
145                 }
146                 UseTreeKind::Glob => {
147                     res.push(PathAlias {
148                         kind: PathAliasKind::Glob,
149                         path,
150                         range: ByteRange::from(use_tree.span),
151                     });
152                     contains_glob = true;
153                 }
154             }
155             (res, contains_glob)
156         }
157         if let ItemKind::Use(ref use_tree) = i.kind {
158             let (path_list, contains_glob) = collect_nested_items(use_tree, None);
159             self.path_list = path_list;
160             self.contains_glob = contains_glob;
161         }
162     }
163 }
164 
165 pub struct PatBindVisitor {
166     ident_points: Vec<ByteRange>,
167 }
168 
169 impl<'ast> visit::Visitor<'ast> for PatBindVisitor {
visit_local(&mut self, local: &ast::Local)170     fn visit_local(&mut self, local: &ast::Local) {
171         // don't visit the RHS (init) side of the let stmt
172         self.visit_pat(&local.pat);
173     }
174 
visit_expr(&mut self, ex: &ast::Expr)175     fn visit_expr(&mut self, ex: &ast::Expr) {
176         // don't visit the RHS or block of an 'if let' or 'for' stmt
177         match &ex.kind {
178             ExprKind::If(let_stmt, ..) | ExprKind::While(let_stmt, ..) => {
179                 if let ExprKind::Let(pat, ..) = &let_stmt.kind {
180                     self.visit_pat(pat);
181                 }
182             }
183             ExprKind::ForLoop(pat, ..) => self.visit_pat(pat),
184             _ => visit::walk_expr(self, ex),
185         }
186     }
187 
visit_pat(&mut self, p: &ast::Pat)188     fn visit_pat(&mut self, p: &ast::Pat) {
189         match p.kind {
190             PatKind::Ident(_, ref spannedident, _) => {
191                 self.ident_points.push(spannedident.span.into());
192             }
193             _ => {
194                 visit::walk_pat(self, p);
195             }
196         }
197     }
198 }
199 
200 pub struct PatVisitor {
201     ident_points: Vec<ByteRange>,
202 }
203 
204 impl<'ast> visit::Visitor<'ast> for PatVisitor {
visit_pat(&mut self, p: &ast::Pat)205     fn visit_pat(&mut self, p: &ast::Pat) {
206         match p.kind {
207             PatKind::Ident(_, ref spannedident, _) => {
208                 self.ident_points.push(spannedident.span.into());
209             }
210             _ => {
211                 visit::walk_pat(self, p);
212             }
213         }
214     }
215 }
216 
217 pub struct FnArgVisitor {
218     idents: Vec<(Pat, Option<Ty>, ByteRange)>,
219     generics: GenericsArgs,
220     scope: Scope,
221     offset: i32,
222 }
223 
224 impl<'ast> visit::Visitor<'ast> for FnArgVisitor {
visit_fn(&mut self, fk: visit::FnKind<'_>, _: source_map::Span, _: ast::NodeId)225     fn visit_fn(&mut self, fk: visit::FnKind<'_>, _: source_map::Span, _: ast::NodeId) {
226         let fd = match fk {
227             visit::FnKind::Fn(_, _, ref fn_sig, _, _) => &*fn_sig.decl,
228             visit::FnKind::Closure(ref fn_decl, _) => fn_decl,
229         };
230         debug!("[FnArgVisitor::visit_fn] inputs: {:?}", fd.inputs);
231         self.idents = fd
232             .inputs
233             .iter()
234             .map(|arg| {
235                 debug!("[FnArgTypeVisitor::visit_fn] type {:?} was found", arg.ty);
236                 let pat = Pat::from_ast(&arg.pat.kind, &self.scope);
237                 let ty = Ty::from_ast(&arg.ty, &self.scope);
238                 let source_map::BytePos(lo) = arg.pat.span.lo();
239                 let source_map::BytePos(hi) = arg.ty.span.hi();
240                 (pat, ty, ByteRange::new(lo, hi))
241             })
242             .collect();
243     }
visit_generics(&mut self, g: &'ast ast::Generics)244     fn visit_generics(&mut self, g: &'ast ast::Generics) {
245         let generics = GenericsArgs::from_generics(g, &self.scope.filepath, self.offset);
246         self.generics.extend(generics);
247     }
248 }
249 
point_is_in_span(point: BytePos, span: &Span) -> bool250 fn point_is_in_span(point: BytePos, span: &Span) -> bool {
251     let point: u32 = point.0 as u32;
252     let (lo, hi) = destruct_span(*span);
253     point >= lo && point < hi
254 }
255 
256 // The point must point to an ident within the pattern.
destructure_pattern_to_ty( pat: &ast::Pat, point: BytePos, ty: &Ty, scope: &Scope, session: &Session<'_>, ) -> Option<Ty>257 fn destructure_pattern_to_ty(
258     pat: &ast::Pat,
259     point: BytePos,
260     ty: &Ty,
261     scope: &Scope,
262     session: &Session<'_>,
263 ) -> Option<Ty> {
264     debug!(
265         "destructure_pattern_to_ty point {:?} ty {:?} pat: {:?}",
266         point, ty, pat.kind
267     );
268     match pat.kind {
269         PatKind::Ident(_, ref spannedident, _) => {
270             if point_is_in_span(point, &spannedident.span) {
271                 debug!("destructure_pattern_to_ty matched an ident!");
272                 Some(ty.clone())
273             } else {
274                 panic!(
275                     "Expecting the point to be in the patident span. pt: {:?}",
276                     point
277                 );
278             }
279         }
280         PatKind::Tuple(ref tuple_elements) => match *ty {
281             Ty::Tuple(ref typeelems) => {
282                 for (i, p) in tuple_elements.iter().enumerate() {
283                     if !point_is_in_span(point, &p.span) {
284                         continue;
285                     }
286                     if let Some(ref ty) = typeelems[i] {
287                         return destructure_pattern_to_ty(p, point, ty, scope, session);
288                     }
289                 }
290                 None
291             }
292             _ => panic!("Expecting TyTuple"),
293         },
294         PatKind::TupleStruct(ref path, ref children) => {
295             let m = resolve_ast_path(path, &scope.filepath, scope.point, session)?;
296             let contextty = path_to_match(ty.clone(), session);
297             for (i, p) in children.iter().enumerate() {
298                 if point_is_in_span(point, &p.span) {
299                     return typeinf::get_tuplestruct_field_type(i, &m, session)
300                         .and_then(|ty| {
301                             // if context ty is a match, use its generics
302                             if let Some(Ty::Match(ref contextm)) = contextty {
303                                 path_to_match_including_generics(
304                                     ty,
305                                     contextm.to_generics(),
306                                     session,
307                                 )
308                             } else {
309                                 path_to_match(ty, session)
310                             }
311                         })
312                         .and_then(|ty| destructure_pattern_to_ty(p, point, &ty, scope, session));
313                 }
314             }
315             None
316         }
317         PatKind::Struct(ref path, ref children, _) => {
318             let m = resolve_ast_path(path, &scope.filepath, scope.point, session)?;
319             let contextty = path_to_match(ty.clone(), session);
320             for child in children {
321                 if point_is_in_span(point, &child.span) {
322                     return typeinf::get_struct_field_type(&child.ident.name.as_str(), &m, session)
323                         .and_then(|ty| {
324                             if let Some(Ty::Match(ref contextm)) = contextty {
325                                 path_to_match_including_generics(
326                                     ty,
327                                     contextm.to_generics(),
328                                     session,
329                                 )
330                             } else {
331                                 path_to_match(ty, session)
332                             }
333                         })
334                         .and_then(|ty| {
335                             destructure_pattern_to_ty(&child.pat, point, &ty, scope, session)
336                         });
337                 }
338             }
339             None
340         }
341         _ => {
342             debug!("Could not destructure pattern {:?}", pat);
343             None
344         }
345     }
346 }
347 
348 struct LetTypeVisitor<'c, 's> {
349     scope: Scope,
350     session: &'s Session<'c>,
351     pos: BytePos, // pos is relative to the srctxt, scope is global
352     result: Option<Ty>,
353 }
354 
355 impl<'c, 's, 'ast> visit::Visitor<'ast> for LetTypeVisitor<'c, 's> {
visit_local(&mut self, local: &ast::Local)356     fn visit_local(&mut self, local: &ast::Local) {
357         let ty = match &local.ty {
358             Some(annon) => Ty::from_ast(&*annon, &self.scope),
359             None => local.init.as_ref().and_then(|initexpr| {
360                 debug!("[LetTypeVisitor] initexpr is {:?}", initexpr.kind);
361                 let mut v = ExprTypeVisitor::new(self.scope.clone(), self.session);
362                 v.visit_expr(initexpr);
363                 v.result
364             }),
365         };
366         debug!("[LetTypeVisitor] ty is {:?}. pos is {:?}", ty, self.pos);
367         self.result = ty
368             .and_then(|ty| {
369                 destructure_pattern_to_ty(&local.pat, self.pos, &ty, &self.scope, self.session)
370             })
371             .and_then(|ty| path_to_match(ty, self.session));
372     }
373 }
374 
375 struct MatchTypeVisitor<'c, 's> {
376     scope: Scope,
377     session: &'s Session<'c>,
378     pos: BytePos, // pos is relative to the srctxt, scope is global
379     result: Option<Ty>,
380 }
381 
382 impl<'c, 's, 'ast> visit::Visitor<'ast> for MatchTypeVisitor<'c, 's> {
visit_expr(&mut self, ex: &ast::Expr)383     fn visit_expr(&mut self, ex: &ast::Expr) {
384         if let ExprKind::Match(ref subexpression, ref arms) = ex.kind {
385             debug!("PHIL sub expr is {:?}", subexpression);
386 
387             let mut v = ExprTypeVisitor::new(self.scope.clone(), self.session);
388             v.visit_expr(subexpression);
389 
390             debug!("PHIL sub type is {:?}", v.result);
391 
392             for arm in arms {
393                 if !point_is_in_span(self.pos, &arm.pat.span) {
394                     continue;
395                 }
396                 debug!("PHIL point is in pattern |{:?}|", arm.pat);
397                 self.result = v
398                     .result
399                     .as_ref()
400                     .and_then(|ty| {
401                         destructure_pattern_to_ty(&arm.pat, self.pos, ty, &self.scope, self.session)
402                     })
403                     .and_then(|ty| path_to_match(ty, self.session));
404             }
405         }
406     }
407 }
408 
resolve_ast_path( path: &ast::Path, filepath: &Path, pos: BytePos, session: &Session<'_>, ) -> Option<Match>409 fn resolve_ast_path(
410     path: &ast::Path,
411     filepath: &Path,
412     pos: BytePos,
413     session: &Session<'_>,
414 ) -> Option<Match> {
415     let scope = Scope::new(filepath.to_owned(), pos);
416     let path = RacerPath::from_ast(path, &scope);
417     nameres::resolve_path_with_primitive(
418         &path,
419         filepath,
420         pos,
421         core::SearchType::ExactMatch,
422         core::Namespace::Path,
423         session,
424     )
425     .into_iter()
426     .nth(0)
427 }
428 
path_to_match(ty: Ty, session: &Session<'_>) -> Option<Ty>429 fn path_to_match(ty: Ty, session: &Session<'_>) -> Option<Ty> {
430     match ty {
431         Ty::PathSearch(paths) => {
432             find_type_match(&paths.path, &paths.filepath, paths.point, session).map(Ty::Match)
433         }
434         Ty::RefPtr(ty, _) => path_to_match(*ty, session),
435         _ => Some(ty),
436     }
437 }
438 
find_type_match( path: &RacerPath, fpath: &Path, pos: BytePos, session: &Session<'_>, ) -> Option<Match>439 pub(crate) fn find_type_match(
440     path: &RacerPath,
441     fpath: &Path,
442     pos: BytePos,
443     session: &Session<'_>,
444 ) -> Option<Match> {
445     debug!("find_type_match {:?}, {:?}", path, fpath);
446     let mut res = nameres::resolve_path_with_primitive(
447         path,
448         fpath,
449         pos,
450         core::SearchType::ExactMatch,
451         core::Namespace::Type,
452         session,
453     )
454     .into_iter()
455     .nth(0)
456     .and_then(|m| match m.mtype {
457         MatchType::Type => typeinf::get_type_of_typedef(&m, session),
458         _ => Some(m),
459     })?;
460     // TODO: 'Type' support
461     // if res is Enum/Struct and has a generic type paramter, let's resolve it.
462     for (param, typ) in res.generics_mut().zip(path.generic_types()) {
463         param.resolve(typ.to_owned());
464     }
465     Some(res)
466 }
467 
468 struct ExprTypeVisitor<'c, 's> {
469     scope: Scope,
470     session: &'s Session<'c>,
471     // what we have before calling typeinf::get_type_of_match
472     path_match: Option<Match>,
473     result: Option<Ty>,
474 }
475 
476 impl<'c: 's, 's> ExprTypeVisitor<'c, 's> {
new(scope: Scope, session: &'s Session<'c>) -> Self477     fn new(scope: Scope, session: &'s Session<'c>) -> Self {
478         ExprTypeVisitor {
479             scope,
480             session,
481             path_match: None,
482             result: None,
483         }
484     }
same_scope(&self) -> Self485     fn same_scope(&self) -> Self {
486         Self {
487             scope: self.scope.clone(),
488             session: self.session,
489             path_match: None,
490             result: None,
491         }
492     }
493 }
494 
495 impl<'c, 's, 'ast> visit::Visitor<'ast> for ExprTypeVisitor<'c, 's> {
visit_expr(&mut self, expr: &ast::Expr)496     fn visit_expr(&mut self, expr: &ast::Expr) {
497         debug!(
498             "ExprTypeVisitor::visit_expr {:?}(kind: {:?})",
499             expr, expr.kind
500         );
501         //walk_expr(self, ex, e)
502         match expr.kind {
503             ExprKind::Unary(_, ref expr) | ExprKind::AddrOf(_, _, ref expr) => {
504                 self.visit_expr(expr);
505             }
506             ExprKind::Path(_, ref path) => {
507                 let source_map::BytePos(lo) = path.span.lo();
508                 self.result = resolve_ast_path(
509                     path,
510                     &self.scope.filepath,
511                     self.scope.point + lo.into(),
512                     self.session,
513                 )
514                 .and_then(|m| {
515                     let msrc = self.session.load_source_file(&m.filepath);
516                     self.path_match = Some(m.clone());
517                     typeinf::get_type_of_match(m, msrc.as_src(), self.session)
518                 });
519             }
520             ExprKind::Call(ref callee_expression, ref caller_expr) => {
521                 self.visit_expr(callee_expression);
522                 self.result = self.result.take().and_then(|m| {
523                     if let Ty::Match(mut m) = m {
524                         match m.mtype {
525                             MatchType::Function => {
526                                 typeinf::get_return_type_of_function(&m, &m, self.session)
527                                     .and_then(|ty| path_to_match(ty, self.session))
528                             }
529                             MatchType::Method(ref gen) => {
530                                 let mut return_ty = typeinf::get_return_type_of_function(&m, &m, self.session);
531                                 // Account for already resolved generics if the return type is Self
532                                 // (in which case we return bare type as found in the `impl` header)
533                                 if let (Some(Ty::Match(ref mut m)), Some(gen)) = (&mut return_ty, gen) {
534                                     for (type_param, arg) in m.generics_mut().zip(gen.args()) {
535                                         if let Some(resolved) = arg.resolved() {
536                                             type_param.resolve(resolved.clone());
537                                         }
538                                     }
539                                 }
540                                 return_ty.and_then(
541                                     |ty| {
542                                         path_to_match_including_generics(
543                                             ty,
544                                             gen.as_ref().map(AsRef::as_ref),
545                                             self.session,
546                                         )
547                                     },
548                                 )
549                             }
550                             // if we find tuple struct / enum variant, try to resolve its generics name
551                             MatchType::Struct(ref mut gen)
552                             | MatchType::Enum(ref mut gen)
553                             | MatchType::Union(ref mut gen) => {
554                                 if gen.is_empty() {
555                                     return Some(Ty::Match(m));
556                                 }
557                                 let tuple_fields = match self.path_match {
558                                     Some(ref m) => typeinf::get_tuplestruct_fields(m, self.session),
559                                     None => return Some(Ty::Match(m)),
560                                 };
561                                 // search what is in callee e.g. Some(String::new()<-) for generics
562                                 for ((_, _, ty), expr) in tuple_fields.into_iter().zip(caller_expr)
563                                 {
564                                     let ty = try_continue!(ty).dereference();
565                                     if let Ty::PathSearch(paths) = ty {
566                                         let (id, _) =
567                                             try_continue!(gen.search_param_by_path(&paths.path));
568                                         let mut visitor = self.same_scope();
569                                         visitor.visit_expr(expr);
570                                         if let Some(ty) = visitor.result {
571                                             gen.0[id].resolve(ty.dereference());
572                                         }
573                                     }
574                                 }
575                                 Some(Ty::Match(m))
576                             }
577                             MatchType::TypeParameter(ref traitbounds)
578                                 if traitbounds.has_closure() =>
579                             {
580                                 let mut output = None;
581                                 if let Some(path_search) = traitbounds.get_closure() {
582                                     for seg in path_search.path.segments.iter() {
583                                         if seg.output.is_some() {
584                                             output = seg.output.clone();
585                                             break;
586                                         }
587                                     }
588                                 }
589                                 output
590                             }
591                             _ => {
592                                 debug!(
593                                     "ExprTypeVisitor: Cannot handle ExprCall of {:?} type",
594                                     m.mtype
595                                 );
596                                 None
597                             }
598                         }
599                     } else {
600                         None
601                     }
602                 });
603             }
604             ExprKind::Struct(ref struct_expr) => {
605                 let ast::StructExpr { ref path, .. } = **struct_expr;
606                 let pathvec = RacerPath::from_ast(path, &self.scope);
607                 self.result = find_type_match(
608                     &pathvec,
609                     &self.scope.filepath,
610                     self.scope.point,
611                     self.session,
612                 )
613                 .map(Ty::Match);
614             }
615             ExprKind::MethodCall(ref method_def, ref arguments, _) => {
616                 let methodname = method_def.ident.name.as_str();
617                 debug!("method call ast name {}", methodname);
618 
619                 // arguments[0] is receiver(e.g. self)
620                 let objexpr = &arguments[0];
621                 self.visit_expr(objexpr);
622                 let result = self.result.take();
623                 let get_method_output_ty = |contextm: Match| {
624                     let matching_methods = nameres::search_for_fields_and_methods(
625                         contextm.clone(),
626                         &methodname,
627                         core::SearchType::ExactMatch,
628                         true,
629                         self.session,
630                     );
631                     matching_methods
632                         .into_iter()
633                         .filter_map(|method| {
634                             let ty = typeinf::get_return_type_of_function(
635                                 &method,
636                                 &contextm,
637                                 self.session,
638                             )?;
639                             path_to_match_including_generics(
640                                 ty,
641                                 contextm.to_generics(),
642                                 self.session,
643                             )
644                         })
645                         .nth(0)
646                 };
647                 self.result = result.and_then(|ty| {
648                     ty.resolve_as_field_match(self.session)
649                         .and_then(get_method_output_ty)
650                 });
651             }
652             ExprKind::Field(ref subexpression, spannedident) => {
653                 let fieldname = spannedident.name.to_string();
654                 debug!("exprfield {}", fieldname);
655                 self.visit_expr(subexpression);
656                 let result = self.result.take();
657                 let match_to_field_ty = |structm: Match| {
658                     typeinf::get_struct_field_type(&fieldname, &structm, self.session).and_then(
659                         |fieldtypepath| {
660                             find_type_match_including_generics(
661                                 fieldtypepath,
662                                 &structm.filepath,
663                                 structm.point,
664                                 &structm,
665                                 self.session,
666                             )
667                         },
668                     )
669                 };
670                 self.result = result.and_then(|ty| {
671                     ty.resolve_as_field_match(self.session)
672                         .and_then(match_to_field_ty)
673                 });
674             }
675             ExprKind::Tup(ref exprs) => {
676                 let mut v = Vec::new();
677                 for expr in exprs {
678                     self.visit_expr(expr);
679                     v.push(self.result.take());
680                 }
681                 self.result = Some(Ty::Tuple(v));
682             }
683             ExprKind::Lit(ref lit) => self.result = Ty::from_lit(lit),
684             ExprKind::Try(ref expr) => {
685                 self.visit_expr(&expr);
686                 debug!("ExprKind::Try result: {:?} expr: {:?}", self.result, expr);
687                 self.result = if let Some(&Ty::Match(ref m)) = self.result.as_ref() {
688                     // HACK for speed up (kngwyu)
689                     // Yeah there're many corner cases but it'll work well in most cases
690                     if m.matchstr == "Result" || m.matchstr == "Option" {
691                         debug!("Option or Result: {:?}", m);
692                         m.resolved_generics().next().map(|x| x.to_owned())
693                     } else {
694                         debug!("Unable to desugar Try expression; type was {:?}", m);
695                         None
696                     }
697                 } else {
698                     None
699                 };
700             }
701             ExprKind::Match(_, ref arms) => {
702                 debug!("match expr");
703 
704                 for arm in arms {
705                     self.visit_expr(&arm.body);
706 
707                     // All match arms need to return the same result, so if we found a result
708                     // we can end the search.
709                     if self.result.is_some() {
710                         break;
711                     }
712                 }
713             }
714             ExprKind::If(_, ref block, ref else_block) => {
715                 debug!("if/iflet expr");
716                 if let Some(stmt) = block.stmts.last() {
717                     visit::walk_stmt(self, stmt);
718                 }
719                 if self.result.is_some() {
720                     return;
721                 }
722                 // if the block does not resolve to a type, try the else block
723                 if let Some(expr) = else_block {
724                     self.visit_expr(expr);
725                 }
726             }
727             ExprKind::Block(ref block, ref _label) => {
728                 debug!("block expr");
729                 if let Some(stmt) = block.stmts.last() {
730                     visit::walk_stmt(self, stmt);
731                 }
732             }
733             ExprKind::Index(ref body, ref _index) => {
734                 self.visit_expr(body);
735                 // TODO(kngwyu) now we don't have support for literal so don't parse index
736                 // but in the future, we should handle index's type
737                 self.result = self
738                     .result
739                     .take()
740                     .and_then(|ty| typeinf::get_type_of_indexed_value(ty, self.session));
741             }
742             ExprKind::Array(ref exprs) => {
743                 for expr in exprs {
744                     self.visit_expr(expr);
745                     if self.result.is_some() {
746                         self.result = self
747                             .result
748                             .take()
749                             .map(|ty| Ty::Array(Box::new(ty), format!("{}", exprs.len())));
750                         break;
751                     }
752                 }
753                 if self.result.is_none() {
754                     self.result = Some(Ty::Array(Box::new(Ty::Unsupported), String::new()));
755                 }
756             }
757             ExprKind::MacCall(ref m) => {
758                 if let Some(name) = m.path.segments.last().map(|seg| seg.ident) {
759                     // use some ad-hoc rules
760                     if name.as_str() == "vec" {
761                         let path = RacerPath::from_iter(
762                             true,
763                             ["std", "vec", "Vec"].iter().map(|s| s.to_string()),
764                         );
765                         self.result = find_type_match(
766                             &path,
767                             &self.scope.filepath,
768                             self.scope.point,
769                             self.session,
770                         )
771                         .map(Ty::Match);
772                     }
773                 }
774             }
775             ExprKind::Binary(bin, ref left, ref right) => {
776                 self.visit_expr(left);
777                 let type_match = match self.result.take() {
778                     Some(Ty::Match(m)) => m,
779                     Some(Ty::PathSearch(ps)) => match ps.resolve_as_match(self.session) {
780                         Some(m) => m,
781                         _ => {
782                             return;
783                         }
784                     },
785                     _ => {
786                         return;
787                     }
788                 };
789 
790                 self.visit_expr(right);
791                 let right_expr_type = match self.result.take() {
792                     Some(Ty::Match(m)) => Some(m.matchstr),
793                     Some(Ty::PathSearch(ps)) => {
794                         ps.resolve_as_match(self.session).map(|m| m.matchstr)
795                     }
796                     _ => None,
797                 };
798                 self.result = nameres::resolve_binary_expr_type(
799                     &type_match,
800                     bin.node,
801                     right_expr_type.as_ref().map(|s| s.as_str()),
802                     self.session,
803                 );
804             }
805             _ => {
806                 debug!("- Could not match expr node type: {:?}", expr.kind);
807             }
808         };
809     }
810     /// Just do nothing if we see a macro, but also prevent the panic! in the default impl.
visit_mac_call(&mut self, _mac: &ast::MacCall)811     fn visit_mac_call(&mut self, _mac: &ast::MacCall) {}
812 }
813 
814 // gets generics info from the context match
path_to_match_including_generics( mut ty: Ty, generics: Option<&GenericsArgs>, session: &Session<'_>, ) -> Option<Ty>815 fn path_to_match_including_generics(
816     mut ty: Ty,
817     generics: Option<&GenericsArgs>,
818     session: &Session<'_>,
819 ) -> Option<Ty> {
820     if let Some(gen) = generics {
821         ty = ty.replace_by_generics(gen);
822     }
823     match ty {
824         Ty::PathSearch(paths) => {
825             let fieldtypepath = &paths.path;
826             find_type_match(&fieldtypepath, &paths.filepath, paths.point, session).map(Ty::Match)
827         }
828         _ => Some(ty),
829     }
830 }
831 
find_type_match_including_generics( fieldtype: Ty, filepath: &Path, pos: BytePos, structm: &Match, session: &Session<'_>, ) -> Option<Ty>832 fn find_type_match_including_generics(
833     fieldtype: Ty,
834     filepath: &Path,
835     pos: BytePos,
836     structm: &Match,
837     session: &Session<'_>,
838 ) -> Option<Ty> {
839     assert_eq!(&structm.filepath, filepath);
840     let fieldtypepath = match fieldtype {
841         Ty::PathSearch(paths) => paths.path,
842         Ty::RefPtr(ty, _) => match ty.dereference() {
843             Ty::PathSearch(paths) => paths.path,
844             Ty::Match(m) => return Some(Ty::Match(m)),
845             _ => return None,
846         },
847         // already resolved
848         Ty::Match(m) => return Some(Ty::Match(m)),
849         _ => {
850             return None;
851         }
852     };
853     let generics = match &structm.mtype {
854         MatchType::Struct(gen) => gen,
855         _ => return None,
856     };
857     if fieldtypepath.segments.len() == 1 {
858         // could be a generic arg! - try and resolve it
859         if let Some((_, param)) = generics.search_param_by_path(&fieldtypepath) {
860             if let Some(res) = param.resolved() {
861                 return Some(res.to_owned());
862             }
863             let mut m = param.to_owned().into_match();
864             m.local = structm.local;
865             return Some(Ty::Match(m));
866         }
867     }
868 
869     find_type_match(&fieldtypepath, filepath, pos, session).map(Ty::Match)
870 }
871 
872 struct StructVisitor {
873     pub scope: Scope,
874     pub fields: Vec<(String, ByteRange, Option<Ty>)>,
875 }
876 
877 impl<'ast> visit::Visitor<'ast> for StructVisitor {
visit_variant_data(&mut self, struct_definition: &ast::VariantData)878     fn visit_variant_data(&mut self, struct_definition: &ast::VariantData) {
879         for field in struct_definition.fields() {
880             let ty = Ty::from_ast(&field.ty, &self.scope);
881             let name = match field.ident {
882                 Some(ref ident) => ident.to_string(),
883                 // name unnamed field by its ordinal, since self.0 works
884                 None => format!("{}", self.fields.len()),
885             };
886             self.fields.push((name, field.span.into(), ty));
887         }
888     }
889 }
890 
891 #[derive(Debug)]
892 pub struct TypeVisitor<'s> {
893     pub name: Option<String>,
894     pub type_: Option<Ty>,
895     scope: &'s Scope,
896 }
897 
898 impl<'ast, 's> visit::Visitor<'ast> for TypeVisitor<'s> {
visit_item(&mut self, item: &ast::Item)899     fn visit_item(&mut self, item: &ast::Item) {
900         if let ItemKind::TyAlias(ref ty_kind) = item.kind {
901             if let Some(ref ty) = ty_kind.3 {
902                 self.name = Some(item.ident.name.to_string());
903                 self.type_ = Ty::from_ast(&ty, self.scope);
904                 debug!("typevisitor type is {:?}", self.type_);
905             }
906         }
907     }
908 }
909 
910 pub struct TraitVisitor {
911     pub name: Option<String>,
912 }
913 
914 impl<'ast> visit::Visitor<'ast> for TraitVisitor {
visit_item(&mut self, item: &ast::Item)915     fn visit_item(&mut self, item: &ast::Item) {
916         if let ItemKind::Trait(..) = item.kind {
917             self.name = Some(item.ident.name.to_string());
918         }
919     }
920 }
921 
922 #[derive(Debug)]
923 pub struct ImplVisitor<'p> {
924     pub result: Option<ImplHeader>,
925     filepath: &'p Path,
926     offset: BytePos,
927     block_start: BytePos, // the point { appears
928     local: bool,
929 }
930 
931 impl<'p> ImplVisitor<'p> {
new(filepath: &'p Path, offset: BytePos, local: bool, block_start: BytePos) -> Self932     fn new(filepath: &'p Path, offset: BytePos, local: bool, block_start: BytePos) -> Self {
933         ImplVisitor {
934             result: None,
935             filepath,
936             offset,
937             block_start,
938             local,
939         }
940     }
941 }
942 
943 impl<'ast, 'p> visit::Visitor<'ast> for ImplVisitor<'p> {
visit_item(&mut self, item: &ast::Item)944     fn visit_item(&mut self, item: &ast::Item) {
945         if let ItemKind::Impl(ref impl_kind) = item.kind {
946             let ast::ImplKind {
947                 ref generics,
948                 ref of_trait,
949                 ref self_ty,
950                 ..
951             } = **impl_kind;
952             let impl_start = self.offset + get_span_start(item.span).into();
953             self.result = ImplHeader::new(
954                 generics,
955                 self.filepath,
956                 of_trait,
957                 self_ty,
958                 self.offset,
959                 self.local,
960                 impl_start,
961                 self.block_start,
962             );
963         }
964     }
965 }
966 
967 pub struct ExternCrateVisitor {
968     pub name: Option<String>,
969     pub realname: Option<String>,
970 }
971 
972 impl<'ast> visit::Visitor<'ast> for ExternCrateVisitor {
visit_item(&mut self, item: &ast::Item)973     fn visit_item(&mut self, item: &ast::Item) {
974         if let ItemKind::ExternCrate(ref optional_s) = item.kind {
975             self.name = Some(item.ident.name.to_string());
976             if let Some(ref istr) = *optional_s {
977                 self.realname = Some(istr.to_string());
978             }
979         }
980     }
visit_mac_call(&mut self, _mac: &ast::MacCall)981     fn visit_mac_call(&mut self, _mac: &ast::MacCall) {}
982 }
983 
984 #[derive(Debug)]
985 struct GenericsVisitor<P> {
986     result: GenericsArgs,
987     filepath: P,
988 }
989 
990 impl<'ast, P: AsRef<Path>> visit::Visitor<'ast> for GenericsVisitor<P> {
visit_generics(&mut self, g: &ast::Generics)991     fn visit_generics(&mut self, g: &ast::Generics) {
992         let path = &self.filepath;
993         if !self.result.0.is_empty() {
994             warn!("[visit_generics] called for multiple generics!");
995         }
996         self.result.extend(GenericsArgs::from_generics(g, path, 0));
997     }
998 }
999 
1000 pub struct EnumVisitor {
1001     pub name: String,
1002     pub values: Vec<(String, BytePos)>,
1003 }
1004 
1005 impl<'ast> visit::Visitor<'ast> for EnumVisitor {
visit_item(&mut self, i: &ast::Item)1006     fn visit_item(&mut self, i: &ast::Item) {
1007         if let ItemKind::Enum(ref enum_definition, _) = i.kind {
1008             self.name = i.ident.name.to_string();
1009             let (point1, point2) = destruct_span(i.span);
1010             debug!("name point is {} {}", point1, point2);
1011 
1012             for variant in &enum_definition.variants {
1013                 let source_map::BytePos(point) = variant.span.lo();
1014                 self.values.push((variant.ident.to_string(), point.into()));
1015             }
1016         }
1017     }
1018 }
1019 
1020 #[derive(Clone, Debug)]
1021 pub struct StaticVisitor {
1022     pub ty: Option<Ty>,
1023     pub is_mutable: bool,
1024     scope: Scope,
1025 }
1026 
1027 impl StaticVisitor {
new(scope: Scope) -> Self1028     fn new(scope: Scope) -> Self {
1029         StaticVisitor {
1030             ty: None,
1031             is_mutable: false,
1032             scope,
1033         }
1034     }
1035 }
1036 
1037 impl<'ast> visit::Visitor<'ast> for StaticVisitor {
visit_item(&mut self, i: &ast::Item)1038     fn visit_item(&mut self, i: &ast::Item) {
1039         match i.kind {
1040             ItemKind::Const(_, ref ty, ref _expr) => self.ty = Ty::from_ast(ty, &self.scope),
1041             ItemKind::Static(ref ty, m, ref _expr) => {
1042                 self.is_mutable = m == ast::Mutability::Mut;
1043                 self.ty = Ty::from_ast(ty, &self.scope);
1044             }
1045             _ => {}
1046         }
1047     }
1048 }
1049 
parse_use(s: String) -> UseVisitor1050 pub fn parse_use(s: String) -> UseVisitor {
1051     let mut v = UseVisitor {
1052         path_list: Vec::new(),
1053         contains_glob: false,
1054     };
1055 
1056     // visit::walk_crate can be panic so we don't use it here
1057     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1058     v
1059 }
1060 
parse_pat_bind_stmt(s: String) -> Vec<ByteRange>1061 pub fn parse_pat_bind_stmt(s: String) -> Vec<ByteRange> {
1062     let mut v = PatBindVisitor {
1063         ident_points: Vec::new(),
1064     };
1065     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1066     v.ident_points
1067 }
1068 
parse_struct_fields(s: String, scope: Scope) -> Vec<(String, ByteRange, Option<Ty>)>1069 pub fn parse_struct_fields(s: String, scope: Scope) -> Vec<(String, ByteRange, Option<Ty>)> {
1070     let mut v = StructVisitor {
1071         scope,
1072         fields: Vec::new(),
1073     };
1074     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1075     v.fields
1076 }
1077 
parse_impl( s: String, path: &Path, offset: BytePos, local: bool, scope_start: BytePos, ) -> Option<ImplHeader>1078 pub fn parse_impl(
1079     s: String,
1080     path: &Path,
1081     offset: BytePos,
1082     local: bool,
1083     scope_start: BytePos,
1084 ) -> Option<ImplHeader> {
1085     let mut v = ImplVisitor::new(path, offset, local, scope_start);
1086     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1087     v.result
1088 }
1089 
parse_trait(s: String) -> TraitVisitor1090 pub fn parse_trait(s: String) -> TraitVisitor {
1091     let mut v = TraitVisitor { name: None };
1092     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1093     v
1094 }
1095 
1096 /// parse traits and collect inherited traits as TraitBounds
parse_inherited_traits<P: AsRef<Path>>( s: String, filepath: P, offset: i32, ) -> Option<TraitBounds>1097 pub fn parse_inherited_traits<P: AsRef<Path>>(
1098     s: String,
1099     filepath: P,
1100     offset: i32,
1101 ) -> Option<TraitBounds> {
1102     let mut v = InheritedTraitsVisitor {
1103         result: None,
1104         file_path: filepath,
1105         offset: offset,
1106     };
1107     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1108     v.result
1109 }
1110 
parse_generics(s: String, filepath: &Path) -> GenericsArgs1111 pub fn parse_generics(s: String, filepath: &Path) -> GenericsArgs {
1112     let mut v = GenericsVisitor {
1113         result: GenericsArgs::default(),
1114         filepath: filepath,
1115     };
1116     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1117     v.result
1118 }
1119 
parse_type<'s>(s: String, scope: &'s Scope) -> TypeVisitor<'s>1120 pub fn parse_type<'s>(s: String, scope: &'s Scope) -> TypeVisitor<'s> {
1121     let mut v = TypeVisitor {
1122         name: None,
1123         type_: None,
1124         scope,
1125     };
1126     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1127     v
1128 }
1129 
parse_fn_args_and_generics( s: String, scope: Scope, offset: i32, ) -> (Vec<(Pat, Option<Ty>, ByteRange)>, GenericsArgs)1130 pub fn parse_fn_args_and_generics(
1131     s: String,
1132     scope: Scope,
1133     offset: i32,
1134 ) -> (Vec<(Pat, Option<Ty>, ByteRange)>, GenericsArgs) {
1135     let mut v = FnArgVisitor {
1136         idents: Vec::new(),
1137         generics: GenericsArgs::default(),
1138         scope,
1139         offset,
1140     };
1141     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1142     (v.idents, v.generics)
1143 }
1144 
parse_closure_args(s: String, scope: Scope) -> Vec<(Pat, Option<Ty>, ByteRange)>1145 pub fn parse_closure_args(s: String, scope: Scope) -> Vec<(Pat, Option<Ty>, ByteRange)> {
1146     let mut v = FnArgVisitor {
1147         idents: Vec::new(),
1148         generics: GenericsArgs::default(),
1149         scope,
1150         offset: 0,
1151     };
1152     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1153     v.idents
1154 }
1155 
parse_pat_idents(s: String) -> Vec<ByteRange>1156 pub fn parse_pat_idents(s: String) -> Vec<ByteRange> {
1157     let mut v = PatVisitor {
1158         ident_points: Vec::new(),
1159     };
1160     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1161     debug!("ident points are {:?}", v.ident_points);
1162     v.ident_points
1163 }
1164 
parse_fn_output(s: String, scope: Scope) -> (Option<Ty>, bool)1165 pub fn parse_fn_output(s: String, scope: Scope) -> (Option<Ty>, bool) {
1166     let mut v = FnOutputVisitor::new(scope);
1167     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1168     let FnOutputVisitor { ty, is_async, .. } = v;
1169     (ty, is_async)
1170 }
1171 
parse_extern_crate(s: String) -> ExternCrateVisitor1172 pub fn parse_extern_crate(s: String) -> ExternCrateVisitor {
1173     let mut v = ExternCrateVisitor {
1174         name: None,
1175         realname: None,
1176     };
1177     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1178     v
1179 }
1180 
parse_enum(s: String) -> EnumVisitor1181 pub fn parse_enum(s: String) -> EnumVisitor {
1182     let mut v = EnumVisitor {
1183         name: String::new(),
1184         values: Vec::new(),
1185     };
1186     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1187     v
1188 }
1189 
parse_static(s: String, scope: Scope) -> StaticVisitor1190 pub fn parse_static(s: String, scope: Scope) -> StaticVisitor {
1191     let mut v = StaticVisitor::new(scope);
1192     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1193     v
1194 }
1195 
get_type_of(s: String, fpath: &Path, pos: BytePos, session: &Session<'_>) -> Option<Ty>1196 pub fn get_type_of(s: String, fpath: &Path, pos: BytePos, session: &Session<'_>) -> Option<Ty> {
1197     let startscope = Scope {
1198         filepath: fpath.to_path_buf(),
1199         point: pos,
1200     };
1201 
1202     let mut v = ExprTypeVisitor::new(startscope, session);
1203 
1204     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1205     v.result
1206 }
1207 
1208 // pos points to an ident in the lhs of the stmtstr
get_let_type(s: String, pos: BytePos, scope: Scope, session: &Session<'_>) -> Option<Ty>1209 pub fn get_let_type(s: String, pos: BytePos, scope: Scope, session: &Session<'_>) -> Option<Ty> {
1210     let mut v = LetTypeVisitor {
1211         scope,
1212         session,
1213         pos,
1214         result: None,
1215     };
1216     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1217     v.result
1218 }
1219 
get_match_arm_type( s: String, pos: BytePos, scope: Scope, session: &Session<'_>, ) -> Option<Ty>1220 pub fn get_match_arm_type(
1221     s: String,
1222     pos: BytePos,
1223     scope: Scope,
1224     session: &Session<'_>,
1225 ) -> Option<Ty> {
1226     let mut v = MatchTypeVisitor {
1227         scope,
1228         session,
1229         pos,
1230         result: None,
1231     };
1232     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1233     v.result
1234 }
1235 
1236 pub struct FnOutputVisitor {
1237     scope: Scope,
1238     pub ty: Option<Ty>,
1239     pub is_async: bool,
1240 }
1241 
1242 impl FnOutputVisitor {
new(scope: Scope) -> Self1243     pub(crate) fn new(scope: Scope) -> Self {
1244         FnOutputVisitor {
1245             scope,
1246             ty: None,
1247             is_async: false,
1248         }
1249     }
1250 }
1251 
1252 impl<'ast> visit::Visitor<'ast> for FnOutputVisitor {
visit_fn(&mut self, kind: visit::FnKind<'_>, _: source_map::Span, _: ast::NodeId)1253     fn visit_fn(&mut self, kind: visit::FnKind<'_>, _: source_map::Span, _: ast::NodeId) {
1254         let fd = match kind {
1255             visit::FnKind::Fn(_, _, ref fn_sig, _, _) => &*fn_sig.decl,
1256             visit::FnKind::Closure(ref fn_decl, _) => fn_decl,
1257         };
1258         self.is_async = kind
1259             .header()
1260             .map(|header| header.asyncness.is_async())
1261             .unwrap_or(false);
1262         self.ty = match fd.output {
1263             FnRetTy::Ty(ref ty) => Ty::from_ast(ty, &self.scope),
1264             FnRetTy::Default(_) => Some(Ty::Default),
1265         };
1266     }
1267 }
1268 
1269 /// Visitor to collect Inherited Traits
1270 pub struct InheritedTraitsVisitor<P> {
1271     /// search result(list of Inherited Traits)
1272     result: Option<TraitBounds>,
1273     /// the file trait appears
1274     file_path: P,
1275     /// thecode point 'trait' statement starts
1276     offset: i32,
1277 }
1278 
1279 impl<'ast, P> visit::Visitor<'ast> for InheritedTraitsVisitor<P>
1280 where
1281     P: AsRef<Path>,
1282 {
visit_item(&mut self, item: &ast::Item)1283     fn visit_item(&mut self, item: &ast::Item) {
1284         if let ItemKind::Trait(ref trait_kind) = item.kind {
1285             self.result = Some(TraitBounds::from_generic_bounds(
1286                 &trait_kind.3,
1287                 &self.file_path,
1288                 self.offset,
1289             ));
1290         }
1291     }
1292 }
1293 
1294 /// Visitor for for ~ in .. statement
1295 pub(crate) struct ForStmtVisitor<'r, 's> {
1296     pub(crate) for_pat: Option<Pat>,
1297     pub(crate) in_expr: Option<Ty>,
1298     scope: Scope,
1299     session: &'r Session<'s>,
1300 }
1301 
1302 impl<'ast, 'r, 's> visit::Visitor<'ast> for ForStmtVisitor<'r, 's> {
visit_expr(&mut self, ex: &'ast ast::Expr)1303     fn visit_expr(&mut self, ex: &'ast ast::Expr) {
1304         if let ExprKind::ForLoop(ref pat, ref expr, _, _) = ex.kind {
1305             let for_pat = Pat::from_ast(&pat.kind, &self.scope);
1306             let mut expr_visitor = ExprTypeVisitor::new(self.scope.clone(), self.session);
1307             expr_visitor.visit_expr(expr);
1308             self.in_expr = expr_visitor.result;
1309             self.for_pat = Some(for_pat);
1310         }
1311     }
1312 }
1313 
parse_for_stmt<'r, 's: 'r>( s: String, scope: Scope, session: &'r Session<'s>, ) -> ForStmtVisitor<'r, 's>1314 pub(crate) fn parse_for_stmt<'r, 's: 'r>(
1315     s: String,
1316     scope: Scope,
1317     session: &'r Session<'s>,
1318 ) -> ForStmtVisitor<'r, 's> {
1319     let mut v = ForStmtVisitor {
1320         for_pat: None,
1321         in_expr: None,
1322         scope,
1323         session,
1324     };
1325     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1326     v
1327 }
1328 
1329 /// Visitor for if let / while let statement
1330 pub(crate) struct IfLetVisitor<'r, 's> {
1331     pub(crate) let_pat: Option<Pat>,
1332     pub(crate) rh_expr: Option<Ty>,
1333     scope: Scope,
1334     session: &'r Session<'s>,
1335 }
1336 
1337 impl<'ast, 'r, 's> visit::Visitor<'ast> for IfLetVisitor<'r, 's> {
visit_expr(&mut self, ex: &'ast ast::Expr)1338     fn visit_expr(&mut self, ex: &'ast ast::Expr) {
1339         match &ex.kind {
1340             ExprKind::If(let_stmt, ..) | ExprKind::While(let_stmt, ..) => {
1341                 if let ExprKind::Let(pat, expr) = &let_stmt.kind {
1342                     self.let_pat = Some(Pat::from_ast(&pat.kind, &self.scope));
1343                     let mut expr_visitor = ExprTypeVisitor::new(self.scope.clone(), self.session);
1344                     expr_visitor.visit_expr(expr);
1345                     self.rh_expr = expr_visitor.result;
1346                 }
1347             }
1348             _ => {}
1349         }
1350     }
1351 }
1352 
parse_if_let<'r, 's: 'r>( s: String, scope: Scope, session: &'r Session<'s>, ) -> IfLetVisitor<'r, 's>1353 pub(crate) fn parse_if_let<'r, 's: 'r>(
1354     s: String,
1355     scope: Scope,
1356     session: &'r Session<'s>,
1357 ) -> IfLetVisitor<'r, 's> {
1358     let mut v = IfLetVisitor {
1359         let_pat: None,
1360         rh_expr: None,
1361         scope,
1362         session,
1363     };
1364     with_stmt(s, |stmt| visit::walk_stmt(&mut v, stmt));
1365     v
1366 }
1367