1mod asm;
5mod format_args;
6mod generics;
7mod path;
8
9use std::{cell::OnceCell, mem};
10
11use base_db::FxIndexSet;
12use cfg::CfgOptions;
13use either::Either;
14use hir_expand::{
15 HirFileId, InFile, MacroDefId,
16 name::{AsName, Name},
17 span_map::SpanMapRef,
18};
19use intern::{Symbol, sym};
20use rustc_hash::FxHashMap;
21use stdx::never;
22use syntax::{
23 AstNode, AstPtr, SyntaxNodePtr,
24 ast::{
25 self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasGenericArgs,
26 HasGenericParams, HasLoopBody, HasName, HasTypeBounds, IsString, RangeItem,
27 SlicePatComponents,
28 },
29};
30use thin_vec::ThinVec;
31use triomphe::Arc;
32use tt::TextRange;
33
34use crate::{
35 AdtId, BlockId, BlockLoc, DefWithBodyId, FunctionId, GenericDefId, ImplId, MacroId,
36 ModuleDefId, ModuleId, TraitId, TypeAliasId, UnresolvedMacro,
37 attrs::AttrFlags,
38 db::DefDatabase,
39 expr_store::{
40 Body, BodySourceMap, ExprPtr, ExpressionStore, ExpressionStoreBuilder,
41 ExpressionStoreDiagnostics, ExpressionStoreSourceMap, HygieneId, LabelPtr, LifetimePtr,
42 PatPtr, TypePtr,
43 expander::Expander,
44 lower::generics::ImplTraitLowerFn,
45 path::{AssociatedTypeBinding, GenericArg, GenericArgs, GenericArgsParentheses, Path},
46 },
47 hir::{
48 Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind,
49 Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId,
50 RecordFieldPat, RecordLitField, Statement, generics::GenericParams,
51 },
52 item_scope::BuiltinShadowMode,
53 item_tree::FieldsShape,
54 lang_item::{LangItemTarget, LangItems},
55 nameres::{DefMap, LocalDefMap, MacroSubNs, block_def_map},
56 type_ref::{
57 ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, Mutability, PathId, Rawness,
58 RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, UseArgRef,
59 },
60};
61
62pub use self::path::hir_segment_to_ast_segment;
63
64pub(super) fn lower_body(
65 db: &dyn DefDatabase,
66 owner: DefWithBodyId,
67 current_file_id: HirFileId,
68 module: ModuleId,
69 parameters: Option<ast::ParamList>,
70 body: Option<ast::Expr>,
71 is_async_fn: bool,
72) -> (Body, BodySourceMap) {
73 let mut self_param = None;
80 let mut source_map_self_param = None;
81 let mut params = vec![];
82 let mut collector = ExprCollector::new(db, module, current_file_id);
83
84 let skip_body = AttrFlags::query(
85 db,
86 match owner {
87 DefWithBodyId::FunctionId(it) => it.into(),
88 DefWithBodyId::StaticId(it) => it.into(),
89 DefWithBodyId::ConstId(it) => it.into(),
90 DefWithBodyId::VariantId(it) => it.into(),
91 },
92 )
93 .contains(AttrFlags::RUST_ANALYZER_SKIP);
94 if skip_body {
97 if let Some(param_list) = parameters {
98 if let Some(self_param_syn) =
99 param_list.self_param().filter(|self_param| collector.check_cfg(self_param))
100 {
101 let is_mutable =
102 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
103 let hygiene = self_param_syn
104 .name()
105 .map(|name| collector.hygiene_id_for(name.syntax().text_range()))
106 .unwrap_or(HygieneId::ROOT);
107 let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
108 Name::new_symbol_root(sym::self_),
109 BindingAnnotation::new(is_mutable, false),
110 hygiene,
111 );
112 self_param = Some(binding_id);
113 source_map_self_param =
114 Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
115 }
116 let count = param_list.params().filter(|it| collector.check_cfg(it)).count();
117 params = (0..count).map(|_| collector.missing_pat()).collect();
118 };
119 let body_expr = collector.missing_expr();
120 let (store, source_map) = collector.store.finish();
121 return (
122 Body { store, params: params.into_boxed_slice(), self_param, body_expr },
123 BodySourceMap { self_param: source_map_self_param, store: source_map },
124 );
125 }
126
127 if let Some(param_list) = parameters {
128 if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) {
129 let is_mutable =
130 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
131 let hygiene = self_param_syn
132 .name()
133 .map(|name| collector.hygiene_id_for(name.syntax().text_range()))
134 .unwrap_or(HygieneId::ROOT);
135 let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
136 Name::new_symbol_root(sym::self_),
137 BindingAnnotation::new(is_mutable, false),
138 hygiene,
139 );
140 self_param = Some(binding_id);
141 source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
142 }
143
144 for param in param_list.params() {
145 if collector.check_cfg(¶m) {
146 let param_pat = collector.collect_pat_top(param.pat());
147 params.push(param_pat);
148 }
149 }
150 };
151
152 let body_expr = collector.collect(
153 body,
154 if is_async_fn {
155 Awaitable::Yes
156 } else {
157 match owner {
158 DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
159 DefWithBodyId::StaticId(..) => Awaitable::No("static"),
160 DefWithBodyId::ConstId(..) => Awaitable::No("constant"),
161 DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
162 }
163 },
164 );
165
166 let (store, source_map) = collector.store.finish();
167 (
168 Body { store, params: params.into_boxed_slice(), self_param, body_expr },
169 BodySourceMap { self_param: source_map_self_param, store: source_map },
170 )
171}
172
173pub(crate) fn lower_type_ref(
174 db: &dyn DefDatabase,
175 module: ModuleId,
176 type_ref: InFile<Option<ast::Type>>,
177) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
178 let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
179 let type_ref =
180 expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
181 let (store, source_map) = expr_collector.store.finish();
182 (store, source_map, type_ref)
183}
184
185pub(crate) fn lower_generic_params(
186 db: &dyn DefDatabase,
187 module: ModuleId,
188 def: GenericDefId,
189 file_id: HirFileId,
190 param_list: Option<ast::GenericParamList>,
191 where_clause: Option<ast::WhereClause>,
192) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
193 let mut expr_collector = ExprCollector::new(db, module, file_id);
194 let mut collector = generics::GenericParamsCollector::new(def);
195 collector.lower(&mut expr_collector, param_list, where_clause);
196 let params = collector.finish();
197 let (store, source_map) = expr_collector.store.finish();
198 (Arc::new(store), params, source_map)
199}
200
201pub(crate) fn lower_impl(
202 db: &dyn DefDatabase,
203 module: ModuleId,
204 impl_syntax: InFile<ast::Impl>,
205 impl_id: ImplId,
206) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, Arc<GenericParams>) {
207 let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id);
208 let self_ty =
209 expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
210 let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
211 ast::Type::PathType(path_type) => {
212 let path = expr_collector
213 .lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?;
214 Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) })
215 }
216 _ => None,
217 });
218 let mut collector = generics::GenericParamsCollector::new(impl_id.into());
219 collector.lower(
220 &mut expr_collector,
221 impl_syntax.value.generic_param_list(),
222 impl_syntax.value.where_clause(),
223 );
224 let params = collector.finish();
225 let (store, source_map) = expr_collector.store.finish();
226 (store, source_map, self_ty, trait_, params)
227}
228
229pub(crate) fn lower_trait(
230 db: &dyn DefDatabase,
231 module: ModuleId,
232 trait_syntax: InFile<ast::Trait>,
233 trait_id: TraitId,
234) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
235 let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
236 let mut collector = generics::GenericParamsCollector::with_self_param(
237 &mut expr_collector,
238 trait_id.into(),
239 trait_syntax.value.type_bound_list(),
240 );
241 collector.lower(
242 &mut expr_collector,
243 trait_syntax.value.generic_param_list(),
244 trait_syntax.value.where_clause(),
245 );
246 let params = collector.finish();
247 let (store, source_map) = expr_collector.store.finish();
248 (store, source_map, params)
249}
250
251pub(crate) fn lower_type_alias(
252 db: &dyn DefDatabase,
253 module: ModuleId,
254 alias: InFile<ast::TypeAlias>,
255 type_alias_id: TypeAliasId,
256) -> (
257 ExpressionStore,
258 ExpressionStoreSourceMap,
259 Arc<GenericParams>,
260 Box<[TypeBound]>,
261 Option<TypeRefId>,
262) {
263 let mut expr_collector = ExprCollector::new(db, module, alias.file_id);
264 let bounds = alias
265 .value
266 .type_bound_list()
267 .map(|bounds| {
268 bounds
269 .bounds()
270 .map(|bound| {
271 expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator)
272 })
273 .collect()
274 })
275 .unwrap_or_default();
276 let mut collector = generics::GenericParamsCollector::new(type_alias_id.into());
277 collector.lower(
278 &mut expr_collector,
279 alias.value.generic_param_list(),
280 alias.value.where_clause(),
281 );
282 let params = collector.finish();
283 let type_ref = alias
284 .value
285 .ty()
286 .map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator));
287 let (store, source_map) = expr_collector.store.finish();
288 (store, source_map, params, bounds, type_ref)
289}
290
291pub(crate) fn lower_function(
292 db: &dyn DefDatabase,
293 module: ModuleId,
294 fn_: InFile<ast::Fn>,
295 function_id: FunctionId,
296) -> (
297 ExpressionStore,
298 ExpressionStoreSourceMap,
299 Arc<GenericParams>,
300 Box<[TypeRefId]>,
301 Option<TypeRefId>,
302 bool,
303 bool,
304) {
305 let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
306 let mut collector = generics::GenericParamsCollector::new(function_id.into());
307 collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
308 let mut params = vec![];
309 let mut has_self_param = false;
310 let mut has_variadic = false;
311 collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| {
312 if let Some(param_list) = fn_.value.param_list() {
313 if let Some(param) = param_list.self_param() {
314 let enabled = collector.check_cfg(¶m);
315 if enabled {
316 has_self_param = true;
317 params.push(match param.ty() {
318 Some(ty) => collector.lower_type_ref(ty, &mut impl_trait_lower_fn),
319 None => {
320 let self_type = collector.alloc_type_ref_desugared(TypeRef::Path(
321 Name::new_symbol_root(sym::Self_).into(),
322 ));
323 let lifetime = param
324 .lifetime()
325 .map(|lifetime| collector.lower_lifetime_ref(lifetime));
326 match param.kind() {
327 ast::SelfParamKind::Owned => self_type,
328 ast::SelfParamKind::Ref => collector.alloc_type_ref_desugared(
329 TypeRef::Reference(Box::new(RefType {
330 ty: self_type,
331 lifetime,
332 mutability: Mutability::Shared,
333 })),
334 ),
335 ast::SelfParamKind::MutRef => collector.alloc_type_ref_desugared(
336 TypeRef::Reference(Box::new(RefType {
337 ty: self_type,
338 lifetime,
339 mutability: Mutability::Mut,
340 })),
341 ),
342 }
343 }
344 });
345 }
346 }
347 let p = param_list
348 .params()
349 .filter(|param| collector.check_cfg(param))
350 .filter(|param| {
351 let is_variadic = param.dotdotdot_token().is_some();
352 has_variadic |= is_variadic;
353 !is_variadic
354 })
355 .map(|param| param.ty())
356 .collect::<Vec<_>>();
358 for p in p {
359 params.push(collector.lower_type_ref_opt(p, &mut impl_trait_lower_fn));
360 }
361 }
362 });
363 let generics = collector.finish();
364 let return_type = fn_.value.ret_type().map(|ret_type| {
365 expr_collector.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator)
366 });
367
368 let return_type = if fn_.value.async_token().is_some() {
369 let path = hir_expand::mod_path::path![core::future::Future];
370 let mut generic_args: Vec<_> =
371 std::iter::repeat_n(None, path.segments().len() - 1).collect();
372 let binding = AssociatedTypeBinding {
373 name: Name::new_symbol_root(sym::Output),
374 args: None,
375 type_ref: Some(
376 return_type
377 .unwrap_or_else(|| expr_collector.alloc_type_ref_desugared(TypeRef::unit())),
378 ),
379 bounds: Box::default(),
380 };
381 generic_args
382 .push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));
383
384 let path = Path::from_known_path(path, generic_args);
385 let path = PathId::from_type_ref_unchecked(
386 expr_collector.alloc_type_ref_desugared(TypeRef::Path(path)),
387 );
388 let ty_bound = TypeBound::Path(path, TraitBoundModifier::None);
389 Some(
390 expr_collector
391 .alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound]))),
392 )
393 } else {
394 return_type
395 };
396 let (store, source_map) = expr_collector.store.finish();
397 (
398 store,
399 source_map,
400 generics,
401 params.into_boxed_slice(),
402 return_type,
403 has_self_param,
404 has_variadic,
405 )
406}
407
408pub struct ExprCollector<'db> {
409 db: &'db dyn DefDatabase,
410 cfg_options: &'db CfgOptions,
411 expander: Expander,
412 def_map: &'db DefMap,
413 local_def_map: &'db LocalDefMap,
414 module: ModuleId,
415 lang_items: OnceCell<&'db LangItems>,
416 pub store: ExpressionStoreBuilder,
417
418 outer_impl_trait: bool,
421
422 is_lowering_coroutine: bool,
423
424 current_block_legacy_macro_defs_count: FxHashMap<Name, usize>,
427
428 current_try_block_label: Option<LabelId>,
429
430 label_ribs: Vec<LabelRib>,
431 unowned_bindings: Vec<BindingId>,
432
433 awaitable_context: Option<Awaitable>,
434 krate: base_db::Crate,
435
436 name_generator_index: usize,
437}
438
439#[derive(Clone, Debug)]
440struct LabelRib {
441 kind: RibKind,
442}
443
444impl LabelRib {
445 fn new(kind: RibKind) -> Self {
446 LabelRib { kind }
447 }
448}
449
450#[derive(Clone, Debug, PartialEq, Eq)]
451enum RibKind {
452 Normal(Name, LabelId, HygieneId),
453 Closure,
454 Constant,
455 MacroDef(Box<MacroDefId>),
456}
457
458impl RibKind {
459 fn is_label_barrier(&self) -> bool {
461 match self {
462 RibKind::Normal(..) | RibKind::MacroDef(_) => false,
463 RibKind::Closure | RibKind::Constant => true,
464 }
465 }
466}
467
468#[derive(PartialEq, Eq, Debug, Copy, Clone)]
469enum Awaitable {
470 Yes,
471 No(&'static str),
472}
473
474#[derive(Debug, Default)]
475struct BindingList {
476 map: FxHashMap<(Name, HygieneId), BindingId>,
477 is_used: FxHashMap<BindingId, bool>,
478 reject_new: bool,
479}
480
481impl BindingList {
482 fn find(
483 &mut self,
484 ec: &mut ExprCollector<'_>,
485 name: Name,
486 hygiene: HygieneId,
487 mode: BindingAnnotation,
488 ) -> BindingId {
489 let id = *self
490 .map
491 .entry((name, hygiene))
492 .or_insert_with_key(|(name, hygiene)| ec.alloc_binding(name.clone(), mode, *hygiene));
493 if ec.store.bindings[id].mode != mode {
494 ec.store.bindings[id].problems = Some(BindingProblems::BoundInconsistently);
495 }
496 self.check_is_used(ec, id);
497 id
498 }
499
500 fn check_is_used(&mut self, ec: &mut ExprCollector<'_>, id: BindingId) {
501 match self.is_used.get(&id) {
502 None => {
503 if self.reject_new {
504 ec.store.bindings[id].problems = Some(BindingProblems::NotBoundAcrossAll);
505 }
506 }
507 Some(true) => {
508 ec.store.bindings[id].problems = Some(BindingProblems::BoundMoreThanOnce);
509 }
510 Some(false) => {}
511 }
512 self.is_used.insert(id, true);
513 }
514}
515
516impl<'db> ExprCollector<'db> {
517 pub fn new(
518 db: &dyn DefDatabase,
519 module: ModuleId,
520 current_file_id: HirFileId,
521 ) -> ExprCollector<'_> {
522 let (def_map, local_def_map) = module.local_def_map(db);
523 let expander = Expander::new(db, current_file_id, def_map);
524 let krate = module.krate(db);
525 ExprCollector {
526 db,
527 cfg_options: krate.cfg_options(db),
528 module,
529 def_map,
530 local_def_map,
531 lang_items: OnceCell::new(),
532 store: ExpressionStoreBuilder::default(),
533 expander,
534 current_try_block_label: None,
535 is_lowering_coroutine: false,
536 label_ribs: Vec::new(),
537 unowned_bindings: Vec::new(),
538 awaitable_context: None,
539 current_block_legacy_macro_defs_count: FxHashMap::default(),
540 outer_impl_trait: false,
541 krate,
542 name_generator_index: 0,
543 }
544 }
545
546 fn generate_new_name(&mut self) -> Name {
547 let index = self.name_generator_index;
548 self.name_generator_index += 1;
549 Name::generate_new_name(index)
550 }
551
552 #[inline]
553 pub(crate) fn lang_items(&self) -> &'db LangItems {
554 self.lang_items.get_or_init(|| crate::lang_item::lang_items(self.db, self.def_map.krate()))
555 }
556
557 #[inline]
558 pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
559 self.expander.span_map()
560 }
561
562 pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId {
563 let lifetime_ref = match &*lifetime.text() {
565 "" | "'" => LifetimeRef::Error,
566 "'static" => LifetimeRef::Static,
567 "'_" => LifetimeRef::Placeholder,
568 text => LifetimeRef::Named(Name::new_lifetime(text)),
569 };
570 self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime))
571 }
572
573 pub fn lower_lifetime_ref_opt(&mut self, lifetime: Option<ast::Lifetime>) -> LifetimeRefId {
574 match lifetime {
575 Some(lifetime) => self.lower_lifetime_ref(lifetime),
576 None => self.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder),
577 }
578 }
579
580 pub fn lower_type_ref(
582 &mut self,
583 node: ast::Type,
584 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
585 ) -> TypeRefId {
586 let ty = match &node {
587 ast::Type::ParenType(inner) => {
588 return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
589 }
590 ast::Type::TupleType(inner) => TypeRef::Tuple(ThinVec::from_iter(Vec::from_iter(
591 inner.fields().map(|it| self.lower_type_ref(it, impl_trait_lower_fn)),
592 ))),
593 ast::Type::NeverType(..) => TypeRef::Never,
594 ast::Type::PathType(inner) => inner
595 .path()
596 .and_then(|it| self.lower_path(it, impl_trait_lower_fn))
597 .map(TypeRef::Path)
598 .unwrap_or(TypeRef::Error),
599 ast::Type::PtrType(inner) => {
600 let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
601 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
602 TypeRef::RawPtr(inner_ty, mutability)
603 }
604 ast::Type::ArrayType(inner) => {
605 let len = self.lower_const_arg_opt(inner.const_arg());
606 TypeRef::Array(ArrayType {
607 ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn),
608 len,
609 })
610 }
611 ast::Type::SliceType(inner) => {
612 TypeRef::Slice(self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn))
613 }
614 ast::Type::RefType(inner) => {
615 let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
616 let lifetime = inner.lifetime().map(|lt| self.lower_lifetime_ref(lt));
617 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
618 TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
619 }
620 ast::Type::InferType(_inner) => TypeRef::Placeholder,
621 ast::Type::FnPtrType(inner) => {
622 let ret_ty = inner
623 .ret_type()
624 .and_then(|rt| rt.ty())
625 .map(|it| self.lower_type_ref(it, impl_trait_lower_fn))
626 .unwrap_or_else(|| self.alloc_type_ref_desugared(TypeRef::unit()));
627 let mut is_varargs = false;
628 let mut params = if let Some(pl) = inner.param_list() {
629 if let Some(param) = pl.params().last() {
630 is_varargs = param.dotdotdot_token().is_some();
631 }
632
633 pl.params()
634 .map(|it| {
635 let type_ref = self.lower_type_ref_opt(it.ty(), impl_trait_lower_fn);
636 let name = match it.pat() {
637 Some(ast::Pat::IdentPat(it)) => Some(
638 it.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing),
639 ),
640 _ => None,
641 };
642 (name, type_ref)
643 })
644 .collect()
645 } else {
646 Vec::with_capacity(1)
647 };
648 fn lower_abi(abi: ast::Abi) -> Symbol {
649 match abi.abi_string() {
650 Some(tok) => Symbol::intern(tok.text_without_quotes()),
651 _ => sym::C,
653 }
654 }
655
656 let abi = inner.abi().map(lower_abi);
657 params.push((None, ret_ty));
658 TypeRef::Fn(Box::new(FnType {
659 is_varargs,
660 is_unsafe: inner.unsafe_token().is_some(),
661 abi,
662 params: params.into_boxed_slice(),
663 }))
664 }
665 ast::Type::ForType(inner) => {
667 return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
668 }
669 ast::Type::ImplTraitType(inner) => {
670 if self.outer_impl_trait {
671 TypeRef::Error
673 } else {
674 return self.with_outer_impl_trait_scope(true, |this| {
675 let type_bounds =
676 this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
677 impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds)
678 });
679 }
680 }
681 ast::Type::DynTraitType(inner) => TypeRef::DynTrait(
682 self.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn),
683 ),
684 ast::Type::MacroType(mt) => match mt.macro_call() {
685 Some(mcall) => {
686 let macro_ptr = AstPtr::new(&mcall);
687 let src = self.expander.in_file(AstPtr::new(&node));
688 let id = self.collect_macro_call(mcall, macro_ptr, true, |this, expansion| {
689 this.lower_type_ref_opt(expansion, impl_trait_lower_fn)
690 });
691 self.store.types_map.insert(src, id);
692 return id;
693 }
694 None => TypeRef::Error,
695 },
696 };
697 self.alloc_type_ref(ty, AstPtr::new(&node))
698 }
699
700 pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId {
701 self.lower_type_ref(node, &mut Self::impl_trait_error_allocator)
702 }
703
704 pub(crate) fn lower_type_ref_opt(
705 &mut self,
706 node: Option<ast::Type>,
707 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
708 ) -> TypeRefId {
709 match node {
710 Some(node) => self.lower_type_ref(node, impl_trait_lower_fn),
711 None => self.alloc_error_type(),
712 }
713 }
714
715 pub(crate) fn lower_type_ref_opt_disallow_impl_trait(
716 &mut self,
717 node: Option<ast::Type>,
718 ) -> TypeRefId {
719 self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator)
720 }
721
722 fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
723 let id = self.store.types.alloc(type_ref);
724 let ptr = self.expander.in_file(node);
725 self.store.types_map_back.insert(id, ptr);
726 self.store.types_map.insert(ptr, id);
727 id
728 }
729
730 fn alloc_lifetime_ref(
731 &mut self,
732 lifetime_ref: LifetimeRef,
733 node: LifetimePtr,
734 ) -> LifetimeRefId {
735 let id = self.store.lifetimes.alloc(lifetime_ref);
736 let ptr = self.expander.in_file(node);
737 self.store.lifetime_map_back.insert(id, ptr);
738 self.store.lifetime_map.insert(ptr, id);
739 id
740 }
741
742 fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId {
743 self.store.types.alloc(type_ref)
744 }
745
746 fn alloc_lifetime_ref_desugared(&mut self, lifetime_ref: LifetimeRef) -> LifetimeRefId {
747 self.store.lifetimes.alloc(lifetime_ref)
748 }
749
750 fn alloc_error_type(&mut self) -> TypeRefId {
751 self.store.types.alloc(TypeRef::Error)
752 }
753
754 pub fn lower_path(
755 &mut self,
756 ast: ast::Path,
757 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
758 ) -> Option<Path> {
759 super::lower::path::lower_path(self, ast, impl_trait_lower_fn)
760 }
761
762 fn with_outer_impl_trait_scope<R>(
763 &mut self,
764 impl_trait: bool,
765 f: impl FnOnce(&mut Self) -> R,
766 ) -> R {
767 let old = mem::replace(&mut self.outer_impl_trait, impl_trait);
768 let result = f(self);
769 self.outer_impl_trait = old;
770 result
771 }
772
773 pub fn impl_trait_error_allocator(
774 ec: &mut ExprCollector<'_>,
775 ptr: TypePtr,
776 _: ThinVec<TypeBound>,
777 ) -> TypeRefId {
778 ec.alloc_type_ref(TypeRef::Error, ptr)
779 }
780
781 fn impl_trait_allocator(
782 ec: &mut ExprCollector<'_>,
783 ptr: TypePtr,
784 bounds: ThinVec<TypeBound>,
785 ) -> TypeRefId {
786 ec.alloc_type_ref(TypeRef::ImplTrait(bounds), ptr)
787 }
788
789 fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
790 PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
791 }
792
793 pub fn lower_generic_args_from_fn_path(
796 &mut self,
797 args: Option<ast::ParenthesizedArgList>,
798 ret_type: Option<ast::RetType>,
799 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
800 ) -> Option<GenericArgs> {
801 let params = args?;
802 let mut param_types = Vec::new();
803 for param in params.type_args() {
804 let type_ref = self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn);
805 param_types.push(type_ref);
806 }
807 let args = Box::new([GenericArg::Type(
808 self.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))),
809 )]);
810 let bindings = if let Some(ret_type) = ret_type {
811 let type_ref = self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn);
812 Box::new([AssociatedTypeBinding {
813 name: Name::new_symbol_root(sym::Output),
814 args: None,
815 type_ref: Some(type_ref),
816 bounds: Box::default(),
817 }])
818 } else {
819 let type_ref = self.alloc_type_ref_desugared(TypeRef::unit());
821 Box::new([AssociatedTypeBinding {
822 name: Name::new_symbol_root(sym::Output),
823 args: None,
824 type_ref: Some(type_ref),
825 bounds: Box::default(),
826 }])
827 };
828 Some(GenericArgs {
829 args,
830 has_self_type: false,
831 bindings,
832 parenthesized: GenericArgsParentheses::ParenSugar,
833 })
834 }
835
836 pub(super) fn lower_generic_args(
837 &mut self,
838 node: ast::GenericArgList,
839 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
840 ) -> Option<GenericArgs> {
841 let mut args = Vec::new();
843 let mut bindings = Vec::new();
844 for generic_arg in node.generic_args() {
845 match generic_arg {
846 ast::GenericArg::TypeArg(type_arg) => {
847 let type_ref = self.lower_type_ref_opt(type_arg.ty(), impl_trait_lower_fn);
848 args.push(GenericArg::Type(type_ref));
849 }
850 ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
851 if assoc_type_arg.param_list().is_some() {
853 continue;
855 }
856 if let Some(name_ref) = assoc_type_arg.name_ref() {
857 self.with_outer_impl_trait_scope(false, |this| {
859 let name = name_ref.as_name();
860 let args = assoc_type_arg
861 .generic_arg_list()
862 .and_then(|args| this.lower_generic_args(args, impl_trait_lower_fn))
863 .or_else(|| {
864 assoc_type_arg
865 .return_type_syntax()
866 .map(|_| GenericArgs::return_type_notation())
867 });
868 let type_ref = assoc_type_arg
869 .ty()
870 .map(|it| this.lower_type_ref(it, impl_trait_lower_fn));
871 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
872 l.bounds()
873 .map(|it| this.lower_type_bound(it, impl_trait_lower_fn))
874 .collect()
875 } else {
876 Box::default()
877 };
878 bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
879 });
880 }
881 }
882 ast::GenericArg::LifetimeArg(lifetime_arg) => {
883 if let Some(lifetime) = lifetime_arg.lifetime() {
884 let lifetime_ref = self.lower_lifetime_ref(lifetime);
885 args.push(GenericArg::Lifetime(lifetime_ref))
886 }
887 }
888 ast::GenericArg::ConstArg(arg) => {
889 let arg = self.lower_const_arg(arg);
890 args.push(GenericArg::Const(arg))
891 }
892 }
893 }
894
895 if args.is_empty() && bindings.is_empty() {
896 return None;
897 }
898 Some(GenericArgs {
899 args: args.into_boxed_slice(),
900 has_self_type: false,
901 bindings: bindings.into_boxed_slice(),
902 parenthesized: GenericArgsParentheses::No,
903 })
904 }
905
906 fn collect(&mut self, expr: Option<ast::Expr>, awaitable: Awaitable) -> ExprId {
907 self.awaitable_context.replace(awaitable);
908 self.with_label_rib(RibKind::Closure, |this| {
909 if awaitable == Awaitable::Yes {
910 match expr {
911 Some(e) => {
912 let syntax_ptr = AstPtr::new(&e);
913 let expr = this.collect_expr(e);
914 this.alloc_expr_desugared_with_ptr(
915 Expr::Async { id: None, statements: Box::new([]), tail: Some(expr) },
916 syntax_ptr,
917 )
918 }
919 None => this.missing_expr(),
920 }
921 } else {
922 this.collect_expr_opt(expr)
923 }
924 })
925 }
926
927 fn type_bounds_from_ast(
928 &mut self,
929 type_bounds_opt: Option<ast::TypeBoundList>,
930 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
931 ) -> ThinVec<TypeBound> {
932 if let Some(type_bounds) = type_bounds_opt {
933 ThinVec::from_iter(Vec::from_iter(
934 type_bounds.bounds().map(|it| self.lower_type_bound(it, impl_trait_lower_fn)),
935 ))
936 } else {
937 ThinVec::from_iter([])
938 }
939 }
940
941 fn lower_path_type(
942 &mut self,
943 path_type: &ast::PathType,
944 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
945 ) -> Option<Path> {
946 let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?;
947 Some(path)
948 }
949
950 fn lower_type_bound(
951 &mut self,
952 node: ast::TypeBound,
953 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
954 ) -> TypeBound {
955 let Some(kind) = node.kind() else { return TypeBound::Error };
956 match kind {
957 ast::TypeBoundKind::PathType(binder, path_type) => {
958 let binder = match binder.and_then(|it| it.generic_param_list()) {
959 Some(gpl) => gpl
960 .lifetime_params()
961 .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<.text())))
962 .collect(),
963 None => ThinVec::default(),
964 };
965 let m = match node.question_mark_token() {
966 Some(_) => TraitBoundModifier::Maybe,
967 None => TraitBoundModifier::None,
968 };
969 self.lower_path_type(&path_type, impl_trait_lower_fn)
970 .map(|p| {
971 let path = self.alloc_path(p, AstPtr::new(&path_type).upcast());
972 if binder.is_empty() {
973 TypeBound::Path(path, m)
974 } else {
975 TypeBound::ForLifetime(binder, path)
976 }
977 })
978 .unwrap_or(TypeBound::Error)
979 }
980 ast::TypeBoundKind::Use(gal) => TypeBound::Use(
981 gal.use_bound_generic_args()
982 .map(|p| match p {
983 ast::UseBoundGenericArg::Lifetime(l) => {
984 UseArgRef::Lifetime(self.lower_lifetime_ref(l))
985 }
986 ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()),
987 })
988 .collect(),
989 ),
990 ast::TypeBoundKind::Lifetime(lifetime) => {
991 TypeBound::Lifetime(self.lower_lifetime_ref(lifetime))
992 }
993 }
994 }
995
996 fn lower_const_arg_opt(&mut self, arg: Option<ast::ConstArg>) -> ConstRef {
997 ConstRef { expr: self.collect_expr_opt(arg.and_then(|it| it.expr())) }
998 }
999
1000 fn lower_const_arg(&mut self, arg: ast::ConstArg) -> ConstRef {
1001 ConstRef { expr: self.collect_expr_opt(arg.expr()) }
1002 }
1003
1004 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
1005 self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
1006 }
1007
1008 fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
1010 let syntax_ptr = AstPtr::new(&expr);
1011 if !self.check_cfg(&expr) {
1012 return None;
1013 }
1014
1015 Some(match expr {
1017 ast::Expr::IfExpr(e) => {
1018 let then_branch = self.collect_block_opt(e.then_branch());
1019
1020 let else_branch = e.else_branch().map(|b| match b {
1021 ast::ElseBranch::Block(it) => self.collect_block(it),
1022 ast::ElseBranch::IfExpr(elif) => {
1023 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
1024 self.collect_expr(expr)
1025 }
1026 });
1027
1028 let condition = self.collect_expr_opt(e.condition());
1029
1030 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
1031 }
1032 ast::Expr::LetExpr(e) => {
1033 let pat = self.collect_pat_top(e.pat());
1034 let expr = self.collect_expr_opt(e.expr());
1035 self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
1036 }
1037 ast::Expr::BlockExpr(e) => match e.modifier() {
1038 Some(ast::BlockModifier::Try(_)) => self.desugar_try_block(e),
1039 Some(ast::BlockModifier::Unsafe(_)) => {
1040 self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
1041 id,
1042 statements,
1043 tail,
1044 })
1045 }
1046 Some(ast::BlockModifier::Label(label)) => {
1047 let label_hygiene = self.hygiene_id_for(label.syntax().text_range());
1048 let label_id = self.collect_label(label);
1049 self.with_labeled_rib(label_id, label_hygiene, |this| {
1050 this.collect_block_(e, |id, statements, tail| Expr::Block {
1051 id,
1052 statements,
1053 tail,
1054 label: Some(label_id),
1055 })
1056 })
1057 }
1058 Some(ast::BlockModifier::Async(_)) => {
1059 self.with_label_rib(RibKind::Closure, |this| {
1060 this.with_awaitable_block(Awaitable::Yes, |this| {
1061 this.collect_block_(e, |id, statements, tail| Expr::Async {
1062 id,
1063 statements,
1064 tail,
1065 })
1066 })
1067 })
1068 }
1069 Some(ast::BlockModifier::Const(_)) => {
1070 self.with_label_rib(RibKind::Constant, |this| {
1071 this.with_awaitable_block(Awaitable::No("constant block"), |this| {
1072 this.with_binding_owner(|this| {
1073 let inner_expr = this.collect_block(e);
1074 this.alloc_expr(Expr::Const(inner_expr), syntax_ptr)
1075 })
1076 })
1077 })
1078 }
1079 Some(ast::BlockModifier::AsyncGen(_)) => {
1081 self.with_awaitable_block(Awaitable::Yes, |this| this.collect_block(e))
1082 }
1083 Some(ast::BlockModifier::Gen(_)) => self
1084 .with_awaitable_block(Awaitable::No("non-async gen block"), |this| {
1085 this.collect_block(e)
1086 }),
1087 None => self.collect_block(e),
1088 },
1089 ast::Expr::LoopExpr(e) => {
1090 let label = e.label().map(|label| {
1091 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1092 });
1093 let body = self.collect_labelled_block_opt(label, e.loop_body());
1094 self.alloc_expr(Expr::Loop { body, label: label.map(|it| it.1) }, syntax_ptr)
1095 }
1096 ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e),
1097 ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
1098 ast::Expr::CallExpr(e) => {
1099 let is_rustc_box = {
1101 let attrs = e.attrs();
1102 attrs.filter_map(|it| it.as_simple_atom()).any(|it| it == "rustc_box")
1103 };
1104 if is_rustc_box {
1105 let expr = self.collect_expr_opt(e.arg_list().and_then(|it| it.args().next()));
1106 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
1107 } else {
1108 let callee = self.collect_expr_opt(e.expr());
1109 let args = if let Some(arg_list) = e.arg_list() {
1110 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
1111 } else {
1112 Box::default()
1113 };
1114 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
1115 }
1116 }
1117 ast::Expr::MethodCallExpr(e) => {
1118 let receiver = self.collect_expr_opt(e.receiver());
1119 let args = if let Some(arg_list) = e.arg_list() {
1120 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
1121 } else {
1122 Box::default()
1123 };
1124 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
1125 let generic_args = e
1126 .generic_arg_list()
1127 .and_then(|it| {
1128 self.lower_generic_args(it, &mut Self::impl_trait_error_allocator)
1129 })
1130 .map(Box::new);
1131 self.alloc_expr(
1132 Expr::MethodCall { receiver, method_name, args, generic_args },
1133 syntax_ptr,
1134 )
1135 }
1136 ast::Expr::MatchExpr(e) => {
1137 let expr = self.collect_expr_opt(e.expr());
1138 let arms = if let Some(match_arm_list) = e.match_arm_list() {
1139 match_arm_list
1140 .arms()
1141 .filter_map(|arm| {
1142 if self.check_cfg(&arm) {
1143 Some(MatchArm {
1144 pat: self.collect_pat_top(arm.pat()),
1145 expr: self.collect_expr_opt(arm.expr()),
1146 guard: arm
1147 .guard()
1148 .map(|guard| self.collect_expr_opt(guard.condition())),
1149 })
1150 } else {
1151 None
1152 }
1153 })
1154 .collect()
1155 } else {
1156 Box::default()
1157 };
1158 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
1159 }
1160 ast::Expr::PathExpr(e) => {
1161 let (path, hygiene) = self
1162 .collect_expr_path(e)
1163 .map(|(path, hygiene)| (Expr::Path(path), hygiene))
1164 .unwrap_or((Expr::Missing, HygieneId::ROOT));
1165 let expr_id = self.alloc_expr(path, syntax_ptr);
1166 if !hygiene.is_root() {
1167 self.store.ident_hygiene.insert(expr_id.into(), hygiene);
1168 }
1169 expr_id
1170 }
1171 ast::Expr::ContinueExpr(e) => {
1172 let label = self.resolve_label(e.lifetime()).unwrap_or_else(|e| {
1173 self.store.diagnostics.push(e);
1174 None
1175 });
1176 self.alloc_expr(Expr::Continue { label }, syntax_ptr)
1177 }
1178 ast::Expr::BreakExpr(e) => {
1179 let label = self.resolve_label(e.lifetime()).unwrap_or_else(|e| {
1180 self.store.diagnostics.push(e);
1181 None
1182 });
1183 let expr = e.expr().map(|e| self.collect_expr(e));
1184 self.alloc_expr(Expr::Break { expr, label }, syntax_ptr)
1185 }
1186 ast::Expr::ParenExpr(e) => {
1187 let inner = self.collect_expr_opt(e.expr());
1188 let src = self.expander.in_file(syntax_ptr);
1190 self.store.expr_map.insert(src, inner.into());
1191 inner
1192 }
1193 ast::Expr::ReturnExpr(e) => {
1194 let expr = e.expr().map(|e| self.collect_expr(e));
1195 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
1196 }
1197 ast::Expr::BecomeExpr(e) => {
1198 let expr =
1199 e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
1200 self.alloc_expr(Expr::Become { expr }, syntax_ptr)
1201 }
1202 ast::Expr::YieldExpr(e) => {
1203 self.is_lowering_coroutine = true;
1204 let expr = e.expr().map(|e| self.collect_expr(e));
1205 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
1206 }
1207 ast::Expr::YeetExpr(e) => {
1208 let expr = e.expr().map(|e| self.collect_expr(e));
1209 self.alloc_expr(Expr::Yeet { expr }, syntax_ptr)
1210 }
1211 ast::Expr::RecordExpr(e) => {
1212 let path = e
1213 .path()
1214 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1215 .map(Box::new);
1216 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
1217 let fields = nfl
1218 .fields()
1219 .filter_map(|field| {
1220 if !self.check_cfg(&field) {
1221 return None;
1222 }
1223
1224 let name = field.field_name()?.as_name();
1225
1226 let expr = match field.expr() {
1227 Some(e) => self.collect_expr(e),
1228 None => self.missing_expr(),
1229 };
1230 let src = self.expander.in_file(AstPtr::new(&field));
1231 self.store.field_map_back.insert(expr, src);
1232 Some(RecordLitField { name, expr })
1233 })
1234 .collect();
1235 let spread = nfl.spread().map(|s| self.collect_expr(s));
1236 Expr::RecordLit { path, fields, spread }
1237 } else {
1238 Expr::RecordLit { path, fields: Box::default(), spread: None }
1239 };
1240
1241 self.alloc_expr(record_lit, syntax_ptr)
1242 }
1243 ast::Expr::FieldExpr(e) => {
1244 let expr = self.collect_expr_opt(e.expr());
1245 let name = match e.field_access() {
1246 Some(kind) => kind.as_name(),
1247 _ => Name::missing(),
1248 };
1249 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
1250 }
1251 ast::Expr::AwaitExpr(e) => {
1252 let expr = self.collect_expr_opt(e.expr());
1253 if let Awaitable::No(location) = self.is_lowering_awaitable_block() {
1254 self.store.diagnostics.push(ExpressionStoreDiagnostics::AwaitOutsideOfAsync {
1255 node: self.expander.in_file(AstPtr::new(&e)),
1256 location: location.to_string(),
1257 });
1258 }
1259 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
1260 }
1261 ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
1262 ast::Expr::CastExpr(e) => {
1263 let expr = self.collect_expr_opt(e.expr());
1264 let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty());
1265 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
1266 }
1267 ast::Expr::RefExpr(e) => {
1268 let expr = self.collect_expr_opt(e.expr());
1269 let raw_tok = e.raw_token().is_some();
1270 let mutability = if raw_tok {
1271 if e.mut_token().is_some() { Mutability::Mut } else { Mutability::Shared }
1272 } else {
1273 Mutability::from_mutable(e.mut_token().is_some())
1274 };
1275 let rawness = Rawness::from_raw(raw_tok);
1276 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
1277 }
1278 ast::Expr::PrefixExpr(e) => {
1279 let expr = self.collect_expr_opt(e.expr());
1280 match e.op_kind() {
1281 Some(op) => self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr),
1282 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1283 }
1284 }
1285 ast::Expr::ClosureExpr(e) => self.with_label_rib(RibKind::Closure, |this| {
1286 this.with_binding_owner(|this| {
1287 let mut args = Vec::new();
1288 let mut arg_types = Vec::new();
1289 if let Some(pl) = e.param_list() {
1290 let num_params = pl.params().count();
1291 args.reserve_exact(num_params);
1292 arg_types.reserve_exact(num_params);
1293 for param in pl.params() {
1294 let pat = this.collect_pat_top(param.pat());
1295 let type_ref =
1296 param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it));
1297 args.push(pat);
1298 arg_types.push(type_ref);
1299 }
1300 }
1301 let ret_type = e
1302 .ret_type()
1303 .and_then(|r| r.ty())
1304 .map(|it| this.lower_type_ref_disallow_impl_trait(it));
1305
1306 let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
1307 let prev_try_block_label = this.current_try_block_label.take();
1308
1309 let awaitable = if e.async_token().is_some() {
1310 Awaitable::Yes
1311 } else {
1312 Awaitable::No("non-async closure")
1313 };
1314 let body = this
1315 .with_awaitable_block(awaitable, |this| this.collect_expr_opt(e.body()));
1316
1317 let closure_kind = if this.is_lowering_coroutine {
1318 let movability = if e.static_token().is_some() {
1319 Movability::Static
1320 } else {
1321 Movability::Movable
1322 };
1323 ClosureKind::Coroutine(movability)
1324 } else if e.async_token().is_some() {
1325 ClosureKind::Async
1326 } else {
1327 ClosureKind::Closure
1328 };
1329 let capture_by =
1330 if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
1331 this.is_lowering_coroutine = prev_is_lowering_coroutine;
1332 this.current_try_block_label = prev_try_block_label;
1333 this.alloc_expr(
1334 Expr::Closure {
1335 args: args.into(),
1336 arg_types: arg_types.into(),
1337 ret_type,
1338 body,
1339 closure_kind,
1340 capture_by,
1341 },
1342 syntax_ptr,
1343 )
1344 })
1345 }),
1346 ast::Expr::BinExpr(e) => {
1347 let op = e.op_kind();
1348 if let Some(ast::BinaryOp::Assignment { op: None }) = op {
1349 let target = self.collect_expr_as_pat_opt(e.lhs());
1350 let value = self.collect_expr_opt(e.rhs());
1351 self.alloc_expr(Expr::Assignment { target, value }, syntax_ptr)
1352 } else {
1353 let lhs = self.collect_expr_opt(e.lhs());
1354 let rhs = self.collect_expr_opt(e.rhs());
1355 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
1356 }
1357 }
1358 ast::Expr::TupleExpr(e) => {
1359 let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect();
1360 if comma_follows_token(e.l_paren_token()) {
1363 exprs.insert(0, self.missing_expr());
1364 }
1365
1366 self.alloc_expr(Expr::Tuple { exprs: exprs.into_boxed_slice() }, syntax_ptr)
1367 }
1368 ast::Expr::ArrayExpr(e) => {
1369 let kind = e.kind();
1370
1371 match kind {
1372 ArrayExprKind::ElementList(e) => {
1373 let elements = e.map(|expr| self.collect_expr(expr)).collect();
1374 self.alloc_expr(Expr::Array(Array::ElementList { elements }), syntax_ptr)
1375 }
1376 ArrayExprKind::Repeat { initializer, repeat } => {
1377 let initializer = self.collect_expr_opt(initializer);
1378 let repeat = self.with_label_rib(RibKind::Constant, |this| {
1379 if let Some(repeat) = repeat {
1380 this.with_binding_owner(|this| this.collect_expr(repeat))
1381 } else {
1382 this.missing_expr()
1383 }
1384 });
1385 self.alloc_expr(
1386 Expr::Array(Array::Repeat { initializer, repeat }),
1387 syntax_ptr,
1388 )
1389 }
1390 }
1391 }
1392
1393 ast::Expr::Literal(e) => self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr),
1394 ast::Expr::IndexExpr(e) => {
1395 let base = self.collect_expr_opt(e.base());
1396 let index = self.collect_expr_opt(e.index());
1397 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
1398 }
1399 ast::Expr::RangeExpr(e) => {
1400 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
1401 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
1402 match e.op_kind() {
1403 Some(range_type) => {
1404 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
1405 }
1406 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1407 }
1408 }
1409 ast::Expr::MacroExpr(e) => {
1410 let e = e.macro_call()?;
1411 let macro_ptr = AstPtr::new(&e);
1412 let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
1413 expansion.map(|it| this.collect_expr(it))
1414 });
1415 match id {
1416 Some(id) => {
1417 let src = self.expander.in_file(syntax_ptr);
1420 self.store.expr_map.insert(src, id.into());
1421 id
1422 }
1423 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1424 }
1425 }
1426 ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
1427 ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr),
1428 ast::Expr::OffsetOfExpr(e) => {
1429 let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty());
1430 let fields = e.fields().map(|it| it.as_name()).collect();
1431 self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
1432 }
1433 ast::Expr::FormatArgsExpr(f) => self.collect_format_args(f, syntax_ptr),
1434 })
1435 }
1436
1437 fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
1438 e.path().and_then(|path| {
1439 let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?;
1440 let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
1442 let hygiene = if may_be_variable {
1443 self.hygiene_id_for(e.syntax().text_range())
1444 } else {
1445 HygieneId::ROOT
1446 };
1447 Some((path, hygiene))
1448 })
1449 }
1450
1451 fn collect_expr_as_pat_opt(&mut self, expr: Option<ast::Expr>) -> PatId {
1452 match expr {
1453 Some(expr) => self.collect_expr_as_pat(expr),
1454 _ => self.missing_pat(),
1455 }
1456 }
1457
1458 fn collect_expr_as_pat(&mut self, expr: ast::Expr) -> PatId {
1459 self.maybe_collect_expr_as_pat(&expr).unwrap_or_else(|| {
1460 let src = self.expander.in_file(AstPtr::new(&expr).wrap_left());
1461 let expr = self.collect_expr(expr);
1462 let id = self.store.pats.alloc(Pat::Expr(expr));
1464 self.store.pat_map_back.insert(id, src);
1465 id
1466 })
1467 }
1468
1469 fn maybe_collect_expr_as_pat(&mut self, expr: &ast::Expr) -> Option<PatId> {
1470 if !self.check_cfg(expr) {
1471 return None;
1472 }
1473 let syntax_ptr = AstPtr::new(expr);
1474
1475 let result = match expr {
1476 ast::Expr::UnderscoreExpr(_) => self.alloc_pat_from_expr(Pat::Wild, syntax_ptr),
1477 ast::Expr::ParenExpr(e) => {
1478 if let Some(ast::Expr::RangeExpr(range)) = e.expr()
1480 && range.is_range_full()
1481 {
1482 return Some(self.alloc_pat_from_expr(
1483 Pat::Tuple { args: Box::default(), ellipsis: Some(0) },
1484 syntax_ptr,
1485 ));
1486 }
1487 return e.expr().and_then(|expr| self.maybe_collect_expr_as_pat(&expr));
1488 }
1489 ast::Expr::TupleExpr(e) => {
1490 let (ellipsis, args) = collect_tuple(self, e.fields());
1491 self.alloc_pat_from_expr(Pat::Tuple { args, ellipsis }, syntax_ptr)
1492 }
1493 ast::Expr::ArrayExpr(e) => {
1494 if e.semicolon_token().is_some() {
1495 return None;
1496 }
1497
1498 let mut elements = e.exprs();
1499 let prefix = elements
1500 .by_ref()
1501 .map_while(|elem| collect_possibly_rest(self, elem).left())
1502 .collect();
1503 let suffix = elements.map(|elem| self.collect_expr_as_pat(elem)).collect();
1504 self.alloc_pat_from_expr(Pat::Slice { prefix, slice: None, suffix }, syntax_ptr)
1505 }
1506 ast::Expr::CallExpr(e) => {
1507 let path = collect_path(self, e.expr()?)?;
1508 let path = path
1509 .path()
1510 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1511 .map(Box::new);
1512 let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
1513 self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
1514 }
1515 ast::Expr::PathExpr(e) => {
1516 let (path, hygiene) = self
1517 .collect_expr_path(e.clone())
1518 .map(|(path, hygiene)| (Pat::Path(path), hygiene))
1519 .unwrap_or((Pat::Missing, HygieneId::ROOT));
1520 let pat_id = self.alloc_pat_from_expr(path, syntax_ptr);
1521 if !hygiene.is_root() {
1522 self.store.ident_hygiene.insert(pat_id.into(), hygiene);
1523 }
1524 pat_id
1525 }
1526 ast::Expr::MacroExpr(e) => {
1527 let e = e.macro_call()?;
1528 let macro_ptr = AstPtr::new(&e);
1529 let src = self.expander.in_file(AstPtr::new(expr));
1530 let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
1531 this.collect_expr_as_pat_opt(expansion)
1532 });
1533 self.store.expr_map.insert(src, id.into());
1534 id
1535 }
1536 ast::Expr::RecordExpr(e) => {
1537 let path = e
1538 .path()
1539 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1540 .map(Box::new);
1541 let record_field_list = e.record_expr_field_list()?;
1542 let ellipsis = record_field_list.dotdot_token().is_some();
1543 let args = record_field_list
1545 .fields()
1546 .filter_map(|f| {
1547 if !self.check_cfg(&f) {
1548 return None;
1549 }
1550 let field_expr = f.expr()?;
1551 let pat = self.collect_expr_as_pat(field_expr);
1552 let name = f.field_name()?.as_name();
1553 let src = self.expander.in_file(AstPtr::new(&f).wrap_left());
1554 self.store.pat_field_map_back.insert(pat, src);
1555 Some(RecordFieldPat { name, pat })
1556 })
1557 .collect();
1558 self.alloc_pat_from_expr(Pat::Record { path, args, ellipsis }, syntax_ptr)
1559 }
1560 _ => return None,
1561 };
1562 return Some(result);
1563
1564 fn collect_path(this: &mut ExprCollector<'_>, expr: ast::Expr) -> Option<ast::PathExpr> {
1565 match expr {
1566 ast::Expr::PathExpr(e) => Some(e),
1567 ast::Expr::MacroExpr(mac) => {
1568 let call = mac.macro_call()?;
1569 {
1570 let macro_ptr = AstPtr::new(&call);
1571 this.collect_macro_call(call, macro_ptr, true, |this, expanded_path| {
1572 collect_path(this, expanded_path?)
1573 })
1574 }
1575 }
1576 _ => None,
1577 }
1578 }
1579
1580 fn collect_possibly_rest(
1581 this: &mut ExprCollector<'_>,
1582 expr: ast::Expr,
1583 ) -> Either<PatId, ()> {
1584 match &expr {
1585 ast::Expr::RangeExpr(e) if e.is_range_full() => Either::Right(()),
1586 ast::Expr::MacroExpr(mac) => match mac.macro_call() {
1587 Some(call) => {
1588 let macro_ptr = AstPtr::new(&call);
1589 let pat = this.collect_macro_call(
1590 call,
1591 macro_ptr,
1592 true,
1593 |this, expanded_expr| match expanded_expr {
1594 Some(expanded_pat) => collect_possibly_rest(this, expanded_pat),
1595 None => Either::Left(this.missing_pat()),
1596 },
1597 );
1598 if let Either::Left(pat) = pat {
1599 let src = this.expander.in_file(AstPtr::new(&expr).wrap_left());
1600 this.store.pat_map_back.insert(pat, src);
1601 }
1602 pat
1603 }
1604 None => {
1605 let ptr = AstPtr::new(&expr);
1606 Either::Left(this.alloc_pat_from_expr(Pat::Missing, ptr))
1607 }
1608 },
1609 _ => Either::Left(this.collect_expr_as_pat(expr)),
1610 }
1611 }
1612
1613 fn collect_tuple(
1614 this: &mut ExprCollector<'_>,
1615 fields: ast::AstChildren<ast::Expr>,
1616 ) -> (Option<u32>, Box<[la_arena::Idx<Pat>]>) {
1617 let mut ellipsis = None;
1618 let args = fields
1619 .enumerate()
1620 .filter_map(|(idx, elem)| {
1621 match collect_possibly_rest(this, elem) {
1622 Either::Left(pat) => Some(pat),
1623 Either::Right(()) => {
1624 if ellipsis.is_none() {
1625 ellipsis = Some(idx as u32);
1626 }
1627 None
1629 }
1630 }
1631 })
1632 .collect();
1633 (ellipsis, args)
1634 }
1635 }
1636
1637 fn with_binding_owner(&mut self, create_expr: impl FnOnce(&mut Self) -> ExprId) -> ExprId {
1638 let prev_unowned_bindings_len = self.unowned_bindings.len();
1639 let expr_id = create_expr(self);
1640 for binding in self.unowned_bindings.drain(prev_unowned_bindings_len..) {
1641 self.store.binding_owners.insert(binding, expr_id);
1642 }
1643 expr_id
1644 }
1645
1646 fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
1650 let try_from_output = self.lang_path(self.lang_items().TryTraitFromOutput);
1651 let label = self.generate_new_name();
1652 let label = self.alloc_label_desugared(Label { name: label });
1653 let old_label = self.current_try_block_label.replace(label);
1654
1655 let ptr = AstPtr::new(&e).upcast();
1656 let (btail, expr_id) = self.with_labeled_rib(label, HygieneId::ROOT, |this| {
1657 let mut btail = None;
1658 let block = this.collect_block_(e, |id, statements, tail| {
1659 btail = tail;
1660 Expr::Block { id, statements, tail, label: Some(label) }
1661 });
1662 (btail, block)
1663 });
1664
1665 let callee = self
1666 .alloc_expr_desugared_with_ptr(try_from_output.map_or(Expr::Missing, Expr::Path), ptr);
1667 let next_tail = match btail {
1668 Some(tail) => self
1669 .alloc_expr_desugared_with_ptr(Expr::Call { callee, args: Box::new([tail]) }, ptr),
1670 None => {
1671 let unit =
1672 self.alloc_expr_desugared_with_ptr(Expr::Tuple { exprs: Box::new([]) }, ptr);
1673 self.alloc_expr_desugared_with_ptr(
1674 Expr::Call { callee, args: Box::new([unit]) },
1675 ptr,
1676 )
1677 }
1678 };
1679 let Expr::Block { tail, .. } = &mut self.store.exprs[expr_id] else {
1680 unreachable!("block was lowered to non-block");
1681 };
1682 *tail = Some(next_tail);
1683 self.current_try_block_label = old_label;
1684 expr_id
1685 }
1686
1687 fn collect_while_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::WhileExpr) -> ExprId {
1701 let label = e.label().map(|label| {
1702 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1703 });
1704 let body = self.collect_labelled_block_opt(label, e.loop_body());
1705
1706 let condition = match label {
1720 Some((label_hygiene, label)) => self.with_labeled_rib(label, label_hygiene, |this| {
1721 this.collect_expr_opt(e.condition())
1722 }),
1723 None => self.collect_expr_opt(e.condition()),
1724 };
1725
1726 let break_expr = self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr);
1727 let if_expr = self.alloc_expr(
1728 Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
1729 syntax_ptr,
1730 );
1731 self.alloc_expr(Expr::Loop { body: if_expr, label: label.map(|it| it.1) }, syntax_ptr)
1732 }
1733
1734 fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
1748 let lang_items = self.lang_items();
1749 let into_iter_fn = self.lang_path(lang_items.IntoIterIntoIter);
1750 let iter_next_fn = self.lang_path(lang_items.IteratorNext);
1751 let option_some = self.lang_path(lang_items.OptionSome);
1752 let option_none = self.lang_path(lang_items.OptionNone);
1753 let head = self.collect_expr_opt(e.iterable());
1754 let into_iter_fn_expr =
1755 self.alloc_expr(into_iter_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1756 let iterator = self.alloc_expr(
1757 Expr::Call { callee: into_iter_fn_expr, args: Box::new([head]) },
1758 syntax_ptr,
1759 );
1760 let none_arm = MatchArm {
1761 pat: self.alloc_pat_desugared(option_none.map_or(Pat::Missing, Pat::Path)),
1762 guard: None,
1763 expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr),
1764 };
1765 let some_pat = Pat::TupleStruct {
1766 path: option_some.map(Box::new),
1767 args: Box::new([self.collect_pat_top(e.pat())]),
1768 ellipsis: None,
1769 };
1770 let label = e.label().map(|label| {
1771 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1772 });
1773 let some_arm = MatchArm {
1774 pat: self.alloc_pat_desugared(some_pat),
1775 guard: None,
1776 expr: self.with_opt_labeled_rib(label, |this| {
1777 this.collect_expr_opt(e.loop_body().map(|it| it.into()))
1778 }),
1779 };
1780 let iter_name = self.generate_new_name();
1781 let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
1782 let iter_expr_mut = self.alloc_expr(
1783 Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
1784 syntax_ptr,
1785 );
1786 let iter_next_fn_expr =
1787 self.alloc_expr(iter_next_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1788 let iter_next_expr = self.alloc_expr(
1789 Expr::Call { callee: iter_next_fn_expr, args: Box::new([iter_expr_mut]) },
1790 syntax_ptr,
1791 );
1792 let loop_inner = self.alloc_expr(
1793 Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
1794 syntax_ptr,
1795 );
1796 let loop_inner = self.alloc_expr(
1797 Expr::Block {
1798 id: None,
1799 statements: Box::default(),
1800 tail: Some(loop_inner),
1801 label: None,
1802 },
1803 syntax_ptr,
1804 );
1805 let loop_outer = self
1806 .alloc_expr(Expr::Loop { body: loop_inner, label: label.map(|it| it.1) }, syntax_ptr);
1807 let iter_binding =
1808 self.alloc_binding(iter_name, BindingAnnotation::Mutable, HygieneId::ROOT);
1809 let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
1810 self.add_definition_to_binding(iter_binding, iter_pat);
1811 self.alloc_expr(
1812 Expr::Match {
1813 expr: iterator,
1814 arms: Box::new([MatchArm { pat: iter_pat, guard: None, expr: loop_outer }]),
1815 },
1816 syntax_ptr,
1817 )
1818 }
1819
1820 fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
1832 let lang_items = self.lang_items();
1833 let try_branch = self.lang_path(lang_items.TryTraitBranch);
1834 let cf_continue = self.lang_path(lang_items.ControlFlowContinue);
1835 let cf_break = self.lang_path(lang_items.ControlFlowBreak);
1836 let try_from_residual = self.lang_path(lang_items.TryTraitFromResidual);
1837 let operand = self.collect_expr_opt(e.expr());
1838 let try_branch = self.alloc_expr(try_branch.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1839 let expr = self
1840 .alloc_expr(Expr::Call { callee: try_branch, args: Box::new([operand]) }, syntax_ptr);
1841 let continue_name = self.generate_new_name();
1842 let continue_binding = self.alloc_binding(
1843 continue_name.clone(),
1844 BindingAnnotation::Unannotated,
1845 HygieneId::ROOT,
1846 );
1847 let continue_bpat =
1848 self.alloc_pat_desugared(Pat::Bind { id: continue_binding, subpat: None });
1849 self.add_definition_to_binding(continue_binding, continue_bpat);
1850 let continue_arm = MatchArm {
1851 pat: self.alloc_pat_desugared(Pat::TupleStruct {
1852 path: cf_continue.map(Box::new),
1853 args: Box::new([continue_bpat]),
1854 ellipsis: None,
1855 }),
1856 guard: None,
1857 expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
1858 };
1859 let break_name = self.generate_new_name();
1860 let break_binding =
1861 self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated, HygieneId::ROOT);
1862 let break_bpat = self.alloc_pat_desugared(Pat::Bind { id: break_binding, subpat: None });
1863 self.add_definition_to_binding(break_binding, break_bpat);
1864 let break_arm = MatchArm {
1865 pat: self.alloc_pat_desugared(Pat::TupleStruct {
1866 path: cf_break.map(Box::new),
1867 args: Box::new([break_bpat]),
1868 ellipsis: None,
1869 }),
1870 guard: None,
1871 expr: {
1872 let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr);
1873 let callee = self
1874 .alloc_expr(try_from_residual.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1875 let result =
1876 self.alloc_expr(Expr::Call { callee, args: Box::new([it]) }, syntax_ptr);
1877 self.alloc_expr(
1878 match self.current_try_block_label {
1879 Some(label) => Expr::Break { expr: Some(result), label: Some(label) },
1880 None => Expr::Return { expr: Some(result) },
1881 },
1882 syntax_ptr,
1883 )
1884 },
1885 };
1886 let arms = Box::new([continue_arm, break_arm]);
1887 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
1888 }
1889
1890 fn collect_macro_call<T, U>(
1891 &mut self,
1892 mcall: ast::MacroCall,
1893 syntax_ptr: AstPtr<ast::MacroCall>,
1894 record_diagnostics: bool,
1895 collector: impl FnOnce(&mut Self, Option<T>) -> U,
1896 ) -> U
1897 where
1898 T: ast::AstNode,
1899 {
1900 let macro_call_ptr = self.expander.in_file(syntax_ptr);
1901
1902 let block_call = self.def_map.modules[self.module].scope.macro_invoc(
1903 self.expander.in_file(self.expander.ast_id_map().ast_id_for_ptr(syntax_ptr)),
1904 );
1905 let res = match block_call {
1906 Some(call) => Ok(self.expander.enter_expand_id(self.db, call)),
1908 None => {
1909 let resolver = |path: &_| {
1910 self.def_map
1911 .resolve_path(
1912 self.local_def_map,
1913 self.db,
1914 self.module,
1915 path,
1916 crate::item_scope::BuiltinShadowMode::Other,
1917 Some(MacroSubNs::Bang),
1918 )
1919 .0
1920 .take_macros()
1921 };
1922 self.expander.enter_expand(
1923 self.db,
1924 mcall,
1925 self.krate,
1926 resolver,
1927 &mut |ptr, call| {
1928 _ = self.store.expansions.insert(ptr.map(|(it, _)| it), call);
1929 },
1930 )
1931 }
1932 };
1933
1934 let res = match res {
1935 Ok(res) => res,
1936 Err(UnresolvedMacro { path }) => {
1937 if record_diagnostics {
1938 self.store.diagnostics.push(ExpressionStoreDiagnostics::UnresolvedMacroCall {
1939 node: self.expander.in_file(syntax_ptr),
1940 path,
1941 });
1942 }
1943 return collector(self, None);
1944 }
1945 };
1946 match res.value {
1949 Some((mark, expansion)) => {
1950 if let Some(macro_file) = self.expander.current_file_id().macro_file() {
1953 self.store.expansions.insert(macro_call_ptr, macro_file);
1954 }
1955
1956 let id = collector(self, expansion.map(|it| it.tree()));
1957 self.expander.exit(mark);
1958 id
1959 }
1960 None => collector(self, None),
1961 }
1962 }
1963
1964 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
1965 match expr {
1966 Some(expr) => self.collect_expr(expr),
1967 None => self.missing_expr(),
1968 }
1969 }
1970
1971 fn collect_macro_as_stmt(
1972 &mut self,
1973 statements: &mut Vec<Statement>,
1974 mac: ast::MacroExpr,
1975 ) -> Option<ExprId> {
1976 let mac_call = mac.macro_call()?;
1977 let syntax_ptr = AstPtr::new(&ast::Expr::from(mac));
1978 let macro_ptr = AstPtr::new(&mac_call);
1979 let expansion = self.collect_macro_call(
1980 mac_call,
1981 macro_ptr,
1982 false,
1983 |this, expansion: Option<ast::MacroStmts>| match expansion {
1984 Some(expansion) => {
1985 expansion.statements().for_each(|stmt| this.collect_stmt(statements, stmt));
1986 expansion.expr().and_then(|expr| match expr {
1987 ast::Expr::MacroExpr(mac) => this.collect_macro_as_stmt(statements, mac),
1988 expr => Some(this.collect_expr(expr)),
1989 })
1990 }
1991 None => None,
1992 },
1993 );
1994 expansion.inspect(|&tail| {
1995 let src = self.expander.in_file(syntax_ptr);
1998 self.store.expr_map.insert(src, tail.into());
1999 })
2000 }
2001
2002 fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) {
2003 match s {
2004 ast::Stmt::LetStmt(stmt) => {
2005 if !self.check_cfg(&stmt) {
2006 return;
2007 }
2008 let pat = self.collect_pat_top(stmt.pat());
2009 let type_ref = stmt.ty().map(|it| self.lower_type_ref_disallow_impl_trait(it));
2010 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
2011 let else_branch = stmt
2012 .let_else()
2013 .and_then(|let_else| let_else.block_expr())
2014 .map(|block| self.collect_block(block));
2015 statements.push(Statement::Let { pat, type_ref, initializer, else_branch });
2016 }
2017 ast::Stmt::ExprStmt(stmt) => {
2018 let expr = stmt.expr();
2019 match &expr {
2020 Some(expr) if !self.check_cfg(expr) => return,
2021 _ => (),
2022 }
2023 let has_semi = stmt.semicolon_token().is_some();
2024 if let Some(ast::Expr::MacroExpr(mac)) = expr {
2026 if let Some(expr) = self.collect_macro_as_stmt(statements, mac) {
2027 statements.push(Statement::Expr { expr, has_semi })
2028 }
2029 } else {
2030 let expr = self.collect_expr_opt(expr);
2031 statements.push(Statement::Expr { expr, has_semi });
2032 }
2033 }
2034 ast::Stmt::Item(ast::Item::MacroDef(macro_)) => {
2035 if !self.check_cfg(¯o_) {
2036 return;
2037 }
2038 let Some(name) = macro_.name() else {
2039 statements.push(Statement::Item(Item::Other));
2040 return;
2041 };
2042 let name = name.as_name();
2043 let macro_id =
2044 self.def_map.modules[self.def_map.root].scope.get(&name).take_macros();
2045 self.collect_macro_def(statements, macro_id);
2046 }
2047 ast::Stmt::Item(ast::Item::MacroRules(macro_)) => {
2048 if !self.check_cfg(¯o_) {
2049 return;
2050 }
2051 let Some(name) = macro_.name() else {
2052 statements.push(Statement::Item(Item::Other));
2053 return;
2054 };
2055 let name = name.as_name();
2056 let macro_defs_count =
2057 self.current_block_legacy_macro_defs_count.entry(name.clone()).or_insert(0);
2058 let macro_id = self.def_map.modules[self.def_map.root]
2059 .scope
2060 .get_legacy_macro(&name)
2061 .and_then(|it| it.get(*macro_defs_count))
2062 .copied();
2063 *macro_defs_count += 1;
2064 self.collect_macro_def(statements, macro_id);
2065 }
2066 ast::Stmt::Item(_item) => statements.push(Statement::Item(Item::Other)),
2067 }
2068 }
2069
2070 fn collect_macro_def(&mut self, statements: &mut Vec<Statement>, macro_id: Option<MacroId>) {
2071 let Some(macro_id) = macro_id else {
2072 never!("def map should have macro definition, but it doesn't");
2073 statements.push(Statement::Item(Item::Other));
2074 return;
2075 };
2076 let macro_id = self.db.macro_def(macro_id);
2077 statements.push(Statement::Item(Item::MacroDef(Box::new(macro_id))));
2078 self.label_ribs.push(LabelRib::new(RibKind::MacroDef(Box::new(macro_id))));
2079 }
2080
2081 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
2082 self.collect_block_(block, |id, statements, tail| Expr::Block {
2083 id,
2084 statements,
2085 tail,
2086 label: None,
2087 })
2088 }
2089
2090 fn collect_block_(
2091 &mut self,
2092 block: ast::BlockExpr,
2093 mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr,
2094 ) -> ExprId {
2095 let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| {
2096 let ast_id = self.expander.in_file(file_local_id);
2097 self.db.intern_block(BlockLoc { ast_id, module: self.module })
2098 });
2099
2100 let (module, def_map) =
2101 match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) {
2102 Some((def_map, block_id)) => {
2103 self.store.block_scopes.push(block_id);
2104 (def_map.root_module_id(), def_map)
2105 }
2106 None => (self.module, self.def_map),
2107 };
2108 let prev_def_map = mem::replace(&mut self.def_map, def_map);
2109 let prev_local_module = mem::replace(&mut self.module, module);
2110 let prev_legacy_macros_count = mem::take(&mut self.current_block_legacy_macro_defs_count);
2111
2112 let mut statements = Vec::new();
2113 block.statements().for_each(|s| self.collect_stmt(&mut statements, s));
2114 let tail = block.tail_expr().and_then(|e| match e {
2115 ast::Expr::MacroExpr(mac) => self.collect_macro_as_stmt(&mut statements, mac),
2116 expr => self.maybe_collect_expr(expr),
2117 });
2118 let tail = tail.or_else(|| {
2119 let stmt = statements.pop()?;
2120 if let Statement::Expr { expr, has_semi: false } = stmt {
2121 return Some(expr);
2122 }
2123 statements.push(stmt);
2124 None
2125 });
2126
2127 let syntax_node_ptr = AstPtr::new(&block.into());
2128 let expr_id = self
2129 .alloc_expr(mk_block(block_id, statements.into_boxed_slice(), tail), syntax_node_ptr);
2130
2131 self.def_map = prev_def_map;
2132 self.module = prev_local_module;
2133 self.current_block_legacy_macro_defs_count = prev_legacy_macros_count;
2134 expr_id
2135 }
2136
2137 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
2138 match expr {
2139 Some(block) => self.collect_block(block),
2140 None => self.missing_expr(),
2141 }
2142 }
2143
2144 fn collect_labelled_block_opt(
2145 &mut self,
2146 label: Option<(HygieneId, LabelId)>,
2147 expr: Option<ast::BlockExpr>,
2148 ) -> ExprId {
2149 match label {
2150 Some((hygiene, label)) => {
2151 self.with_labeled_rib(label, hygiene, |this| this.collect_block_opt(expr))
2152 }
2153 None => self.collect_block_opt(expr),
2154 }
2155 }
2156
2157 fn collect_pat_top(&mut self, pat: Option<ast::Pat>) -> PatId {
2160 match pat {
2161 Some(pat) => self.collect_pat(pat, &mut BindingList::default()),
2162 None => self.missing_pat(),
2163 }
2164 }
2165
2166 fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
2167 let pattern = match &pat {
2168 ast::Pat::IdentPat(bp) => {
2169 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
2170 let hygiene = bp
2171 .name()
2172 .map(|name| self.hygiene_id_for(name.syntax().text_range()))
2173 .unwrap_or(HygieneId::ROOT);
2174
2175 let annotation =
2176 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
2177 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat, binding_list));
2178
2179 let is_simple_ident_pat =
2180 annotation == BindingAnnotation::Unannotated && subpat.is_none();
2181 let (binding, pattern) = if is_simple_ident_pat {
2182 let (resolved, _) = self.def_map.resolve_path(
2185 self.local_def_map,
2186 self.db,
2187 self.module,
2188 &name.clone().into(),
2189 BuiltinShadowMode::Other,
2190 None,
2191 );
2192 match resolved.take_values() {
2196 Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
2197 Some(ModuleDefId::EnumVariantId(variant))
2198 if variant.fields(self.db).shape != FieldsShape::Record =>
2200 {
2201 (None, Pat::Path(name.into()))
2202 }
2203 Some(ModuleDefId::AdtId(AdtId::StructId(s)))
2204 if self.db.struct_signature(s).shape != FieldsShape::Record =>
2206 {
2207 (None, Pat::Path(name.into()))
2208 }
2209 _ => {
2211 let id = binding_list.find(self, name, hygiene, annotation);
2212 (Some(id), Pat::Bind { id, subpat })
2213 }
2214 }
2215 } else {
2216 let id = binding_list.find(self, name, hygiene, annotation);
2217 (Some(id), Pat::Bind { id, subpat })
2218 };
2219
2220 let ptr = AstPtr::new(&pat);
2221 let pat = self.alloc_pat(pattern, ptr);
2222 if let Some(binding_id) = binding {
2223 self.add_definition_to_binding(binding_id, pat);
2224 }
2225 return pat;
2226 }
2227 ast::Pat::TupleStructPat(p) => {
2228 let path = p
2229 .path()
2230 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
2231 .map(Box::new);
2232 let (args, ellipsis) = self.collect_tuple_pat(
2233 p.fields(),
2234 comma_follows_token(p.l_paren_token()),
2235 binding_list,
2236 );
2237 Pat::TupleStruct { path, args, ellipsis }
2238 }
2239 ast::Pat::RefPat(p) => {
2240 let pat = self.collect_pat_opt(p.pat(), binding_list);
2241 let mutability = Mutability::from_mutable(p.mut_token().is_some());
2242 Pat::Ref { pat, mutability }
2243 }
2244 ast::Pat::PathPat(p) => {
2245 let path = p
2246 .path()
2247 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator));
2248 path.map(Pat::Path).unwrap_or(Pat::Missing)
2249 }
2250 ast::Pat::OrPat(p) => 'b: {
2251 let prev_is_used = mem::take(&mut binding_list.is_used);
2252 let prev_reject_new = mem::take(&mut binding_list.reject_new);
2253 let mut pats = Vec::with_capacity(p.pats().count());
2254 let mut it = p.pats();
2255 let Some(first) = it.next() else {
2256 break 'b Pat::Or(Box::new([]));
2257 };
2258 pats.push(self.collect_pat(first, binding_list));
2259 binding_list.reject_new = true;
2260 for rest in it {
2261 for (_, it) in binding_list.is_used.iter_mut() {
2262 *it = false;
2263 }
2264 pats.push(self.collect_pat(rest, binding_list));
2265 for (&id, &is_used) in binding_list.is_used.iter() {
2266 if !is_used {
2267 self.store.bindings[id].problems =
2268 Some(BindingProblems::NotBoundAcrossAll);
2269 }
2270 }
2271 }
2272 binding_list.reject_new = prev_reject_new;
2273 let current_is_used = mem::replace(&mut binding_list.is_used, prev_is_used);
2274 for (id, _) in current_is_used.into_iter() {
2275 binding_list.check_is_used(self, id);
2276 }
2277 if let &[pat] = &*pats {
2278 return pat;
2280 }
2281 Pat::Or(pats.into())
2282 }
2283 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
2284 ast::Pat::TuplePat(p) => {
2285 let (args, ellipsis) = self.collect_tuple_pat(
2286 p.fields(),
2287 comma_follows_token(p.l_paren_token()),
2288 binding_list,
2289 );
2290 Pat::Tuple { args, ellipsis }
2291 }
2292 ast::Pat::WildcardPat(_) => Pat::Wild,
2293 ast::Pat::RecordPat(p) => {
2294 let path = p
2295 .path()
2296 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
2297 .map(Box::new);
2298 let record_pat_field_list =
2299 &p.record_pat_field_list().expect("every struct should have a field list");
2300 let args = record_pat_field_list
2301 .fields()
2302 .filter_map(|f| {
2303 if !self.check_cfg(&f) {
2304 return None;
2305 }
2306 let ast_pat = f.pat()?;
2307 let pat = self.collect_pat(ast_pat, binding_list);
2308 let name = f.field_name()?.as_name();
2309 let src = self.expander.in_file(AstPtr::new(&f).wrap_right());
2310 self.store.pat_field_map_back.insert(pat, src);
2311 Some(RecordFieldPat { name, pat })
2312 })
2313 .collect();
2314
2315 let ellipsis = record_pat_field_list.rest_pat().is_some();
2316
2317 Pat::Record { path, args, ellipsis }
2318 }
2319 ast::Pat::SlicePat(p) => {
2320 let SlicePatComponents { prefix, slice, suffix } = p.components();
2321
2322 Pat::Slice {
2324 prefix: prefix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
2325 slice: slice.map(|p| self.collect_pat(p, binding_list)),
2326 suffix: suffix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
2327 }
2328 }
2329 ast::Pat::LiteralPat(lit) => 'b: {
2330 let Some((hir_lit, ast_lit)) = pat_literal_to_hir(lit) else {
2331 break 'b Pat::Missing;
2332 };
2333 let expr = Expr::Literal(hir_lit);
2334 let expr_ptr = AstPtr::new(&ast::Expr::Literal(ast_lit));
2335 let expr_id = self.alloc_expr(expr, expr_ptr);
2336 Pat::Lit(expr_id)
2337 }
2338 ast::Pat::RestPat(_) => {
2339 Pat::Missing
2346 }
2347 ast::Pat::BoxPat(boxpat) => {
2348 let inner = self.collect_pat_opt(boxpat.pat(), binding_list);
2349 Pat::Box { inner }
2350 }
2351 ast::Pat::ConstBlockPat(const_block_pat) => {
2352 if let Some(block) = const_block_pat.block_expr() {
2353 let expr_id = self.with_label_rib(RibKind::Constant, |this| {
2354 this.with_binding_owner(|this| this.collect_block(block))
2355 });
2356 Pat::ConstBlock(expr_id)
2357 } else {
2358 Pat::Missing
2359 }
2360 }
2361 ast::Pat::MacroPat(mac) => match mac.macro_call() {
2362 Some(call) => {
2363 let macro_ptr = AstPtr::new(&call);
2364 let src = self.expander.in_file(AstPtr::new(&pat));
2365 let pat =
2366 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
2367 this.collect_pat_opt(expanded_pat, binding_list)
2368 });
2369 self.store.pat_map.insert(src, pat.into());
2370 return pat;
2371 }
2372 None => Pat::Missing,
2373 },
2374 ast::Pat::RangePat(p) => {
2375 let mut range_part_lower = |p: Option<ast::Pat>| -> Option<ExprId> {
2376 p.and_then(|it| {
2377 let ptr = PatPtr::new(&it);
2378 match &it {
2379 ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat(
2380 Expr::Literal(pat_literal_to_hir(it)?.0),
2381 ptr,
2382 )),
2383 ast::Pat::IdentPat(ident) if ident.is_simple_ident() => ident
2384 .name()
2385 .map(|name| name.as_name())
2386 .map(Path::from)
2387 .map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
2388 ast::Pat::PathPat(p) => p
2389 .path()
2390 .and_then(|path| {
2391 self.lower_path(path, &mut Self::impl_trait_error_allocator)
2392 })
2393 .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
2394 _ => None,
2397 }
2398 })
2399 };
2400 let start = range_part_lower(p.start());
2401 let end = range_part_lower(p.end());
2402 match p.op_kind() {
2404 Some(range_type) => Pat::Range { start, end, range_type },
2405 None => Pat::Missing,
2406 }
2407 }
2408 };
2409 let ptr = AstPtr::new(&pat);
2410 self.alloc_pat(pattern, ptr)
2411 }
2412
2413 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
2414 match pat {
2415 Some(pat) => self.collect_pat(pat, binding_list),
2416 None => self.missing_pat(),
2417 }
2418 }
2419
2420 fn collect_tuple_pat(
2421 &mut self,
2422 args: AstChildren<ast::Pat>,
2423 has_leading_comma: bool,
2424 binding_list: &mut BindingList,
2425 ) -> (Box<[PatId]>, Option<u32>) {
2426 let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect();
2427 let ellipsis = args.iter().position(|p| p.is_right()).map(|it| it as u32);
2430
2431 let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect();
2433 if has_leading_comma {
2436 args.insert(0, self.missing_pat());
2437 }
2438
2439 (args.into_boxed_slice(), ellipsis)
2440 }
2441
2442 fn collect_pat_possibly_rest(
2445 &mut self,
2446 pat: ast::Pat,
2447 binding_list: &mut BindingList,
2448 ) -> Either<PatId, ()> {
2449 match &pat {
2450 ast::Pat::RestPat(_) => Either::Right(()),
2451 ast::Pat::MacroPat(mac) => match mac.macro_call() {
2452 Some(call) => {
2453 let macro_ptr = AstPtr::new(&call);
2454 let src = self.expander.in_file(AstPtr::new(&pat));
2455 let pat =
2456 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
2457 if let Some(expanded_pat) = expanded_pat {
2458 this.collect_pat_possibly_rest(expanded_pat, binding_list)
2459 } else {
2460 Either::Left(this.missing_pat())
2461 }
2462 });
2463 if let Some(pat) = pat.left() {
2464 self.store.pat_map.insert(src, pat.into());
2465 }
2466 pat
2467 }
2468 None => {
2469 let ptr = AstPtr::new(&pat);
2470 Either::Left(self.alloc_pat(Pat::Missing, ptr))
2471 }
2472 },
2473 _ => Either::Left(self.collect_pat(pat, binding_list)),
2474 }
2475 }
2476
2477 fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> bool {
2482 let enabled = self.expander.is_cfg_enabled(owner, self.cfg_options);
2483 match enabled {
2484 Ok(()) => true,
2485 Err(cfg) => {
2486 self.store.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode {
2487 node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())),
2488 cfg,
2489 opts: self.cfg_options.clone(),
2490 });
2491 false
2492 }
2493 }
2494 }
2495
2496 fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
2497 self.store.binding_definitions.entry(binding_id).or_default().push(pat_id);
2498 }
2499
2500 fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
2503 let label = Label {
2504 name: ast_label
2505 .lifetime()
2506 .as_ref()
2507 .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())),
2508 };
2509 self.alloc_label(label, AstPtr::new(&ast_label))
2510 }
2511
2512 fn resolve_label(
2513 &self,
2514 lifetime: Option<ast::Lifetime>,
2515 ) -> Result<Option<LabelId>, ExpressionStoreDiagnostics> {
2516 let Some(lifetime) = lifetime else { return Ok(None) };
2517 let mut hygiene_id =
2518 self.expander.hygiene_for_range(self.db, lifetime.syntax().text_range());
2519 let mut hygiene_info = if hygiene_id.is_root() {
2520 None
2521 } else {
2522 hygiene_id.lookup().outer_expn(self.db).map(|expansion| {
2523 let expansion = self.db.lookup_intern_macro_call(expansion.into());
2524 (hygiene_id.lookup().parent(self.db), expansion.def)
2525 })
2526 };
2527 let name = Name::new_lifetime(&lifetime.text());
2528
2529 for (rib_idx, rib) in self.label_ribs.iter().enumerate().rev() {
2530 match &rib.kind {
2531 RibKind::Normal(label_name, id, label_hygiene) => {
2532 if *label_name == name && *label_hygiene == hygiene_id {
2533 return if self.is_label_valid_from_rib(rib_idx) {
2534 Ok(Some(*id))
2535 } else {
2536 Err(ExpressionStoreDiagnostics::UnreachableLabel {
2537 name,
2538 node: self.expander.in_file(AstPtr::new(&lifetime)),
2539 })
2540 };
2541 }
2542 }
2543 RibKind::MacroDef(macro_id) => {
2544 if let Some((parent_ctx, label_macro_id)) = hygiene_info
2545 && label_macro_id == **macro_id
2546 {
2547 hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent(self.db));
2552 hygiene_info = parent_ctx.outer_expn(self.db).map(|expansion| {
2553 let expansion = self.db.lookup_intern_macro_call(expansion.into());
2554 (parent_ctx.parent(self.db), expansion.def)
2555 });
2556 }
2557 }
2558 _ => {}
2559 }
2560 }
2561
2562 Err(ExpressionStoreDiagnostics::UndeclaredLabel {
2563 name,
2564 node: self.expander.in_file(AstPtr::new(&lifetime)),
2565 })
2566 }
2567
2568 fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
2569 !self.label_ribs[rib_index + 1..].iter().any(|rib| rib.kind.is_label_barrier())
2570 }
2571
2572 fn pop_label_rib(&mut self) {
2573 while let Some(LabelRib { kind: RibKind::MacroDef(_) }) = self.label_ribs.pop() {
2575 }
2577 }
2578
2579 fn with_label_rib<T>(&mut self, kind: RibKind, f: impl FnOnce(&mut Self) -> T) -> T {
2580 self.label_ribs.push(LabelRib::new(kind));
2581 let res = f(self);
2582 self.pop_label_rib();
2583 res
2584 }
2585
2586 fn with_labeled_rib<T>(
2587 &mut self,
2588 label: LabelId,
2589 hygiene: HygieneId,
2590 f: impl FnOnce(&mut Self) -> T,
2591 ) -> T {
2592 self.label_ribs.push(LabelRib::new(RibKind::Normal(
2593 self.store.labels[label].name.clone(),
2594 label,
2595 hygiene,
2596 )));
2597 let res = f(self);
2598 self.pop_label_rib();
2599 res
2600 }
2601
2602 fn with_opt_labeled_rib<T>(
2603 &mut self,
2604 label: Option<(HygieneId, LabelId)>,
2605 f: impl FnOnce(&mut Self) -> T,
2606 ) -> T {
2607 match label {
2608 None => f(self),
2609 Some((hygiene, label)) => self.with_labeled_rib(label, hygiene, f),
2610 }
2611 }
2612 fn expand_macros_to_string(&mut self, expr: ast::Expr) -> Option<(ast::String, bool)> {
2615 let m = match expr {
2616 ast::Expr::MacroExpr(m) => m,
2617 ast::Expr::Literal(l) => {
2618 return match l.kind() {
2619 ast::LiteralKind::String(s) => Some((s, true)),
2620 _ => None,
2621 };
2622 }
2623 _ => return None,
2624 };
2625 let e = m.macro_call()?;
2626 let macro_ptr = AstPtr::new(&e);
2627 let (exp, _) = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
2628 expansion.and_then(|it| this.expand_macros_to_string(it))
2629 })?;
2630 Some((exp, false))
2631 }
2632
2633 fn lang_path(&self, lang: Option<impl Into<LangItemTarget>>) -> Option<Path> {
2634 Some(Path::LangItem(lang?.into(), None))
2635 }
2636
2637 fn ty_rel_lang_path(
2638 &self,
2639 lang: Option<impl Into<LangItemTarget>>,
2640 relative_name: Symbol,
2641 ) -> Option<Path> {
2642 Some(Path::LangItem(lang?.into(), Some(Name::new_symbol_root(relative_name))))
2643 }
2644
2645 fn ty_rel_lang_path_expr(
2646 &self,
2647 lang: Option<impl Into<LangItemTarget>>,
2648 relative_name: Symbol,
2649 ) -> Expr {
2650 self.ty_rel_lang_path(lang, relative_name).map_or(Expr::Missing, Expr::Path)
2651 }
2652}
2653
2654fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)> {
2655 let ast_lit = lit.literal()?;
2656 let mut hir_lit: Literal = ast_lit.kind().into();
2657 if lit.minus_token().is_some() {
2658 hir_lit = hir_lit.negate()?;
2659 }
2660 Some((hir_lit, ast_lit))
2661}
2662
2663impl ExprCollector<'_> {
2664 fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
2665 let src = self.expander.in_file(ptr);
2666 let id = self.store.exprs.alloc(expr);
2667 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
2668 self.store.expr_map.insert(src, id.into());
2669 id
2670 }
2671 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
2674 self.store.exprs.alloc(expr)
2675 }
2676 fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
2677 let src = self.expander.in_file(ptr);
2678 let id = self.store.exprs.alloc(expr);
2679 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
2680 id
2683 }
2684 fn missing_expr(&mut self) -> ExprId {
2685 self.alloc_expr_desugared(Expr::Missing)
2686 }
2687
2688 fn alloc_binding(
2689 &mut self,
2690 name: Name,
2691 mode: BindingAnnotation,
2692 hygiene: HygieneId,
2693 ) -> BindingId {
2694 let binding = self.store.bindings.alloc(Binding { name, mode, problems: None, hygiene });
2695 self.unowned_bindings.push(binding);
2696 binding
2697 }
2698
2699 fn alloc_pat_from_expr(&mut self, pat: Pat, ptr: ExprPtr) -> PatId {
2700 let src = self.expander.in_file(ptr);
2701 let id = self.store.pats.alloc(pat);
2702 self.store.expr_map.insert(src, id.into());
2703 self.store.pat_map_back.insert(id, src.map(AstPtr::wrap_left));
2704 id
2705 }
2706
2707 fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId {
2708 let src = self.expander.in_file(ptr);
2709 let id = self.store.exprs.alloc(expr);
2710 self.store.pat_map.insert(src, id.into());
2711 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_right));
2712 id
2713 }
2714
2715 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
2716 let src = self.expander.in_file(ptr);
2717 let id = self.store.pats.alloc(pat);
2718 self.store.pat_map_back.insert(id, src.map(AstPtr::wrap_right));
2719 self.store.pat_map.insert(src, id.into());
2720 id
2721 }
2722 fn alloc_pat_desugared(&mut self, pat: Pat) -> PatId {
2724 self.store.pats.alloc(pat)
2725 }
2726 fn missing_pat(&mut self) -> PatId {
2727 self.store.pats.alloc(Pat::Missing)
2728 }
2729
2730 fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
2731 let src = self.expander.in_file(ptr);
2732 let id = self.store.labels.alloc(label);
2733 self.store.label_map_back.insert(id, src);
2734 self.store.label_map.insert(src, id);
2735 id
2736 }
2737 fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
2739 self.store.labels.alloc(label)
2740 }
2741
2742 fn is_lowering_awaitable_block(&self) -> &Awaitable {
2743 self.awaitable_context.as_ref().unwrap_or(&Awaitable::No("unknown"))
2744 }
2745
2746 fn with_awaitable_block<T>(
2747 &mut self,
2748 awaitable: Awaitable,
2749 f: impl FnOnce(&mut Self) -> T,
2750 ) -> T {
2751 let orig = self.awaitable_context.replace(awaitable);
2752 let res = f(self);
2753 self.awaitable_context = orig;
2754 res
2755 }
2756
2757 fn hygiene_id_for(&self, range: TextRange) -> HygieneId {
2758 self.expander.hygiene_for_range(self.db, range)
2759 }
2760}
2761
2762fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
2763 (|| syntax::algo::skip_trivia_token(t?.next_token()?, syntax::Direction::Next))()
2764 .is_some_and(|it| it.kind() == syntax::T![,])
2765}
2766
2767pub fn hir_assoc_type_binding_to_ast(
2769 segment_args: &ast::GenericArgList,
2770 binding_idx: u32,
2771) -> Option<ast::AssocTypeArg> {
2772 segment_args
2773 .generic_args()
2774 .filter_map(|arg| match arg {
2775 ast::GenericArg::AssocTypeArg(it) => Some(it),
2776 _ => None,
2777 })
2778 .filter(|binding| binding.param_list().is_none() && binding.name_ref().is_some())
2779 .nth(binding_idx as usize)
2780}
2781
2782pub fn hir_generic_arg_to_ast(
2784 args: &ast::GenericArgList,
2785 arg_idx: u32,
2786 has_self_arg: bool,
2787) -> Option<ast::GenericArg> {
2788 args.generic_args()
2789 .filter(|arg| match arg {
2790 ast::GenericArg::AssocTypeArg(_) => false,
2791 ast::GenericArg::LifetimeArg(arg) => arg.lifetime().is_some(),
2792 ast::GenericArg::ConstArg(_) | ast::GenericArg::TypeArg(_) => true,
2793 })
2794 .nth(arg_idx as usize - has_self_arg as usize)
2795}