1use alloc::collections::BTreeMap;
4use alloc::string::{String, ToString};
5use alloc::vec;
6use alloc::vec::Vec;
7
8use proc_macro2::{Ident, Span, TokenTree};
9use quote::ToTokens;
10use syn::visit::Visit;
11use syn::visit_mut::VisitMut;
12
13use crate::alpha::{
14 Renamer, is_unit_path, item_binding, resolve_target_path, single_segment_type_name,
15};
16use crate::form::CanonicalForm;
17use crate::scope::{
18 Binding, BindingId, Domain, FirstSeg, Frame, Inherited, Ns, Origin, Target, TargetSeg,
19};
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum ContextKind {
24 FunctionBody,
26 Block,
28 Arm,
30 Closure,
32}
33
34pub struct Context<'a> {
36 pub kind: ContextKind,
38 pub span: Span,
40 pub item: &'a str,
42}
43
44#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
46pub struct ContextWork {
47 pub contexts: usize,
49 pub input_tokens: usize,
51}
52
53pub fn contexts(file: &syn::File, emit: &mut dyn FnMut(Context<'_>, CanonicalForm)) -> ContextWork {
64 let mut walker = Walker {
65 frames: vec![Frame::default()],
66 mod_frames: BTreeMap::new(),
67 mod_origins: BTreeMap::new(),
68 targets: Vec::new(),
69 item_path: Vec::new(),
70 inline_depth: 0,
71 id: 0,
72 work: ContextWork::default(),
73 emit,
74 };
75 walker.visit_file(file);
76 walker.work
77}
78
79fn source_span_and_leaf_tokens(node: &impl ToTokens) -> (Span, usize) {
81 let mut first = None;
82 let mut last = None;
83 let mut count = 0;
84 for tree in node.to_token_stream() {
85 if first.is_none() {
86 first = Some(tree.span());
87 }
88 last = Some(tree.span());
89 count += leaf_count(&tree);
90 }
91 (
92 match (first, last) {
93 (Some(first), Some(last)) => first.join(last).unwrap_or_else(Span::call_site),
94 _ => Span::call_site(),
95 },
96 count,
97 )
98}
99
100fn leaf_count(tree: &TokenTree) -> usize {
102 match tree {
103 TokenTree::Group(group) => group
104 .stream()
105 .into_iter()
106 .map(|inner| leaf_count(&inner))
107 .sum(),
108 _ => 1,
109 }
110}
111
112fn pat_names(pat: &syn::Pat, out: &mut Vec<String>) {
114 match pat {
115 syn::Pat::Ident(id) => {
116 if !is_unit_path(id) {
117 out.push(id.ident.to_string());
118 }
119 if let Some((_, sub)) = &id.subpat {
120 pat_names(sub, out);
121 }
122 }
123 syn::Pat::Tuple(syn::PatTuple { elems, .. })
124 | syn::Pat::Slice(syn::PatSlice { elems, .. })
125 | syn::Pat::TupleStruct(syn::PatTupleStruct { elems, .. }) => {
126 for pat in elems {
127 pat_names(pat, out);
128 }
129 }
130 syn::Pat::Struct(r#struct) => {
131 for field in &r#struct.fields {
132 pat_names(&field.pat, out);
133 }
134 }
135 syn::Pat::Or(r#or) => {
136 for pat in &r#or.cases {
137 pat_names(pat, out);
138 }
139 }
140 syn::Pat::Reference(syn::PatReference { pat, .. })
141 | syn::Pat::Type(syn::PatType { pat, .. })
142 | syn::Pat::Paren(syn::PatParen { pat, .. })
143 | syn::Pat::Guard(syn::PatGuard { pat, .. }) => pat_names(pat, out),
144 _ => {}
145 }
146}
147
148fn fn_input_names<'a>(inputs: impl Iterator<Item = &'a syn::FnArg>) -> Vec<String> {
150 let mut out = Vec::new();
151 for input in inputs {
152 if let syn::FnArg::Typed(pat_type) = input {
153 pat_names(&pat_type.pat, &mut out);
154 }
155 }
156 out
157}
158
159fn prebind_items<'a>(
161 frames: &mut Vec<Frame>,
162 mod_frames: &mut BTreeMap<BindingId, Frame>,
163 mod_origins: &mut BTreeMap<*const syn::ItemMod, BindingId>,
164 id: &mut usize,
165 items: impl Iterator<Item = &'a syn::Item>,
166) {
167 for item in items {
168 let (ns, ident, standard, origin) = if let syn::Item::ExternCrate(item) = item {
169 (
170 Ns::Type,
171 item.rename.as_ref().map_or(&item.ident, |(_, alias)| alias),
172 crate::macros::MacroResolution::external_crate(item),
173 Origin::Use,
174 )
175 } else if let Some((ns, ident)) = item_binding(item) {
176 (ns, ident, None, Origin::Item)
177 } else {
178 continue;
179 };
180 let binding_id = BindingId(*id);
181 *id += 1;
182 let name = ident.to_string();
183 frames.last_mut().expect("a scope frame").bind(
184 ns,
185 &name,
186 Binding {
187 id: binding_id,
188 canon: String::new(),
189 origin,
190 prim: None,
191 port: 0,
192 value_port: None,
193 target: None,
194 raw: false,
195 helper: None,
196 macro_resolution: standard,
197 },
198 );
199 if let syn::Item::Mod(
200 module @ syn::ItemMod {
201 content: Some((_, sub_items)),
202 ..
203 },
204 ) = item
205 {
206 mod_origins.insert(core::ptr::from_ref(module), binding_id);
207 frames.push(Frame::default());
208 prebind_items(frames, mod_frames, mod_origins, id, sub_items.iter());
209 let frame = frames.pop().expect("a scope frame");
210 mod_frames.insert(binding_id, frame);
211 }
212 }
213}
214
215fn self_type_string(self_ty: &syn::Type) -> String {
217 self_ty.to_token_stream().to_string()
218}
219
220struct Walker<'w> {
222 frames: Vec<Frame>,
224 mod_frames: BTreeMap<BindingId, Frame>,
226 mod_origins: BTreeMap<*const syn::ItemMod, BindingId>,
229 targets: Vec<Target>,
231 item_path: Vec<String>,
233 inline_depth: usize,
235 id: usize,
237 work: ContextWork,
239 emit: &'w mut dyn FnMut(Context<'_>, CanonicalForm),
241}
242
243impl Walker<'_> {
244 fn bind(&mut self, ns: Ns, name: &str, origin: Origin) -> BindingId {
246 let binding_id = BindingId(self.id);
247 self.id += 1;
248 self.top_bind(
249 ns,
250 name,
251 Binding {
252 id: binding_id,
253 canon: String::new(),
254 origin,
255 prim: None,
256 port: 0,
257 value_port: None,
258 target: None,
259 raw: false,
260 helper: None,
261 macro_resolution: None,
262 },
263 );
264 binding_id
265 }
266
267 fn top_bind(&mut self, ns: Ns, name: &str, binding: Binding) {
269 self.frames
270 .last_mut()
271 .expect("a scope frame")
272 .bind(ns, name, binding);
273 }
274
275 fn bind_value_and_type(
277 &mut self,
278 name: &str,
279 target: Option<usize>,
280 origin: Origin,
281 macro_resolution: Option<crate::macros::MacroResolution>,
282 ) -> BindingId {
283 let binding_id = BindingId(self.id);
284 self.id += 1;
285 let binding = Binding {
286 id: binding_id,
287 canon: String::new(),
288 origin,
289 prim: None,
290 port: 0,
291 value_port: None,
292 target,
293 raw: false,
294 helper: None,
295 macro_resolution,
296 };
297 self.top_bind(Ns::Value, name, binding.clone());
298 if origin == Origin::Use {
299 self.top_bind(Ns::Macro, name, binding.clone());
300 }
301 self.top_bind(Ns::Type, name, binding);
302 binding_id
303 }
304
305 fn lookup(&self, ns: &[Ns], name: &str) -> Option<&Binding> {
307 for ns in ns {
308 for frame in self.frames.iter().rev() {
309 if let Some(binding) = frame.lookup(*ns, name) {
310 return Some(binding);
311 }
312 }
313 }
314 None
315 }
316
317 fn bind_item_name(&mut self, ns: Ns, ident: &Ident) -> BindingId {
319 let name = ident.to_string();
320 match self.frames.last().and_then(|frame| frame.lookup(ns, &name)) {
321 Some(binding) => binding.id,
322 None => self.bind(ns, &name, Origin::Item),
323 }
324 }
325
326 fn bind_use_item(&mut self, item: &syn::ItemUse) {
328 self.bind_use_tree(
329 item.leading_colon.is_some(),
330 &[],
331 &item.tree,
332 crate::context::blocking_attr(&item.attrs),
333 );
334 }
335
336 fn bind_scope_uses<'a>(&mut self, uses: impl Iterator<Item = &'a syn::ItemUse>) {
338 for use_item in uses {
339 self.bind_use_item(use_item);
340 }
341 }
342
343 fn bind_use_tree(
345 &mut self,
346 rooted: bool,
347 prefix: &[String],
348 tree: &syn::UseTree,
349 opaque: bool,
350 ) {
351 match tree {
352 syn::UseTree::Path(path) => {
353 let mut prefix = prefix.to_vec();
354 prefix.push(path.ident.to_string());
355 self.bind_use_tree(rooted, &prefix, &path.tree, opaque);
356 }
357 syn::UseTree::Name(name) if name.ident == "self" => {
358 if let Some(alias) = prefix.last() {
360 let segments: Vec<&str> = prefix.iter().map(String::as_str).collect();
361 self.frames.last_mut().expect("a scope frame").std_rebound |=
362 crate::drift::import_rebound(&segments, alias, alias);
363 let (rooted, segments) =
364 resolve_target_path(&|name| self.resolve_first_seg(name), rooted, prefix);
365 self.bind_alias_target(rooted, segments, alias, opaque);
366 }
367 }
368 syn::UseTree::Name(name) => {
369 self.bind_alias_leaf(rooted, prefix, &name.ident, &name.ident, opaque);
370 }
371 syn::UseTree::Rename(rename) => {
372 self.bind_alias_leaf(rooted, prefix, &rename.ident, &rename.rename, opaque);
373 }
374 syn::UseTree::Glob(_) => {
377 self.frames.last_mut().expect("a scope frame").glob = true;
378 let segments: Vec<&str> = prefix.iter().map(String::as_str).collect();
379 if crate::drift::macro_glob(&segments, self.inline_depth) {
380 self.frames.last_mut().expect("a scope frame").std_rebound =
381 crate::drift::ALL_STD_NAMES;
382 }
383 }
384 syn::UseTree::Group(group) => {
385 for tree in &group.items {
386 self.bind_use_tree(rooted, prefix, tree, opaque);
387 }
388 }
389 }
390 }
391
392 fn bind_alias_target(
394 &mut self,
395 rooted: bool,
396 segments: Vec<TargetSeg>,
397 alias: &str,
398 opaque: bool,
399 ) {
400 let target = Target { rooted, segments };
401 let opaque = opaque
402 || self
403 .frames
404 .last()
405 .and_then(|frame| frame.lookup(Ns::Macro, alias))
406 .is_some()
407 || self.lookup(&[Ns::Macro], alias).is_some_and(|binding| {
408 binding.origin == Origin::MacroRule
409 || binding.macro_resolution == Some(crate::macros::MacroResolution::Opaque)
410 });
411 let resolution = if opaque {
412 Some(crate::macros::MacroResolution::Opaque)
413 } else {
414 crate::macros::MacroResolution::external_target(&target)
415 };
416 let index = self.targets.len();
417 self.targets.push(target);
418 self.bind_value_and_type(alias, Some(index), Origin::Use, resolution);
419 }
420
421 fn bind_alias_leaf(
423 &mut self,
424 rooted: bool,
425 prefix: &[String],
426 ident: &Ident,
427 alias: &Ident,
428 opaque: bool,
429 ) {
430 let segments: Vec<&str> = prefix.iter().map(String::as_str).collect();
431 self.frames.last_mut().expect("a scope frame").std_rebound |= crate::drift::import_rebound(
432 &segments,
433 &crate::scope::ident_name(ident),
434 &crate::scope::ident_name(alias),
435 );
436 let mut path = prefix.to_vec();
437 path.push(ident.to_string());
438 let (rooted, segments) =
439 resolve_target_path(&|name| self.resolve_first_seg(name), rooted, &path);
440 self.bind_alias_target(rooted, segments, &alias.to_string(), opaque);
441 }
442
443 fn resolve_first_seg(&self, name: &str) -> FirstSeg<'_> {
445 match self.lookup(&[Ns::Type], name) {
446 Some(binding) if binding.target.is_some() => {
447 let index = binding.target.expect("a target index");
448 FirstSeg::Alias(self.targets.get(index).expect("a target index"))
449 }
450 Some(binding) => FirstSeg::Module(Domain::Inherited, binding.id),
451 None => FirstSeg::Free,
452 }
453 }
454
455 fn begin_generics(&mut self, generics: &syn::Generics) {
457 self.frames.push(Frame::default());
458 for param in &generics.params {
459 match param {
460 syn::GenericParam::Lifetime(lifetime) => {
461 self.bind(
462 Ns::Lifetime,
463 &lifetime.lifetime.ident.to_string(),
464 Origin::Lifetime,
465 );
466 }
467 syn::GenericParam::Type(ty_param) => {
468 self.bind(Ns::Type, &ty_param.ident.to_string(), Origin::Generic);
469 }
470 syn::GenericParam::Const(r#const) => {
471 self.bind_value_and_type(
473 &r#const.ident.to_string(),
474 None,
475 Origin::Generic,
476 None,
477 );
478 }
479 }
480 }
481 }
482
483 fn visit_fn(&mut self, sig: &syn::Signature, body: &syn::Block) {
485 self.begin_generics(&sig.generics);
486 self.frames.push(Frame::default());
487 for name in fn_input_names(sig.inputs.iter()) {
488 self.bind(Ns::Value, &name, Origin::Parameter);
489 }
490 syn::visit::visit_signature(self, sig);
491 let (span, input_tokens) = source_span_and_leaf_tokens(body);
492 let inherited = Inherited {
493 frames: &self.frames,
494 mod_frames: &self.mod_frames,
495 targets: &self.targets,
496 };
497 let form = build_function_body_form(inherited, body, sig.asyncness.is_none());
498 self.emit_candidate(ContextKind::FunctionBody, span, input_tokens, form);
499 self.visit_block(body);
500 self.frames.pop();
501 self.frames.pop();
502 }
503
504 fn walk_let_cond(&mut self, cond: &syn::Expr) {
506 match cond {
507 syn::Expr::Binary(binary) => {
508 self.walk_let_cond(&binary.left);
509 self.walk_let_cond(&binary.right);
510 }
511 syn::Expr::Let(let_expr) => {
512 syn::visit::visit_expr(self, &let_expr.expr);
513 let mut names = Vec::new();
514 pat_names(&let_expr.pat, &mut names);
515 for name in &names {
516 self.bind(Ns::Value, name, Origin::Let);
517 }
518 }
519 other => syn::visit::visit_expr(self, other),
520 }
521 }
522
523 fn emit_block_slot(&mut self, block: &syn::Block) {
525 let (span, input_tokens) = source_span_and_leaf_tokens(block);
526 let inherited = Inherited {
527 frames: &self.frames,
528 mod_frames: &self.mod_frames,
529 targets: &self.targets,
530 };
531 let form = build_block_slot_form(inherited, block);
532 self.emit_candidate(ContextKind::Block, span, input_tokens, form);
533 }
534
535 fn emit_block_expr(&mut self, expr: syn::Expr) {
537 let (span, input_tokens) = source_span_and_leaf_tokens(&expr);
538 let inherited = Inherited {
539 frames: &self.frames,
540 mod_frames: &self.mod_frames,
541 targets: &self.targets,
542 };
543 let form = build_block_expr_form(inherited, expr);
544 self.emit_candidate(ContextKind::Block, span, input_tokens, form);
545 }
546
547 fn emit_candidate(
549 &mut self,
550 kind: ContextKind,
551 span: Span,
552 input_tokens: usize,
553 form: CanonicalForm,
554 ) {
555 let item = self.item_path.join("::");
556 (self.emit)(
557 Context {
558 kind,
559 span,
560 item: item.as_str(),
561 },
562 form,
563 );
564 self.work.contexts += 1;
565 self.work.input_tokens += input_tokens;
566 }
567
568 fn push_item_path(&mut self, ident: &Ident) {
570 self.item_path.push(ident.to_string());
571 }
572
573 fn push_item_path_str(&mut self, name: String) {
575 self.item_path.push(name);
576 }
577
578 fn pop_item_path(&mut self) {
580 self.item_path.pop();
581 }
582
583 fn observe(&mut self, attrs: &[syn::Attribute]) -> bool {
584 let frame = self.frames.last_mut().expect("a scope frame");
585 let previous = frame.observed;
586 frame.observed |= crate::context::live_attr(attrs);
587 previous
588 }
589
590 fn restore_observation(&mut self, observed: bool) {
591 self.frames.last_mut().expect("a scope frame").observed = observed;
592 }
593}
594
595impl Visit<'_> for Walker<'_> {
596 fn visit_file(&mut self, file: &syn::File) {
597 self.observe(&file.attrs);
598 prebind_items(
599 &mut self.frames,
600 &mut self.mod_frames,
601 &mut self.mod_origins,
602 &mut self.id,
603 file.items.iter(),
604 );
605 self.frames.last_mut().expect("a scope frame").std_rebound |=
607 crate::drift::file_rebound(file);
608 self.bind_scope_uses(file.items.iter().filter_map(|item| match item {
609 syn::Item::Use(u) => Some(u),
610 _ => None,
611 }));
612 syn::visit::visit_file(self, file);
613 }
614
615 fn visit_item(&mut self, item: &syn::Item) {
616 let observed = self.observe(crate::helpers::item_attrs(item));
617 syn::visit::visit_item(self, item);
618 self.restore_observation(observed);
619 }
620
621 fn visit_expr(&mut self, expr: &syn::Expr) {
622 let observed = self.observe(crate::drift::expr_attrs(expr));
623 syn::visit::visit_expr(self, expr);
624 self.restore_observation(observed);
625 }
626
627 fn visit_block(&mut self, block: &syn::Block) {
628 self.frames.push(Frame::default());
629 prebind_items(
630 &mut self.frames,
631 &mut self.mod_frames,
632 &mut self.mod_origins,
633 &mut self.id,
634 block.stmts.iter().filter_map(|stmt| match stmt {
635 syn::Stmt::Item(item) => Some(item),
636 _ => None,
637 }),
638 );
639 self.bind_scope_uses(block.stmts.iter().filter_map(|stmt| match stmt {
640 syn::Stmt::Item(syn::Item::Use(u)) => Some(u),
641 _ => None,
642 }));
643 syn::visit::visit_block(self, block);
644 self.frames.pop();
645 }
646
647 fn visit_local(&mut self, local: &syn::Local) {
648 if let Some(init) = &local.init {
650 syn::visit::visit_expr(self, &init.expr);
651 if let Some(diverge) = &init.diverge {
652 syn::visit::visit_expr(self, &diverge.1);
653 }
654 }
655 let mut names = Vec::new();
656 pat_names(&local.pat, &mut names);
657 for name in &names {
658 self.bind(Ns::Value, name, Origin::Let);
659 }
660 syn::visit::visit_pat(self, &local.pat);
661 }
662
663 fn visit_item_use(&mut self, _: &syn::ItemUse) {}
665
666 fn visit_item_fn(&mut self, item: &syn::ItemFn) {
667 self.push_item_path(&item.sig.ident);
668 self.visit_fn(&item.sig, &item.block);
669 self.pop_item_path();
670 }
671
672 fn visit_item_mod(&mut self, item: &syn::ItemMod) {
673 self.push_item_path(&item.ident);
674 if let Some((_, items)) = &item.content {
675 let id = *self
676 .mod_origins
677 .get(&core::ptr::from_ref(item))
678 .expect("a module is prebound");
679 let frame = self.mod_frames.remove(&id).unwrap_or_default();
680 self.frames.push(frame);
681 self.inline_depth += 1;
682 self.bind_scope_uses(items.iter().filter_map(|item| match item {
683 syn::Item::Use(u) => Some(u),
684 _ => None,
685 }));
686 for item in items {
687 self.visit_item(item);
688 }
689 self.inline_depth -= 1;
690 let frame = self.frames.pop().expect("a scope frame");
691 self.mod_frames.insert(id, frame);
692 }
693 self.pop_item_path();
694 }
695
696 fn visit_item_impl(&mut self, item: &syn::ItemImpl) {
697 self.frames.push(Frame::default());
698 if let Some(name) = single_segment_type_name(&item.self_ty)
699 && let Some(binding) = self.lookup(&[Ns::Type], &name)
700 {
701 self.top_bind(Ns::Type, "Self", binding.clone());
702 }
703 self.push_item_path_str(self_type_string(&item.self_ty));
704 let has_generics = item.generics.lt_token.is_some();
705 if has_generics {
706 self.begin_generics(&item.generics);
707 }
708 syn::visit::visit_item_impl(self, item);
709 if has_generics {
710 self.frames.pop();
711 }
712 self.frames.pop();
713 self.pop_item_path();
714 }
715
716 fn visit_item_trait(&mut self, item: &syn::ItemTrait) {
717 self.push_item_path(&item.ident);
718 let id = self.bind_item_name(Ns::Type, &item.ident);
719 self.begin_generics(&item.generics);
720 self.top_bind(
721 Ns::Type,
722 "Self",
723 Binding {
724 id,
725 canon: String::new(),
726 origin: Origin::SelfTy,
727 prim: None,
728 port: 0,
729 value_port: None,
730 target: None,
731 raw: false,
732 helper: None,
733 macro_resolution: None,
734 },
735 );
736 syn::visit::visit_item_trait(self, item);
737 self.frames.pop();
738 self.pop_item_path();
739 }
740
741 fn visit_item_struct(&mut self, item: &syn::ItemStruct) {
742 self.push_item_path(&item.ident);
743 self.bind_item_name(Ns::Type, &item.ident);
744 self.begin_generics(&item.generics);
745 syn::visit::visit_item_struct(self, item);
746 self.frames.pop();
747 self.pop_item_path();
748 }
749
750 fn visit_item_enum(&mut self, item: &syn::ItemEnum) {
751 self.push_item_path(&item.ident);
752 self.bind_item_name(Ns::Type, &item.ident);
753 self.begin_generics(&item.generics);
754 syn::visit::visit_item_enum(self, item);
755 self.frames.pop();
756 self.pop_item_path();
757 }
758
759 fn visit_item_union(&mut self, item: &syn::ItemUnion) {
760 self.push_item_path(&item.ident);
761 self.bind_item_name(Ns::Type, &item.ident);
762 self.begin_generics(&item.generics);
763 syn::visit::visit_item_union(self, item);
764 self.frames.pop();
765 self.pop_item_path();
766 }
767
768 fn visit_item_type(&mut self, item: &syn::ItemType) {
769 self.push_item_path(&item.ident);
770 self.bind_item_name(Ns::Type, &item.ident);
771 self.begin_generics(&item.generics);
772 syn::visit::visit_item_type(self, item);
773 self.frames.pop();
774 self.pop_item_path();
775 }
776
777 fn visit_item_trait_alias(&mut self, item: &syn::ItemTraitAlias) {
778 self.push_item_path(&item.ident);
779 self.bind_item_name(Ns::Type, &item.ident);
780 self.begin_generics(&item.generics);
781 syn::visit::visit_item_trait_alias(self, item);
782 self.frames.pop();
783 self.pop_item_path();
784 }
785
786 fn visit_item_const(&mut self, item: &syn::ItemConst) {
787 self.push_item_path(&item.ident);
788 self.bind_item_name(Ns::Value, &item.ident);
789 syn::visit::visit_item_const(self, item);
790 self.pop_item_path();
791 }
792
793 fn visit_item_static(&mut self, item: &syn::ItemStatic) {
794 self.push_item_path(&item.ident);
795 self.bind_item_name(Ns::Value, &item.ident);
796 syn::visit::visit_item_static(self, item);
797 self.pop_item_path();
798 }
799
800 fn visit_item_macro(&mut self, item: &syn::ItemMacro) {
801 if let Some(ident) = &item.ident {
803 let name = ident.to_string();
804 if self
805 .frames
806 .last()
807 .and_then(|frame| frame.lookup(Ns::Macro, &name))
808 .is_none_or(|binding| binding.origin != Origin::MacroRule)
809 {
810 self.bind(Ns::Macro, &name, Origin::MacroRule);
811 }
812 }
813 syn::visit::visit_item_macro(self, item);
814 }
815
816 fn visit_foreign_item_fn(&mut self, item: &syn::ForeignItemFn) {
817 self.push_item_path(&item.sig.ident);
818 self.begin_generics(&item.sig.generics);
819 syn::visit::visit_foreign_item_fn(self, item);
820 self.frames.pop();
821 self.pop_item_path();
822 }
823
824 fn visit_impl_item(&mut self, item: &syn::ImplItem) {
825 let attrs: &[syn::Attribute] = match item {
826 syn::ImplItem::Fn(item) => &item.attrs,
827 syn::ImplItem::Const(item) => &item.attrs,
828 syn::ImplItem::Type(item) => &item.attrs,
829 syn::ImplItem::Macro(item) => &item.attrs,
830 _ => &[],
831 };
832 let observed = self.observe(attrs);
833 match item {
834 syn::ImplItem::Fn(f) => {
835 self.push_item_path(&f.sig.ident);
836 self.visit_fn(&f.sig, &f.block);
837 self.pop_item_path();
838 }
839 syn::ImplItem::Const(c) => {
840 self.push_item_path(&c.ident);
841 syn::visit::visit_impl_item_const(self, c);
842 self.pop_item_path();
843 }
844 syn::ImplItem::Type(t) => {
845 self.push_item_path(&t.ident);
846 syn::visit::visit_impl_item_type(self, t);
847 self.pop_item_path();
848 }
849 syn::ImplItem::Macro(m) => {
850 syn::visit::visit_impl_item_macro(self, m);
851 }
852 syn::ImplItem::Verbatim(_) | _ => {}
853 }
854 self.restore_observation(observed);
855 }
856
857 fn visit_trait_item(&mut self, item: &syn::TraitItem) {
858 let attrs: &[syn::Attribute] = match item {
859 syn::TraitItem::Fn(item) => &item.attrs,
860 syn::TraitItem::Const(item) => &item.attrs,
861 syn::TraitItem::Type(item) => &item.attrs,
862 syn::TraitItem::Macro(item) => &item.attrs,
863 _ => &[],
864 };
865 let observed = self.observe(attrs);
866 match item {
867 syn::TraitItem::Fn(f) => {
868 self.push_item_path(&f.sig.ident);
869 if let Some(body) = &f.default {
870 self.visit_fn(&f.sig, body);
871 } else {
872 self.begin_generics(&f.sig.generics);
873 syn::visit::visit_signature(self, &f.sig);
874 self.frames.pop();
875 }
876 self.pop_item_path();
877 }
878 syn::TraitItem::Const(c) => {
879 self.push_item_path(&c.ident);
880 syn::visit::visit_trait_item_const(self, c);
881 self.pop_item_path();
882 }
883 syn::TraitItem::Type(t) => {
884 self.push_item_path(&t.ident);
885 syn::visit::visit_trait_item_type(self, t);
886 self.pop_item_path();
887 }
888 syn::TraitItem::Macro(m) => {
889 syn::visit::visit_trait_item_macro(self, m);
890 }
891 syn::TraitItem::Verbatim(_) | _ => {}
892 }
893 self.restore_observation(observed);
894 }
895
896 fn visit_expr_closure(&mut self, closure: &syn::ExprClosure) {
897 let (span, input_tokens) = source_span_and_leaf_tokens(closure);
898 let inherited = Inherited {
899 frames: &self.frames,
900 mod_frames: &self.mod_frames,
901 targets: &self.targets,
902 };
903 let form = build_closure_form(inherited, closure);
904 self.emit_candidate(ContextKind::Closure, span, input_tokens, form);
905 self.frames.push(Frame::default());
906 if let Some(bound) = &closure.lifetimes {
907 syn::visit::visit_bound_lifetimes(self, bound);
908 }
909 let mut names = Vec::new();
910 for input in &closure.inputs {
911 pat_names(input, &mut names);
912 }
913 for name in &names {
914 self.bind(Ns::Value, name, Origin::Closure);
915 }
916 for input in &closure.inputs {
917 syn::visit::visit_pat(self, input);
918 }
919 syn::visit::visit_return_type(self, &closure.output);
920 syn::visit::visit_expr(self, &closure.body);
921 self.frames.pop();
922 }
923
924 fn visit_expr_block(&mut self, expr: &syn::ExprBlock) {
925 self.emit_block_expr(syn::Expr::Block(expr.clone()));
926 if let Some(label) = &expr.label {
927 self.bind(Ns::Label, &label.name.ident.to_string(), Origin::Label);
928 }
929 self.visit_block(&expr.block);
930 }
931
932 fn visit_expr_unsafe(&mut self, expr: &syn::ExprUnsafe) {
933 self.emit_block_expr(syn::Expr::Unsafe(expr.clone()));
934 syn::visit::visit_expr_unsafe(self, expr);
935 }
936
937 fn visit_expr_async(&mut self, expr: &syn::ExprAsync) {
938 self.emit_block_expr(syn::Expr::Async(expr.clone()));
939 syn::visit::visit_expr_async(self, expr);
940 }
941
942 fn visit_expr_try_block(&mut self, expr: &syn::ExprTryBlock) {
943 self.emit_block_expr(syn::Expr::TryBlock(expr.clone()));
944 syn::visit::visit_expr_try_block(self, expr);
945 }
946
947 fn visit_expr_const(&mut self, expr: &syn::ExprConst) {
948 self.emit_block_expr(syn::Expr::Const(expr.clone()));
949 syn::visit::visit_expr_const(self, expr);
950 }
951
952 fn visit_expr_if(&mut self, expr: &syn::ExprIf) {
953 self.frames.push(Frame::default());
955 self.walk_let_cond(&expr.cond);
956 self.emit_block_slot(&expr.then_branch);
957 self.visit_block(&expr.then_branch);
958 self.frames.pop();
959 if let Some((_, otherwise)) = &expr.else_branch {
960 syn::visit::visit_expr(self, otherwise);
961 }
962 }
963
964 fn visit_expr_for_loop(&mut self, for_loop: &syn::ExprForLoop) {
965 syn::visit::visit_expr(self, &for_loop.expr);
967 self.frames.push(Frame::default());
968 if let Some(label) = &for_loop.label {
969 self.bind(Ns::Label, &label.name.ident.to_string(), Origin::Label);
970 }
971 let mut names = Vec::new();
972 pat_names(&for_loop.pat, &mut names);
973 for name in &names {
974 self.bind(Ns::Value, name, Origin::Let);
975 }
976 self.emit_block_slot(&for_loop.body);
977 self.visit_block(&for_loop.body);
978 self.frames.pop();
979 }
980
981 fn visit_expr_while(&mut self, expr: &syn::ExprWhile) {
982 self.frames.push(Frame::default());
983 if let Some(label) = &expr.label {
984 self.bind(Ns::Label, &label.name.ident.to_string(), Origin::Label);
985 }
986 self.walk_let_cond(&expr.cond);
987 self.emit_block_slot(&expr.body);
988 self.visit_block(&expr.body);
989 self.frames.pop();
990 }
991
992 fn visit_expr_loop(&mut self, expr: &syn::ExprLoop) {
993 self.frames.push(Frame::default());
994 if let Some(label) = &expr.label {
995 self.bind(Ns::Label, &label.name.ident.to_string(), Origin::Label);
996 }
997 self.emit_block_slot(&expr.body);
998 self.visit_block(&expr.body);
999 self.frames.pop();
1000 }
1001
1002 fn visit_arm(&mut self, arm: &syn::Arm) {
1003 let (span, input_tokens) = source_span_and_leaf_tokens(arm);
1004 let inherited = Inherited {
1005 frames: &self.frames,
1006 mod_frames: &self.mod_frames,
1007 targets: &self.targets,
1008 };
1009 let form = build_arm_form(inherited, arm);
1010 self.emit_candidate(ContextKind::Arm, span, input_tokens, form);
1011 self.frames.push(Frame::default());
1012 let mut names = Vec::new();
1013 pat_names(&arm.pat, &mut names);
1014 for name in &names {
1015 self.bind(Ns::Value, name, Origin::Let);
1016 }
1017 syn::visit::visit_arm(self, arm);
1018 self.frames.pop();
1019 }
1020
1021 fn visit_pat_guard(&mut self, node: &syn::PatGuard) {
1022 syn::visit::visit_pat(self, &node.pat);
1023 self.walk_let_cond(&node.guard);
1024 }
1025
1026 fn visit_bound_lifetimes(&mut self, node: &syn::BoundLifetimes) {
1027 for param in &node.lifetimes {
1028 if let syn::GenericParam::Lifetime(lifetime) = param {
1029 self.bind(
1030 Ns::Lifetime,
1031 &lifetime.lifetime.ident.to_string(),
1032 Origin::Lifetime,
1033 );
1034 }
1035 }
1036 syn::visit::visit_bound_lifetimes(self, node);
1037 }
1038
1039 fn visit_trait_bound(&mut self, node: &syn::TraitBound) {
1040 self.frames.push(Frame::default());
1042 syn::visit::visit_trait_bound(self, node);
1043 self.frames.pop();
1044 }
1045
1046 fn visit_type_fn_ptr(&mut self, node: &syn::TypeFnPtr) {
1047 self.frames.push(Frame::default());
1049 syn::visit::visit_type_fn_ptr(self, node);
1050 self.frames.pop();
1051 }
1052}
1053
1054fn build_function_body_form(
1057 inherited: Inherited<'_>,
1058 body: &syn::Block,
1059 early: bool,
1060) -> CanonicalForm {
1061 let mut block = body.clone();
1062 let frames = inherited.frames;
1063 let mut renamer = Renamer::contextual(inherited);
1064 if !renamer.observes_tokens() {
1065 crate::drift::normalize_block(&mut block, frames);
1066 }
1067 renamer.normalize_return_body(&mut block, early);
1068 renamer.visit_block_mut(&mut block);
1069 let facts = renamer.into_reference_facts();
1070 crate::form::from_node(&block, &facts)
1071}
1072
1073fn build_block_slot_form(inherited: Inherited<'_>, block: &syn::Block) -> CanonicalForm {
1075 let mut block = block.clone();
1076 let frames = inherited.frames;
1077 let mut renamer = Renamer::contextual(inherited);
1078 if !renamer.observes_tokens() {
1079 crate::drift::normalize_block(&mut block, frames);
1080 }
1081 renamer.visit_block_mut(&mut block);
1082 let facts = renamer.into_reference_facts();
1083 crate::form::from_node(&block, &facts)
1084}
1085
1086fn build_block_expr_form(inherited: Inherited<'_>, expr: syn::Expr) -> CanonicalForm {
1088 let mut expr = expr;
1089 let frames = inherited.frames;
1090 let mut renamer = Renamer::contextual(inherited);
1091 if !renamer.observes_tokens() {
1092 crate::drift::normalize_expr(&mut expr, frames);
1093 }
1094 renamer.visit_expr_mut(&mut expr);
1095 let facts = renamer.into_reference_facts();
1096 crate::form::from_node(&expr, &facts)
1097}
1098
1099fn build_arm_form(inherited: Inherited<'_>, arm: &syn::Arm) -> CanonicalForm {
1101 let mut arm = arm.clone();
1102 let frames = inherited.frames;
1103 let mut renamer = Renamer::contextual(inherited);
1104 if !renamer.observes_tokens() {
1105 crate::drift::normalize_arm(&mut arm, frames);
1106 }
1107 renamer.visit_arm_mut(&mut arm);
1108 let facts = renamer.into_reference_facts();
1109 crate::form::from_node(&arm, &facts)
1110}
1111
1112fn build_closure_form(inherited: Inherited<'_>, closure: &syn::ExprClosure) -> CanonicalForm {
1114 let mut expr = syn::Expr::Closure(closure.clone());
1115 let frames = inherited.frames;
1116 let mut renamer = Renamer::contextual(inherited);
1117 if !renamer.observes_tokens() {
1118 crate::drift::normalize_expr(&mut expr, frames);
1119 }
1120 renamer.visit_expr_mut(&mut expr);
1121 let facts = renamer.into_reference_facts();
1122 crate::form::from_node(&expr, &facts)
1123}