1mod asm;
5mod generics;
6mod path;
7
8use std::mem;
9
10use base_db::FxIndexSet;
11use cfg::CfgOptions;
12use either::Either;
13use hir_expand::{
14 HirFileId, InFile, MacroDefId,
15 mod_path::tool_path,
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, AstToken as _, 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 builtin_type::BuiltinUint,
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,
51 format_args::{
52 self, FormatAlignment, FormatArgs, FormatArgsPiece, FormatArgument, FormatArgumentKind,
53 FormatArgumentsCollector, FormatCount, FormatDebugHex, FormatOptions,
54 FormatPlaceholder, FormatSign, FormatTrait,
55 },
56 generics::GenericParams,
57 },
58 item_scope::BuiltinShadowMode,
59 item_tree::FieldsShape,
60 lang_item::LangItem,
61 nameres::{DefMap, LocalDefMap, MacroSubNs, block_def_map},
62 type_ref::{
63 ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, Mutability, PathId, Rawness,
64 RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, UseArgRef,
65 },
66};
67
68pub use self::path::hir_segment_to_ast_segment;
69
70pub(super) fn lower_body(
71 db: &dyn DefDatabase,
72 owner: DefWithBodyId,
73 current_file_id: HirFileId,
74 module: ModuleId,
75 parameters: Option<ast::ParamList>,
76 body: Option<ast::Expr>,
77 is_async_fn: bool,
78) -> (Body, BodySourceMap) {
79 let mut self_param = None;
86 let mut source_map_self_param = None;
87 let mut params = vec![];
88 let mut collector = ExprCollector::new(db, module, current_file_id);
89
90 let skip_body = match owner {
91 DefWithBodyId::FunctionId(it) => db.attrs(it.into()),
92 DefWithBodyId::StaticId(it) => db.attrs(it.into()),
93 DefWithBodyId::ConstId(it) => db.attrs(it.into()),
94 DefWithBodyId::VariantId(it) => db.attrs(it.into()),
95 }
96 .rust_analyzer_tool()
97 .any(|attr| *attr.path() == tool_path![skip]);
98 if skip_body {
101 if let Some(param_list) = parameters {
102 if let Some(self_param_syn) =
103 param_list.self_param().filter(|self_param| collector.check_cfg(self_param))
104 {
105 let is_mutable =
106 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
107 let hygiene = self_param_syn
108 .name()
109 .map(|name| collector.hygiene_id_for(name.syntax().text_range()))
110 .unwrap_or(HygieneId::ROOT);
111 let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
112 Name::new_symbol_root(sym::self_),
113 BindingAnnotation::new(is_mutable, false),
114 hygiene,
115 );
116 self_param = Some(binding_id);
117 source_map_self_param =
118 Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
119 }
120 let count = param_list.params().filter(|it| collector.check_cfg(it)).count();
121 params = (0..count).map(|_| collector.missing_pat()).collect();
122 };
123 let body_expr = collector.missing_expr();
124 let (store, source_map) = collector.store.finish();
125 return (
126 Body { store, params: params.into_boxed_slice(), self_param, body_expr },
127 BodySourceMap { self_param: source_map_self_param, store: source_map },
128 );
129 }
130
131 if let Some(param_list) = parameters {
132 if let Some(self_param_syn) = param_list.self_param().filter(|it| collector.check_cfg(it)) {
133 let is_mutable =
134 self_param_syn.mut_token().is_some() && self_param_syn.amp_token().is_none();
135 let hygiene = self_param_syn
136 .name()
137 .map(|name| collector.hygiene_id_for(name.syntax().text_range()))
138 .unwrap_or(HygieneId::ROOT);
139 let binding_id: la_arena::Idx<Binding> = collector.alloc_binding(
140 Name::new_symbol_root(sym::self_),
141 BindingAnnotation::new(is_mutable, false),
142 hygiene,
143 );
144 self_param = Some(binding_id);
145 source_map_self_param = Some(collector.expander.in_file(AstPtr::new(&self_param_syn)));
146 }
147
148 for param in param_list.params() {
149 if collector.check_cfg(¶m) {
150 let param_pat = collector.collect_pat_top(param.pat());
151 params.push(param_pat);
152 }
153 }
154 };
155
156 let body_expr = collector.collect(
157 body,
158 if is_async_fn {
159 Awaitable::Yes
160 } else {
161 match owner {
162 DefWithBodyId::FunctionId(..) => Awaitable::No("non-async function"),
163 DefWithBodyId::StaticId(..) => Awaitable::No("static"),
164 DefWithBodyId::ConstId(..) => Awaitable::No("constant"),
165 DefWithBodyId::VariantId(..) => Awaitable::No("enum variant"),
166 }
167 },
168 );
169
170 let (store, source_map) = collector.store.finish();
171 (
172 Body { store, params: params.into_boxed_slice(), self_param, body_expr },
173 BodySourceMap { self_param: source_map_self_param, store: source_map },
174 )
175}
176
177pub(crate) fn lower_type_ref(
178 db: &dyn DefDatabase,
179 module: ModuleId,
180 type_ref: InFile<Option<ast::Type>>,
181) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId) {
182 let mut expr_collector = ExprCollector::new(db, module, type_ref.file_id);
183 let type_ref =
184 expr_collector.lower_type_ref_opt(type_ref.value, &mut ExprCollector::impl_trait_allocator);
185 let (store, source_map) = expr_collector.store.finish();
186 (store, source_map, type_ref)
187}
188
189pub(crate) fn lower_generic_params(
190 db: &dyn DefDatabase,
191 module: ModuleId,
192 def: GenericDefId,
193 file_id: HirFileId,
194 param_list: Option<ast::GenericParamList>,
195 where_clause: Option<ast::WhereClause>,
196) -> (Arc<ExpressionStore>, Arc<GenericParams>, ExpressionStoreSourceMap) {
197 let mut expr_collector = ExprCollector::new(db, module, file_id);
198 let mut collector = generics::GenericParamsCollector::new(def);
199 collector.lower(&mut expr_collector, param_list, where_clause);
200 let params = collector.finish();
201 let (store, source_map) = expr_collector.store.finish();
202 (Arc::new(store), params, source_map)
203}
204
205pub(crate) fn lower_impl(
206 db: &dyn DefDatabase,
207 module: ModuleId,
208 impl_syntax: InFile<ast::Impl>,
209 impl_id: ImplId,
210) -> (ExpressionStore, ExpressionStoreSourceMap, TypeRefId, Option<TraitRef>, Arc<GenericParams>) {
211 let mut expr_collector = ExprCollector::new(db, module, impl_syntax.file_id);
212 let self_ty =
213 expr_collector.lower_type_ref_opt_disallow_impl_trait(impl_syntax.value.self_ty());
214 let trait_ = impl_syntax.value.trait_().and_then(|it| match &it {
215 ast::Type::PathType(path_type) => {
216 let path = expr_collector
217 .lower_path_type(path_type, &mut ExprCollector::impl_trait_allocator)?;
218 Some(TraitRef { path: expr_collector.alloc_path(path, AstPtr::new(&it)) })
219 }
220 _ => None,
221 });
222 let mut collector = generics::GenericParamsCollector::new(impl_id.into());
223 collector.lower(
224 &mut expr_collector,
225 impl_syntax.value.generic_param_list(),
226 impl_syntax.value.where_clause(),
227 );
228 let params = collector.finish();
229 let (store, source_map) = expr_collector.store.finish();
230 (store, source_map, self_ty, trait_, params)
231}
232
233pub(crate) fn lower_trait(
234 db: &dyn DefDatabase,
235 module: ModuleId,
236 trait_syntax: InFile<ast::Trait>,
237 trait_id: TraitId,
238) -> (ExpressionStore, ExpressionStoreSourceMap, Arc<GenericParams>) {
239 let mut expr_collector = ExprCollector::new(db, module, trait_syntax.file_id);
240 let mut collector = generics::GenericParamsCollector::with_self_param(
241 &mut expr_collector,
242 trait_id.into(),
243 trait_syntax.value.type_bound_list(),
244 );
245 collector.lower(
246 &mut expr_collector,
247 trait_syntax.value.generic_param_list(),
248 trait_syntax.value.where_clause(),
249 );
250 let params = collector.finish();
251 let (store, source_map) = expr_collector.store.finish();
252 (store, source_map, params)
253}
254
255pub(crate) fn lower_type_alias(
256 db: &dyn DefDatabase,
257 module: ModuleId,
258 alias: InFile<ast::TypeAlias>,
259 type_alias_id: TypeAliasId,
260) -> (
261 ExpressionStore,
262 ExpressionStoreSourceMap,
263 Arc<GenericParams>,
264 Box<[TypeBound]>,
265 Option<TypeRefId>,
266) {
267 let mut expr_collector = ExprCollector::new(db, module, alias.file_id);
268 let bounds = alias
269 .value
270 .type_bound_list()
271 .map(|bounds| {
272 bounds
273 .bounds()
274 .map(|bound| {
275 expr_collector.lower_type_bound(bound, &mut ExprCollector::impl_trait_allocator)
276 })
277 .collect()
278 })
279 .unwrap_or_default();
280 let mut collector = generics::GenericParamsCollector::new(type_alias_id.into());
281 collector.lower(
282 &mut expr_collector,
283 alias.value.generic_param_list(),
284 alias.value.where_clause(),
285 );
286 let params = collector.finish();
287 let type_ref = alias
288 .value
289 .ty()
290 .map(|ty| expr_collector.lower_type_ref(ty, &mut ExprCollector::impl_trait_allocator));
291 let (store, source_map) = expr_collector.store.finish();
292 (store, source_map, params, bounds, type_ref)
293}
294
295pub(crate) fn lower_function(
296 db: &dyn DefDatabase,
297 module: ModuleId,
298 fn_: InFile<ast::Fn>,
299 function_id: FunctionId,
300) -> (
301 ExpressionStore,
302 ExpressionStoreSourceMap,
303 Arc<GenericParams>,
304 Box<[TypeRefId]>,
305 Option<TypeRefId>,
306 bool,
307 bool,
308) {
309 let mut expr_collector = ExprCollector::new(db, module, fn_.file_id);
310 let mut collector = generics::GenericParamsCollector::new(function_id.into());
311 collector.lower(&mut expr_collector, fn_.value.generic_param_list(), fn_.value.where_clause());
312 let mut params = vec![];
313 let mut has_self_param = false;
314 let mut has_variadic = false;
315 collector.collect_impl_trait(&mut expr_collector, |collector, mut impl_trait_lower_fn| {
316 if let Some(param_list) = fn_.value.param_list() {
317 if let Some(param) = param_list.self_param() {
318 let enabled = collector.check_cfg(¶m);
319 if enabled {
320 has_self_param = true;
321 params.push(match param.ty() {
322 Some(ty) => collector.lower_type_ref(ty, &mut impl_trait_lower_fn),
323 None => {
324 let self_type = collector.alloc_type_ref_desugared(TypeRef::Path(
325 Name::new_symbol_root(sym::Self_).into(),
326 ));
327 let lifetime = param
328 .lifetime()
329 .map(|lifetime| collector.lower_lifetime_ref(lifetime));
330 match param.kind() {
331 ast::SelfParamKind::Owned => self_type,
332 ast::SelfParamKind::Ref => collector.alloc_type_ref_desugared(
333 TypeRef::Reference(Box::new(RefType {
334 ty: self_type,
335 lifetime,
336 mutability: Mutability::Shared,
337 })),
338 ),
339 ast::SelfParamKind::MutRef => collector.alloc_type_ref_desugared(
340 TypeRef::Reference(Box::new(RefType {
341 ty: self_type,
342 lifetime,
343 mutability: Mutability::Mut,
344 })),
345 ),
346 }
347 }
348 });
349 }
350 }
351 let p = param_list
352 .params()
353 .filter(|param| collector.check_cfg(param))
354 .filter(|param| {
355 let is_variadic = param.dotdotdot_token().is_some();
356 has_variadic |= is_variadic;
357 !is_variadic
358 })
359 .map(|param| param.ty())
360 .collect::<Vec<_>>();
362 for p in p {
363 params.push(collector.lower_type_ref_opt(p, &mut impl_trait_lower_fn));
364 }
365 }
366 });
367 let generics = collector.finish();
368 let return_type = fn_.value.ret_type().map(|ret_type| {
369 expr_collector.lower_type_ref_opt(ret_type.ty(), &mut ExprCollector::impl_trait_allocator)
370 });
371
372 let return_type = if fn_.value.async_token().is_some() {
373 let path = hir_expand::mod_path::path![core::future::Future];
374 let mut generic_args: Vec<_> =
375 std::iter::repeat_n(None, path.segments().len() - 1).collect();
376 let binding = AssociatedTypeBinding {
377 name: Name::new_symbol_root(sym::Output),
378 args: None,
379 type_ref: Some(
380 return_type
381 .unwrap_or_else(|| expr_collector.alloc_type_ref_desugared(TypeRef::unit())),
382 ),
383 bounds: Box::default(),
384 };
385 generic_args
386 .push(Some(GenericArgs { bindings: Box::new([binding]), ..GenericArgs::empty() }));
387
388 let path = Path::from_known_path(path, generic_args);
389 let path = PathId::from_type_ref_unchecked(
390 expr_collector.alloc_type_ref_desugared(TypeRef::Path(path)),
391 );
392 let ty_bound = TypeBound::Path(path, TraitBoundModifier::None);
393 Some(
394 expr_collector
395 .alloc_type_ref_desugared(TypeRef::ImplTrait(ThinVec::from_iter([ty_bound]))),
396 )
397 } else {
398 return_type
399 };
400 let (store, source_map) = expr_collector.store.finish();
401 (
402 store,
403 source_map,
404 generics,
405 params.into_boxed_slice(),
406 return_type,
407 has_self_param,
408 has_variadic,
409 )
410}
411
412pub struct ExprCollector<'db> {
413 db: &'db dyn DefDatabase,
414 cfg_options: &'db CfgOptions,
415 expander: Expander,
416 def_map: &'db DefMap,
417 local_def_map: &'db LocalDefMap,
418 module: ModuleId,
419 pub store: ExpressionStoreBuilder,
420
421 outer_impl_trait: bool,
424
425 is_lowering_coroutine: bool,
426
427 current_block_legacy_macro_defs_count: FxHashMap<Name, usize>,
430
431 current_try_block_label: Option<LabelId>,
432
433 label_ribs: Vec<LabelRib>,
434 current_binding_owner: Option<ExprId>,
435
436 awaitable_context: Option<Awaitable>,
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 ExprCollector<'_> {
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 ExprCollector {
525 db,
526 cfg_options: module.krate().cfg_options(db),
527 module,
528 def_map,
529 local_def_map,
530 store: ExpressionStoreBuilder::default(),
531 expander,
532 current_try_block_label: None,
533 is_lowering_coroutine: false,
534 label_ribs: Vec::new(),
535 current_binding_owner: None,
536 awaitable_context: None,
537 current_block_legacy_macro_defs_count: FxHashMap::default(),
538 outer_impl_trait: false,
539 }
540 }
541
542 #[inline]
543 pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
544 self.expander.span_map()
545 }
546
547 pub fn lower_lifetime_ref(&mut self, lifetime: ast::Lifetime) -> LifetimeRefId {
548 let lifetime_ref = match &*lifetime.text() {
550 "" | "'" => LifetimeRef::Error,
551 "'static" => LifetimeRef::Static,
552 "'_" => LifetimeRef::Placeholder,
553 text => LifetimeRef::Named(Name::new_lifetime(text)),
554 };
555 self.alloc_lifetime_ref(lifetime_ref, AstPtr::new(&lifetime))
556 }
557
558 pub fn lower_lifetime_ref_opt(&mut self, lifetime: Option<ast::Lifetime>) -> LifetimeRefId {
559 match lifetime {
560 Some(lifetime) => self.lower_lifetime_ref(lifetime),
561 None => self.alloc_lifetime_ref_desugared(LifetimeRef::Placeholder),
562 }
563 }
564
565 pub fn lower_type_ref(
567 &mut self,
568 node: ast::Type,
569 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
570 ) -> TypeRefId {
571 let ty = match &node {
572 ast::Type::ParenType(inner) => {
573 return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
574 }
575 ast::Type::TupleType(inner) => TypeRef::Tuple(ThinVec::from_iter(Vec::from_iter(
576 inner.fields().map(|it| self.lower_type_ref(it, impl_trait_lower_fn)),
577 ))),
578 ast::Type::NeverType(..) => TypeRef::Never,
579 ast::Type::PathType(inner) => inner
580 .path()
581 .and_then(|it| self.lower_path(it, impl_trait_lower_fn))
582 .map(TypeRef::Path)
583 .unwrap_or(TypeRef::Error),
584 ast::Type::PtrType(inner) => {
585 let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
586 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
587 TypeRef::RawPtr(inner_ty, mutability)
588 }
589 ast::Type::ArrayType(inner) => {
590 let len = self.lower_const_arg_opt(inner.const_arg());
591 TypeRef::Array(ArrayType {
592 ty: self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn),
593 len,
594 })
595 }
596 ast::Type::SliceType(inner) => {
597 TypeRef::Slice(self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn))
598 }
599 ast::Type::RefType(inner) => {
600 let inner_ty = self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
601 let lifetime = inner.lifetime().map(|lt| self.lower_lifetime_ref(lt));
602 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
603 TypeRef::Reference(Box::new(RefType { ty: inner_ty, lifetime, mutability }))
604 }
605 ast::Type::InferType(_inner) => TypeRef::Placeholder,
606 ast::Type::FnPtrType(inner) => {
607 let ret_ty = inner
608 .ret_type()
609 .and_then(|rt| rt.ty())
610 .map(|it| self.lower_type_ref(it, impl_trait_lower_fn))
611 .unwrap_or_else(|| self.alloc_type_ref_desugared(TypeRef::unit()));
612 let mut is_varargs = false;
613 let mut params = if let Some(pl) = inner.param_list() {
614 if let Some(param) = pl.params().last() {
615 is_varargs = param.dotdotdot_token().is_some();
616 }
617
618 pl.params()
619 .map(|it| {
620 let type_ref = self.lower_type_ref_opt(it.ty(), impl_trait_lower_fn);
621 let name = match it.pat() {
622 Some(ast::Pat::IdentPat(it)) => Some(
623 it.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing),
624 ),
625 _ => None,
626 };
627 (name, type_ref)
628 })
629 .collect()
630 } else {
631 Vec::with_capacity(1)
632 };
633 fn lower_abi(abi: ast::Abi) -> Symbol {
634 match abi.abi_string() {
635 Some(tok) => Symbol::intern(tok.text_without_quotes()),
636 _ => sym::C,
638 }
639 }
640
641 let abi = inner.abi().map(lower_abi);
642 params.push((None, ret_ty));
643 TypeRef::Fn(Box::new(FnType {
644 is_varargs,
645 is_unsafe: inner.unsafe_token().is_some(),
646 abi,
647 params: params.into_boxed_slice(),
648 }))
649 }
650 ast::Type::ForType(inner) => {
652 return self.lower_type_ref_opt(inner.ty(), impl_trait_lower_fn);
653 }
654 ast::Type::ImplTraitType(inner) => {
655 if self.outer_impl_trait {
656 TypeRef::Error
658 } else {
659 return self.with_outer_impl_trait_scope(true, |this| {
660 let type_bounds =
661 this.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn);
662 impl_trait_lower_fn(this, AstPtr::new(&node), type_bounds)
663 });
664 }
665 }
666 ast::Type::DynTraitType(inner) => TypeRef::DynTrait(
667 self.type_bounds_from_ast(inner.type_bound_list(), impl_trait_lower_fn),
668 ),
669 ast::Type::MacroType(mt) => match mt.macro_call() {
670 Some(mcall) => {
671 let macro_ptr = AstPtr::new(&mcall);
672 let src = self.expander.in_file(AstPtr::new(&node));
673 let id = self.collect_macro_call(mcall, macro_ptr, true, |this, expansion| {
674 this.lower_type_ref_opt(expansion, impl_trait_lower_fn)
675 });
676 self.store.types_map.insert(src, id);
677 return id;
678 }
679 None => TypeRef::Error,
680 },
681 };
682 self.alloc_type_ref(ty, AstPtr::new(&node))
683 }
684
685 pub(crate) fn lower_type_ref_disallow_impl_trait(&mut self, node: ast::Type) -> TypeRefId {
686 self.lower_type_ref(node, &mut Self::impl_trait_error_allocator)
687 }
688
689 pub(crate) fn lower_type_ref_opt(
690 &mut self,
691 node: Option<ast::Type>,
692 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
693 ) -> TypeRefId {
694 match node {
695 Some(node) => self.lower_type_ref(node, impl_trait_lower_fn),
696 None => self.alloc_error_type(),
697 }
698 }
699
700 pub(crate) fn lower_type_ref_opt_disallow_impl_trait(
701 &mut self,
702 node: Option<ast::Type>,
703 ) -> TypeRefId {
704 self.lower_type_ref_opt(node, &mut Self::impl_trait_error_allocator)
705 }
706
707 fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
708 let id = self.store.types.alloc(type_ref);
709 let ptr = self.expander.in_file(node);
710 self.store.types_map_back.insert(id, ptr);
711 self.store.types_map.insert(ptr, id);
712 id
713 }
714
715 fn alloc_lifetime_ref(
716 &mut self,
717 lifetime_ref: LifetimeRef,
718 node: LifetimePtr,
719 ) -> LifetimeRefId {
720 let id = self.store.lifetimes.alloc(lifetime_ref);
721 let ptr = self.expander.in_file(node);
722 self.store.lifetime_map_back.insert(id, ptr);
723 self.store.lifetime_map.insert(ptr, id);
724 id
725 }
726
727 fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId {
728 self.store.types.alloc(type_ref)
729 }
730
731 fn alloc_lifetime_ref_desugared(&mut self, lifetime_ref: LifetimeRef) -> LifetimeRefId {
732 self.store.lifetimes.alloc(lifetime_ref)
733 }
734
735 fn alloc_error_type(&mut self) -> TypeRefId {
736 self.store.types.alloc(TypeRef::Error)
737 }
738
739 pub fn lower_path(
740 &mut self,
741 ast: ast::Path,
742 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
743 ) -> Option<Path> {
744 super::lower::path::lower_path(self, ast, impl_trait_lower_fn)
745 }
746
747 fn with_outer_impl_trait_scope<R>(
748 &mut self,
749 impl_trait: bool,
750 f: impl FnOnce(&mut Self) -> R,
751 ) -> R {
752 let old = mem::replace(&mut self.outer_impl_trait, impl_trait);
753 let result = f(self);
754 self.outer_impl_trait = old;
755 result
756 }
757
758 pub fn impl_trait_error_allocator(
759 ec: &mut ExprCollector<'_>,
760 ptr: TypePtr,
761 _: ThinVec<TypeBound>,
762 ) -> TypeRefId {
763 ec.alloc_type_ref(TypeRef::Error, ptr)
764 }
765
766 fn impl_trait_allocator(
767 ec: &mut ExprCollector<'_>,
768 ptr: TypePtr,
769 bounds: ThinVec<TypeBound>,
770 ) -> TypeRefId {
771 ec.alloc_type_ref(TypeRef::ImplTrait(bounds), ptr)
772 }
773
774 fn alloc_path(&mut self, path: Path, node: TypePtr) -> PathId {
775 PathId::from_type_ref_unchecked(self.alloc_type_ref(TypeRef::Path(path), node))
776 }
777
778 pub fn lower_generic_args_from_fn_path(
781 &mut self,
782 args: Option<ast::ParenthesizedArgList>,
783 ret_type: Option<ast::RetType>,
784 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
785 ) -> Option<GenericArgs> {
786 let params = args?;
787 let mut param_types = Vec::new();
788 for param in params.type_args() {
789 let type_ref = self.lower_type_ref_opt(param.ty(), impl_trait_lower_fn);
790 param_types.push(type_ref);
791 }
792 let args = Box::new([GenericArg::Type(
793 self.alloc_type_ref_desugared(TypeRef::Tuple(ThinVec::from_iter(param_types))),
794 )]);
795 let bindings = if let Some(ret_type) = ret_type {
796 let type_ref = self.lower_type_ref_opt(ret_type.ty(), impl_trait_lower_fn);
797 Box::new([AssociatedTypeBinding {
798 name: Name::new_symbol_root(sym::Output),
799 args: None,
800 type_ref: Some(type_ref),
801 bounds: Box::default(),
802 }])
803 } else {
804 let type_ref = self.alloc_type_ref_desugared(TypeRef::unit());
806 Box::new([AssociatedTypeBinding {
807 name: Name::new_symbol_root(sym::Output),
808 args: None,
809 type_ref: Some(type_ref),
810 bounds: Box::default(),
811 }])
812 };
813 Some(GenericArgs {
814 args,
815 has_self_type: false,
816 bindings,
817 parenthesized: GenericArgsParentheses::ParenSugar,
818 })
819 }
820
821 pub(super) fn lower_generic_args(
822 &mut self,
823 node: ast::GenericArgList,
824 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
825 ) -> Option<GenericArgs> {
826 let mut args = Vec::new();
828 let mut bindings = Vec::new();
829 for generic_arg in node.generic_args() {
830 match generic_arg {
831 ast::GenericArg::TypeArg(type_arg) => {
832 let type_ref = self.lower_type_ref_opt(type_arg.ty(), impl_trait_lower_fn);
833 args.push(GenericArg::Type(type_ref));
834 }
835 ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
836 if assoc_type_arg.param_list().is_some() {
838 continue;
840 }
841 if let Some(name_ref) = assoc_type_arg.name_ref() {
842 self.with_outer_impl_trait_scope(false, |this| {
844 let name = name_ref.as_name();
845 let args = assoc_type_arg
846 .generic_arg_list()
847 .and_then(|args| this.lower_generic_args(args, impl_trait_lower_fn))
848 .or_else(|| {
849 assoc_type_arg
850 .return_type_syntax()
851 .map(|_| GenericArgs::return_type_notation())
852 });
853 let type_ref = assoc_type_arg
854 .ty()
855 .map(|it| this.lower_type_ref(it, impl_trait_lower_fn));
856 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
857 l.bounds()
858 .map(|it| this.lower_type_bound(it, impl_trait_lower_fn))
859 .collect()
860 } else {
861 Box::default()
862 };
863 bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
864 });
865 }
866 }
867 ast::GenericArg::LifetimeArg(lifetime_arg) => {
868 if let Some(lifetime) = lifetime_arg.lifetime() {
869 let lifetime_ref = self.lower_lifetime_ref(lifetime);
870 args.push(GenericArg::Lifetime(lifetime_ref))
871 }
872 }
873 ast::GenericArg::ConstArg(arg) => {
874 let arg = self.lower_const_arg(arg);
875 args.push(GenericArg::Const(arg))
876 }
877 }
878 }
879
880 if args.is_empty() && bindings.is_empty() {
881 return None;
882 }
883 Some(GenericArgs {
884 args: args.into_boxed_slice(),
885 has_self_type: false,
886 bindings: bindings.into_boxed_slice(),
887 parenthesized: GenericArgsParentheses::No,
888 })
889 }
890
891 fn collect(&mut self, expr: Option<ast::Expr>, awaitable: Awaitable) -> ExprId {
892 self.awaitable_context.replace(awaitable);
893 self.with_label_rib(RibKind::Closure, |this| {
894 if awaitable == Awaitable::Yes {
895 match expr {
896 Some(e) => {
897 let syntax_ptr = AstPtr::new(&e);
898 let expr = this.collect_expr(e);
899 this.alloc_expr_desugared_with_ptr(
900 Expr::Async { id: None, statements: Box::new([]), tail: Some(expr) },
901 syntax_ptr,
902 )
903 }
904 None => this.missing_expr(),
905 }
906 } else {
907 this.collect_expr_opt(expr)
908 }
909 })
910 }
911
912 fn type_bounds_from_ast(
913 &mut self,
914 type_bounds_opt: Option<ast::TypeBoundList>,
915 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
916 ) -> ThinVec<TypeBound> {
917 if let Some(type_bounds) = type_bounds_opt {
918 ThinVec::from_iter(Vec::from_iter(
919 type_bounds.bounds().map(|it| self.lower_type_bound(it, impl_trait_lower_fn)),
920 ))
921 } else {
922 ThinVec::from_iter([])
923 }
924 }
925
926 fn lower_path_type(
927 &mut self,
928 path_type: &ast::PathType,
929 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
930 ) -> Option<Path> {
931 let path = self.lower_path(path_type.path()?, impl_trait_lower_fn)?;
932 Some(path)
933 }
934
935 fn lower_type_bound(
936 &mut self,
937 node: ast::TypeBound,
938 impl_trait_lower_fn: ImplTraitLowerFn<'_>,
939 ) -> TypeBound {
940 match node.kind() {
941 ast::TypeBoundKind::PathType(binder, path_type) => {
942 let binder = match binder.and_then(|it| it.generic_param_list()) {
943 Some(gpl) => gpl
944 .lifetime_params()
945 .flat_map(|lp| lp.lifetime().map(|lt| Name::new_lifetime(<.text())))
946 .collect(),
947 None => ThinVec::default(),
948 };
949 let m = match node.question_mark_token() {
950 Some(_) => TraitBoundModifier::Maybe,
951 None => TraitBoundModifier::None,
952 };
953 self.lower_path_type(&path_type, impl_trait_lower_fn)
954 .map(|p| {
955 let path = self.alloc_path(p, AstPtr::new(&path_type).upcast());
956 if binder.is_empty() {
957 TypeBound::Path(path, m)
958 } else {
959 TypeBound::ForLifetime(binder, path)
960 }
961 })
962 .unwrap_or(TypeBound::Error)
963 }
964 ast::TypeBoundKind::Use(gal) => TypeBound::Use(
965 gal.use_bound_generic_args()
966 .map(|p| match p {
967 ast::UseBoundGenericArg::Lifetime(l) => {
968 UseArgRef::Lifetime(self.lower_lifetime_ref(l))
969 }
970 ast::UseBoundGenericArg::NameRef(n) => UseArgRef::Name(n.as_name()),
971 })
972 .collect(),
973 ),
974 ast::TypeBoundKind::Lifetime(lifetime) => {
975 TypeBound::Lifetime(self.lower_lifetime_ref(lifetime))
976 }
977 }
978 }
979
980 fn lower_const_arg_opt(&mut self, arg: Option<ast::ConstArg>) -> ConstRef {
981 ConstRef { expr: self.collect_expr_opt(arg.and_then(|it| it.expr())) }
982 }
983
984 fn lower_const_arg(&mut self, arg: ast::ConstArg) -> ConstRef {
985 ConstRef { expr: self.collect_expr_opt(arg.expr()) }
986 }
987
988 fn collect_expr(&mut self, expr: ast::Expr) -> ExprId {
989 self.maybe_collect_expr(expr).unwrap_or_else(|| self.missing_expr())
990 }
991
992 fn maybe_collect_expr(&mut self, expr: ast::Expr) -> Option<ExprId> {
994 let syntax_ptr = AstPtr::new(&expr);
995 if !self.check_cfg(&expr) {
996 return None;
997 }
998
999 Some(match expr {
1001 ast::Expr::IfExpr(e) => {
1002 let then_branch = self.collect_block_opt(e.then_branch());
1003
1004 let else_branch = e.else_branch().map(|b| match b {
1005 ast::ElseBranch::Block(it) => self.collect_block(it),
1006 ast::ElseBranch::IfExpr(elif) => {
1007 let expr: ast::Expr = ast::Expr::cast(elif.syntax().clone()).unwrap();
1008 self.collect_expr(expr)
1009 }
1010 });
1011
1012 let condition = self.collect_expr_opt(e.condition());
1013
1014 self.alloc_expr(Expr::If { condition, then_branch, else_branch }, syntax_ptr)
1015 }
1016 ast::Expr::LetExpr(e) => {
1017 let pat = self.collect_pat_top(e.pat());
1018 let expr = self.collect_expr_opt(e.expr());
1019 self.alloc_expr(Expr::Let { pat, expr }, syntax_ptr)
1020 }
1021 ast::Expr::BlockExpr(e) => match e.modifier() {
1022 Some(ast::BlockModifier::Try(_)) => self.desugar_try_block(e),
1023 Some(ast::BlockModifier::Unsafe(_)) => {
1024 self.collect_block_(e, |id, statements, tail| Expr::Unsafe {
1025 id,
1026 statements,
1027 tail,
1028 })
1029 }
1030 Some(ast::BlockModifier::Label(label)) => {
1031 let label_hygiene = self.hygiene_id_for(label.syntax().text_range());
1032 let label_id = self.collect_label(label);
1033 self.with_labeled_rib(label_id, label_hygiene, |this| {
1034 this.collect_block_(e, |id, statements, tail| Expr::Block {
1035 id,
1036 statements,
1037 tail,
1038 label: Some(label_id),
1039 })
1040 })
1041 }
1042 Some(ast::BlockModifier::Async(_)) => {
1043 self.with_label_rib(RibKind::Closure, |this| {
1044 this.with_awaitable_block(Awaitable::Yes, |this| {
1045 this.collect_block_(e, |id, statements, tail| Expr::Async {
1046 id,
1047 statements,
1048 tail,
1049 })
1050 })
1051 })
1052 }
1053 Some(ast::BlockModifier::Const(_)) => {
1054 self.with_label_rib(RibKind::Constant, |this| {
1055 this.with_awaitable_block(Awaitable::No("constant block"), |this| {
1056 let (result_expr_id, prev_binding_owner) =
1057 this.initialize_binding_owner(syntax_ptr);
1058 let inner_expr = this.collect_block(e);
1059 this.store.exprs[result_expr_id] = Expr::Const(inner_expr);
1060 this.current_binding_owner = prev_binding_owner;
1061 result_expr_id
1062 })
1063 })
1064 }
1065 Some(ast::BlockModifier::AsyncGen(_)) => {
1067 self.with_awaitable_block(Awaitable::Yes, |this| this.collect_block(e))
1068 }
1069 Some(ast::BlockModifier::Gen(_)) => self
1070 .with_awaitable_block(Awaitable::No("non-async gen block"), |this| {
1071 this.collect_block(e)
1072 }),
1073 None => self.collect_block(e),
1074 },
1075 ast::Expr::LoopExpr(e) => {
1076 let label = e.label().map(|label| {
1077 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1078 });
1079 let body = self.collect_labelled_block_opt(label, e.loop_body());
1080 self.alloc_expr(Expr::Loop { body, label: label.map(|it| it.1) }, syntax_ptr)
1081 }
1082 ast::Expr::WhileExpr(e) => self.collect_while_loop(syntax_ptr, e),
1083 ast::Expr::ForExpr(e) => self.collect_for_loop(syntax_ptr, e),
1084 ast::Expr::CallExpr(e) => {
1085 let is_rustc_box = {
1087 let attrs = e.attrs();
1088 attrs.filter_map(|it| it.as_simple_atom()).any(|it| it == "rustc_box")
1089 };
1090 if is_rustc_box {
1091 let expr = self.collect_expr_opt(e.arg_list().and_then(|it| it.args().next()));
1092 self.alloc_expr(Expr::Box { expr }, syntax_ptr)
1093 } else {
1094 let callee = self.collect_expr_opt(e.expr());
1095 let args = if let Some(arg_list) = e.arg_list() {
1096 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
1097 } else {
1098 Box::default()
1099 };
1100 self.alloc_expr(Expr::Call { callee, args }, syntax_ptr)
1101 }
1102 }
1103 ast::Expr::MethodCallExpr(e) => {
1104 let receiver = self.collect_expr_opt(e.receiver());
1105 let args = if let Some(arg_list) = e.arg_list() {
1106 arg_list.args().filter_map(|e| self.maybe_collect_expr(e)).collect()
1107 } else {
1108 Box::default()
1109 };
1110 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
1111 let generic_args = e
1112 .generic_arg_list()
1113 .and_then(|it| {
1114 self.lower_generic_args(it, &mut Self::impl_trait_error_allocator)
1115 })
1116 .map(Box::new);
1117 self.alloc_expr(
1118 Expr::MethodCall { receiver, method_name, args, generic_args },
1119 syntax_ptr,
1120 )
1121 }
1122 ast::Expr::MatchExpr(e) => {
1123 let expr = self.collect_expr_opt(e.expr());
1124 let arms = if let Some(match_arm_list) = e.match_arm_list() {
1125 match_arm_list
1126 .arms()
1127 .filter_map(|arm| {
1128 if self.check_cfg(&arm) {
1129 Some(MatchArm {
1130 pat: self.collect_pat_top(arm.pat()),
1131 expr: self.collect_expr_opt(arm.expr()),
1132 guard: arm
1133 .guard()
1134 .map(|guard| self.collect_expr_opt(guard.condition())),
1135 })
1136 } else {
1137 None
1138 }
1139 })
1140 .collect()
1141 } else {
1142 Box::default()
1143 };
1144 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
1145 }
1146 ast::Expr::PathExpr(e) => {
1147 let (path, hygiene) = self
1148 .collect_expr_path(e)
1149 .map(|(path, hygiene)| (Expr::Path(path), hygiene))
1150 .unwrap_or((Expr::Missing, HygieneId::ROOT));
1151 let expr_id = self.alloc_expr(path, syntax_ptr);
1152 if !hygiene.is_root() {
1153 self.store.ident_hygiene.insert(expr_id.into(), hygiene);
1154 }
1155 expr_id
1156 }
1157 ast::Expr::ContinueExpr(e) => {
1158 let label = self.resolve_label(e.lifetime()).unwrap_or_else(|e| {
1159 self.store.diagnostics.push(e);
1160 None
1161 });
1162 self.alloc_expr(Expr::Continue { label }, syntax_ptr)
1163 }
1164 ast::Expr::BreakExpr(e) => {
1165 let label = self.resolve_label(e.lifetime()).unwrap_or_else(|e| {
1166 self.store.diagnostics.push(e);
1167 None
1168 });
1169 let expr = e.expr().map(|e| self.collect_expr(e));
1170 self.alloc_expr(Expr::Break { expr, label }, syntax_ptr)
1171 }
1172 ast::Expr::ParenExpr(e) => {
1173 let inner = self.collect_expr_opt(e.expr());
1174 let src = self.expander.in_file(syntax_ptr);
1176 self.store.expr_map.insert(src, inner.into());
1177 inner
1178 }
1179 ast::Expr::ReturnExpr(e) => {
1180 let expr = e.expr().map(|e| self.collect_expr(e));
1181 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
1182 }
1183 ast::Expr::BecomeExpr(e) => {
1184 let expr =
1185 e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
1186 self.alloc_expr(Expr::Become { expr }, syntax_ptr)
1187 }
1188 ast::Expr::YieldExpr(e) => {
1189 self.is_lowering_coroutine = true;
1190 let expr = e.expr().map(|e| self.collect_expr(e));
1191 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
1192 }
1193 ast::Expr::YeetExpr(e) => {
1194 let expr = e.expr().map(|e| self.collect_expr(e));
1195 self.alloc_expr(Expr::Yeet { expr }, syntax_ptr)
1196 }
1197 ast::Expr::RecordExpr(e) => {
1198 let path = e
1199 .path()
1200 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1201 .map(Box::new);
1202 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
1203 let fields = nfl
1204 .fields()
1205 .filter_map(|field| {
1206 if !self.check_cfg(&field) {
1207 return None;
1208 }
1209
1210 let name = field.field_name()?.as_name();
1211
1212 let expr = match field.expr() {
1213 Some(e) => self.collect_expr(e),
1214 None => self.missing_expr(),
1215 };
1216 let src = self.expander.in_file(AstPtr::new(&field));
1217 self.store.field_map_back.insert(expr, src);
1218 Some(RecordLitField { name, expr })
1219 })
1220 .collect();
1221 let spread = nfl.spread().map(|s| self.collect_expr(s));
1222 Expr::RecordLit { path, fields, spread }
1223 } else {
1224 Expr::RecordLit { path, fields: Box::default(), spread: None }
1225 };
1226
1227 self.alloc_expr(record_lit, syntax_ptr)
1228 }
1229 ast::Expr::FieldExpr(e) => {
1230 let expr = self.collect_expr_opt(e.expr());
1231 let name = match e.field_access() {
1232 Some(kind) => kind.as_name(),
1233 _ => Name::missing(),
1234 };
1235 self.alloc_expr(Expr::Field { expr, name }, syntax_ptr)
1236 }
1237 ast::Expr::AwaitExpr(e) => {
1238 let expr = self.collect_expr_opt(e.expr());
1239 if let Awaitable::No(location) = self.is_lowering_awaitable_block() {
1240 self.store.diagnostics.push(ExpressionStoreDiagnostics::AwaitOutsideOfAsync {
1241 node: self.expander.in_file(AstPtr::new(&e)),
1242 location: location.to_string(),
1243 });
1244 }
1245 self.alloc_expr(Expr::Await { expr }, syntax_ptr)
1246 }
1247 ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
1248 ast::Expr::CastExpr(e) => {
1249 let expr = self.collect_expr_opt(e.expr());
1250 let type_ref = self.lower_type_ref_opt_disallow_impl_trait(e.ty());
1251 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
1252 }
1253 ast::Expr::RefExpr(e) => {
1254 let expr = self.collect_expr_opt(e.expr());
1255 let raw_tok = e.raw_token().is_some();
1256 let mutability = if raw_tok {
1257 if e.mut_token().is_some() { Mutability::Mut } else { Mutability::Shared }
1258 } else {
1259 Mutability::from_mutable(e.mut_token().is_some())
1260 };
1261 let rawness = Rawness::from_raw(raw_tok);
1262 self.alloc_expr(Expr::Ref { expr, rawness, mutability }, syntax_ptr)
1263 }
1264 ast::Expr::PrefixExpr(e) => {
1265 let expr = self.collect_expr_opt(e.expr());
1266 match e.op_kind() {
1267 Some(op) => self.alloc_expr(Expr::UnaryOp { expr, op }, syntax_ptr),
1268 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1269 }
1270 }
1271 ast::Expr::ClosureExpr(e) => self.with_label_rib(RibKind::Closure, |this| {
1272 let (result_expr_id, prev_binding_owner) =
1273 this.initialize_binding_owner(syntax_ptr);
1274 let mut args = Vec::new();
1275 let mut arg_types = Vec::new();
1276 if let Some(pl) = e.param_list() {
1277 let num_params = pl.params().count();
1278 args.reserve_exact(num_params);
1279 arg_types.reserve_exact(num_params);
1280 for param in pl.params() {
1281 let pat = this.collect_pat_top(param.pat());
1282 let type_ref =
1283 param.ty().map(|it| this.lower_type_ref_disallow_impl_trait(it));
1284 args.push(pat);
1285 arg_types.push(type_ref);
1286 }
1287 }
1288 let ret_type = e
1289 .ret_type()
1290 .and_then(|r| r.ty())
1291 .map(|it| this.lower_type_ref_disallow_impl_trait(it));
1292
1293 let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
1294 let prev_try_block_label = this.current_try_block_label.take();
1295
1296 let awaitable = if e.async_token().is_some() {
1297 Awaitable::Yes
1298 } else {
1299 Awaitable::No("non-async closure")
1300 };
1301 let body =
1302 this.with_awaitable_block(awaitable, |this| this.collect_expr_opt(e.body()));
1303
1304 let closure_kind = if this.is_lowering_coroutine {
1305 let movability = if e.static_token().is_some() {
1306 Movability::Static
1307 } else {
1308 Movability::Movable
1309 };
1310 ClosureKind::Coroutine(movability)
1311 } else if e.async_token().is_some() {
1312 ClosureKind::Async
1313 } else {
1314 ClosureKind::Closure
1315 };
1316 let capture_by =
1317 if e.move_token().is_some() { CaptureBy::Value } else { CaptureBy::Ref };
1318 this.is_lowering_coroutine = prev_is_lowering_coroutine;
1319 this.current_binding_owner = prev_binding_owner;
1320 this.current_try_block_label = prev_try_block_label;
1321 this.store.exprs[result_expr_id] = Expr::Closure {
1322 args: args.into(),
1323 arg_types: arg_types.into(),
1324 ret_type,
1325 body,
1326 closure_kind,
1327 capture_by,
1328 };
1329 result_expr_id
1330 }),
1331 ast::Expr::BinExpr(e) => {
1332 let op = e.op_kind();
1333 if let Some(ast::BinaryOp::Assignment { op: None }) = op {
1334 let target = self.collect_expr_as_pat_opt(e.lhs());
1335 let value = self.collect_expr_opt(e.rhs());
1336 self.alloc_expr(Expr::Assignment { target, value }, syntax_ptr)
1337 } else {
1338 let lhs = self.collect_expr_opt(e.lhs());
1339 let rhs = self.collect_expr_opt(e.rhs());
1340 self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr)
1341 }
1342 }
1343 ast::Expr::TupleExpr(e) => {
1344 let mut exprs: Vec<_> = e.fields().map(|expr| self.collect_expr(expr)).collect();
1345 if comma_follows_token(e.l_paren_token()) {
1348 exprs.insert(0, self.missing_expr());
1349 }
1350
1351 self.alloc_expr(Expr::Tuple { exprs: exprs.into_boxed_slice() }, syntax_ptr)
1352 }
1353 ast::Expr::ArrayExpr(e) => {
1354 let kind = e.kind();
1355
1356 match kind {
1357 ArrayExprKind::ElementList(e) => {
1358 let elements = e.map(|expr| self.collect_expr(expr)).collect();
1359 self.alloc_expr(Expr::Array(Array::ElementList { elements }), syntax_ptr)
1360 }
1361 ArrayExprKind::Repeat { initializer, repeat } => {
1362 let initializer = self.collect_expr_opt(initializer);
1363 let repeat = self.with_label_rib(RibKind::Constant, |this| {
1364 if let Some(repeat) = repeat {
1365 let syntax_ptr = AstPtr::new(&repeat);
1366 this.collect_as_a_binding_owner_bad(
1367 |this| this.collect_expr(repeat),
1368 syntax_ptr,
1369 )
1370 } else {
1371 this.missing_expr()
1372 }
1373 });
1374 self.alloc_expr(
1375 Expr::Array(Array::Repeat { initializer, repeat }),
1376 syntax_ptr,
1377 )
1378 }
1379 }
1380 }
1381
1382 ast::Expr::Literal(e) => self.alloc_expr(Expr::Literal(e.kind().into()), syntax_ptr),
1383 ast::Expr::IndexExpr(e) => {
1384 let base = self.collect_expr_opt(e.base());
1385 let index = self.collect_expr_opt(e.index());
1386 self.alloc_expr(Expr::Index { base, index }, syntax_ptr)
1387 }
1388 ast::Expr::RangeExpr(e) => {
1389 let lhs = e.start().map(|lhs| self.collect_expr(lhs));
1390 let rhs = e.end().map(|rhs| self.collect_expr(rhs));
1391 match e.op_kind() {
1392 Some(range_type) => {
1393 self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr)
1394 }
1395 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1396 }
1397 }
1398 ast::Expr::MacroExpr(e) => {
1399 let e = e.macro_call()?;
1400 let macro_ptr = AstPtr::new(&e);
1401 let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
1402 expansion.map(|it| this.collect_expr(it))
1403 });
1404 match id {
1405 Some(id) => {
1406 let src = self.expander.in_file(syntax_ptr);
1409 self.store.expr_map.insert(src, id.into());
1410 id
1411 }
1412 None => self.alloc_expr(Expr::Missing, syntax_ptr),
1413 }
1414 }
1415 ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
1416 ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr),
1417 ast::Expr::OffsetOfExpr(e) => {
1418 let container = self.lower_type_ref_opt_disallow_impl_trait(e.ty());
1419 let fields = e.fields().map(|it| it.as_name()).collect();
1420 self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
1421 }
1422 ast::Expr::FormatArgsExpr(f) => self.collect_format_args(f, syntax_ptr),
1423 })
1424 }
1425
1426 fn collect_expr_path(&mut self, e: ast::PathExpr) -> Option<(Path, HygieneId)> {
1427 e.path().and_then(|path| {
1428 let path = self.lower_path(path, &mut Self::impl_trait_error_allocator)?;
1429 let may_be_variable = matches!(&path, Path::BarePath(mod_path) if mod_path.len() <= 1);
1431 let hygiene = if may_be_variable {
1432 self.hygiene_id_for(e.syntax().text_range())
1433 } else {
1434 HygieneId::ROOT
1435 };
1436 Some((path, hygiene))
1437 })
1438 }
1439
1440 fn collect_expr_as_pat_opt(&mut self, expr: Option<ast::Expr>) -> PatId {
1441 match expr {
1442 Some(expr) => self.collect_expr_as_pat(expr),
1443 _ => self.missing_pat(),
1444 }
1445 }
1446
1447 fn collect_expr_as_pat(&mut self, expr: ast::Expr) -> PatId {
1448 self.maybe_collect_expr_as_pat(&expr).unwrap_or_else(|| {
1449 let src = self.expander.in_file(AstPtr::new(&expr).wrap_left());
1450 let expr = self.collect_expr(expr);
1451 let id = self.store.pats.alloc(Pat::Expr(expr));
1453 self.store.pat_map_back.insert(id, src);
1454 id
1455 })
1456 }
1457
1458 fn maybe_collect_expr_as_pat(&mut self, expr: &ast::Expr) -> Option<PatId> {
1459 if !self.check_cfg(expr) {
1460 return None;
1461 }
1462 let syntax_ptr = AstPtr::new(expr);
1463
1464 let result = match expr {
1465 ast::Expr::UnderscoreExpr(_) => self.alloc_pat_from_expr(Pat::Wild, syntax_ptr),
1466 ast::Expr::ParenExpr(e) => {
1467 if let Some(ast::Expr::RangeExpr(range)) = e.expr()
1469 && range.is_range_full()
1470 {
1471 return Some(self.alloc_pat_from_expr(
1472 Pat::Tuple { args: Box::default(), ellipsis: Some(0) },
1473 syntax_ptr,
1474 ));
1475 }
1476 return e.expr().and_then(|expr| self.maybe_collect_expr_as_pat(&expr));
1477 }
1478 ast::Expr::TupleExpr(e) => {
1479 let (ellipsis, args) = collect_tuple(self, e.fields());
1480 self.alloc_pat_from_expr(Pat::Tuple { args, ellipsis }, syntax_ptr)
1481 }
1482 ast::Expr::ArrayExpr(e) => {
1483 if e.semicolon_token().is_some() {
1484 return None;
1485 }
1486
1487 let mut elements = e.exprs();
1488 let prefix = elements
1489 .by_ref()
1490 .map_while(|elem| collect_possibly_rest(self, elem).left())
1491 .collect();
1492 let suffix = elements.map(|elem| self.collect_expr_as_pat(elem)).collect();
1493 self.alloc_pat_from_expr(Pat::Slice { prefix, slice: None, suffix }, syntax_ptr)
1494 }
1495 ast::Expr::CallExpr(e) => {
1496 let path = collect_path(self, e.expr()?)?;
1497 let path = path
1498 .path()
1499 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1500 .map(Box::new);
1501 let (ellipsis, args) = collect_tuple(self, e.arg_list()?.args());
1502 self.alloc_pat_from_expr(Pat::TupleStruct { path, args, ellipsis }, syntax_ptr)
1503 }
1504 ast::Expr::PathExpr(e) => {
1505 let (path, hygiene) = self
1506 .collect_expr_path(e.clone())
1507 .map(|(path, hygiene)| (Pat::Path(path), hygiene))
1508 .unwrap_or((Pat::Missing, HygieneId::ROOT));
1509 let pat_id = self.alloc_pat_from_expr(path, syntax_ptr);
1510 if !hygiene.is_root() {
1511 self.store.ident_hygiene.insert(pat_id.into(), hygiene);
1512 }
1513 pat_id
1514 }
1515 ast::Expr::MacroExpr(e) => {
1516 let e = e.macro_call()?;
1517 let macro_ptr = AstPtr::new(&e);
1518 let src = self.expander.in_file(AstPtr::new(expr));
1519 let id = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
1520 this.collect_expr_as_pat_opt(expansion)
1521 });
1522 self.store.expr_map.insert(src, id.into());
1523 id
1524 }
1525 ast::Expr::RecordExpr(e) => {
1526 let path = e
1527 .path()
1528 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
1529 .map(Box::new);
1530 let record_field_list = e.record_expr_field_list()?;
1531 let ellipsis = record_field_list.dotdot_token().is_some();
1532 let args = record_field_list
1534 .fields()
1535 .filter_map(|f| {
1536 if !self.check_cfg(&f) {
1537 return None;
1538 }
1539 let field_expr = f.expr()?;
1540 let pat = self.collect_expr_as_pat(field_expr);
1541 let name = f.field_name()?.as_name();
1542 let src = self.expander.in_file(AstPtr::new(&f).wrap_left());
1543 self.store.pat_field_map_back.insert(pat, src);
1544 Some(RecordFieldPat { name, pat })
1545 })
1546 .collect();
1547 self.alloc_pat_from_expr(Pat::Record { path, args, ellipsis }, syntax_ptr)
1548 }
1549 _ => return None,
1550 };
1551 return Some(result);
1552
1553 fn collect_path(this: &mut ExprCollector<'_>, expr: ast::Expr) -> Option<ast::PathExpr> {
1554 match expr {
1555 ast::Expr::PathExpr(e) => Some(e),
1556 ast::Expr::MacroExpr(mac) => {
1557 let call = mac.macro_call()?;
1558 {
1559 let macro_ptr = AstPtr::new(&call);
1560 this.collect_macro_call(call, macro_ptr, true, |this, expanded_path| {
1561 collect_path(this, expanded_path?)
1562 })
1563 }
1564 }
1565 _ => None,
1566 }
1567 }
1568
1569 fn collect_possibly_rest(
1570 this: &mut ExprCollector<'_>,
1571 expr: ast::Expr,
1572 ) -> Either<PatId, ()> {
1573 match &expr {
1574 ast::Expr::RangeExpr(e) if e.is_range_full() => Either::Right(()),
1575 ast::Expr::MacroExpr(mac) => match mac.macro_call() {
1576 Some(call) => {
1577 let macro_ptr = AstPtr::new(&call);
1578 let pat = this.collect_macro_call(
1579 call,
1580 macro_ptr,
1581 true,
1582 |this, expanded_expr| match expanded_expr {
1583 Some(expanded_pat) => collect_possibly_rest(this, expanded_pat),
1584 None => Either::Left(this.missing_pat()),
1585 },
1586 );
1587 if let Either::Left(pat) = pat {
1588 let src = this.expander.in_file(AstPtr::new(&expr).wrap_left());
1589 this.store.pat_map_back.insert(pat, src);
1590 }
1591 pat
1592 }
1593 None => {
1594 let ptr = AstPtr::new(&expr);
1595 Either::Left(this.alloc_pat_from_expr(Pat::Missing, ptr))
1596 }
1597 },
1598 _ => Either::Left(this.collect_expr_as_pat(expr)),
1599 }
1600 }
1601
1602 fn collect_tuple(
1603 this: &mut ExprCollector<'_>,
1604 fields: ast::AstChildren<ast::Expr>,
1605 ) -> (Option<u32>, Box<[la_arena::Idx<Pat>]>) {
1606 let mut ellipsis = None;
1607 let args = fields
1608 .enumerate()
1609 .filter_map(|(idx, elem)| {
1610 match collect_possibly_rest(this, elem) {
1611 Either::Left(pat) => Some(pat),
1612 Either::Right(()) => {
1613 if ellipsis.is_none() {
1614 ellipsis = Some(idx as u32);
1615 }
1616 None
1618 }
1619 }
1620 })
1621 .collect();
1622 (ellipsis, args)
1623 }
1624 }
1625
1626 fn initialize_binding_owner(
1627 &mut self,
1628 syntax_ptr: AstPtr<ast::Expr>,
1629 ) -> (ExprId, Option<ExprId>) {
1630 let result_expr_id = self.alloc_expr(Expr::Missing, syntax_ptr);
1631 let prev_binding_owner = self.current_binding_owner.take();
1632 self.current_binding_owner = Some(result_expr_id);
1633
1634 (result_expr_id, prev_binding_owner)
1635 }
1636
1637 fn collect_as_a_binding_owner_bad(
1642 &mut self,
1643 job: impl FnOnce(&mut ExprCollector<'_>) -> ExprId,
1644 syntax_ptr: AstPtr<ast::Expr>,
1645 ) -> ExprId {
1646 let (id, prev_owner) = self.initialize_binding_owner(syntax_ptr);
1647 let tmp = job(self);
1648 self.store.exprs[id] = mem::replace(&mut self.store.exprs[tmp], Expr::Missing);
1649 self.current_binding_owner = prev_owner;
1650 id
1651 }
1652
1653 fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
1657 let try_from_output = self.lang_path(LangItem::TryTraitFromOutput);
1658 let label = self.alloc_label_desugared(Label {
1659 name: Name::generate_new_name(self.store.labels.len()),
1660 });
1661 let old_label = self.current_try_block_label.replace(label);
1662
1663 let ptr = AstPtr::new(&e).upcast();
1664 let (btail, expr_id) = self.with_labeled_rib(label, HygieneId::ROOT, |this| {
1665 let mut btail = None;
1666 let block = this.collect_block_(e, |id, statements, tail| {
1667 btail = tail;
1668 Expr::Block { id, statements, tail, label: Some(label) }
1669 });
1670 (btail, block)
1671 });
1672
1673 let callee = self
1674 .alloc_expr_desugared_with_ptr(try_from_output.map_or(Expr::Missing, Expr::Path), ptr);
1675 let next_tail = match btail {
1676 Some(tail) => self
1677 .alloc_expr_desugared_with_ptr(Expr::Call { callee, args: Box::new([tail]) }, ptr),
1678 None => {
1679 let unit =
1680 self.alloc_expr_desugared_with_ptr(Expr::Tuple { exprs: Box::new([]) }, ptr);
1681 self.alloc_expr_desugared_with_ptr(
1682 Expr::Call { callee, args: Box::new([unit]) },
1683 ptr,
1684 )
1685 }
1686 };
1687 let Expr::Block { tail, .. } = &mut self.store.exprs[expr_id] else {
1688 unreachable!("block was lowered to non-block");
1689 };
1690 *tail = Some(next_tail);
1691 self.current_try_block_label = old_label;
1692 expr_id
1693 }
1694
1695 fn collect_while_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::WhileExpr) -> ExprId {
1709 let label = e.label().map(|label| {
1710 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1711 });
1712 let body = self.collect_labelled_block_opt(label, e.loop_body());
1713
1714 let condition = match label {
1728 Some((label_hygiene, label)) => self.with_labeled_rib(label, label_hygiene, |this| {
1729 this.collect_expr_opt(e.condition())
1730 }),
1731 None => self.collect_expr_opt(e.condition()),
1732 };
1733
1734 let break_expr = self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr);
1735 let if_expr = self.alloc_expr(
1736 Expr::If { condition, then_branch: body, else_branch: Some(break_expr) },
1737 syntax_ptr,
1738 );
1739 self.alloc_expr(Expr::Loop { body: if_expr, label: label.map(|it| it.1) }, syntax_ptr)
1740 }
1741
1742 fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
1756 let into_iter_fn = self.lang_path(LangItem::IntoIterIntoIter);
1757 let iter_next_fn = self.lang_path(LangItem::IteratorNext);
1758 let option_some = self.lang_path(LangItem::OptionSome);
1759 let option_none = self.lang_path(LangItem::OptionNone);
1760 let head = self.collect_expr_opt(e.iterable());
1761 let into_iter_fn_expr =
1762 self.alloc_expr(into_iter_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1763 let iterator = self.alloc_expr(
1764 Expr::Call { callee: into_iter_fn_expr, args: Box::new([head]) },
1765 syntax_ptr,
1766 );
1767 let none_arm = MatchArm {
1768 pat: self.alloc_pat_desugared(option_none.map_or(Pat::Missing, Pat::Path)),
1769 guard: None,
1770 expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr),
1771 };
1772 let some_pat = Pat::TupleStruct {
1773 path: option_some.map(Box::new),
1774 args: Box::new([self.collect_pat_top(e.pat())]),
1775 ellipsis: None,
1776 };
1777 let label = e.label().map(|label| {
1778 (self.hygiene_id_for(label.syntax().text_range()), self.collect_label(label))
1779 });
1780 let some_arm = MatchArm {
1781 pat: self.alloc_pat_desugared(some_pat),
1782 guard: None,
1783 expr: self.with_opt_labeled_rib(label, |this| {
1784 this.collect_expr_opt(e.loop_body().map(|it| it.into()))
1785 }),
1786 };
1787 let iter_name = Name::generate_new_name(self.store.exprs.len());
1788 let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
1789 let iter_expr_mut = self.alloc_expr(
1790 Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
1791 syntax_ptr,
1792 );
1793 let iter_next_fn_expr =
1794 self.alloc_expr(iter_next_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1795 let iter_next_expr = self.alloc_expr(
1796 Expr::Call { callee: iter_next_fn_expr, args: Box::new([iter_expr_mut]) },
1797 syntax_ptr,
1798 );
1799 let loop_inner = self.alloc_expr(
1800 Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
1801 syntax_ptr,
1802 );
1803 let loop_inner = self.alloc_expr(
1804 Expr::Block {
1805 id: None,
1806 statements: Box::default(),
1807 tail: Some(loop_inner),
1808 label: None,
1809 },
1810 syntax_ptr,
1811 );
1812 let loop_outer = self
1813 .alloc_expr(Expr::Loop { body: loop_inner, label: label.map(|it| it.1) }, syntax_ptr);
1814 let iter_binding =
1815 self.alloc_binding(iter_name, BindingAnnotation::Mutable, HygieneId::ROOT);
1816 let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
1817 self.add_definition_to_binding(iter_binding, iter_pat);
1818 self.alloc_expr(
1819 Expr::Match {
1820 expr: iterator,
1821 arms: Box::new([MatchArm { pat: iter_pat, guard: None, expr: loop_outer }]),
1822 },
1823 syntax_ptr,
1824 )
1825 }
1826
1827 fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
1839 let try_branch = self.lang_path(LangItem::TryTraitBranch);
1840 let cf_continue = self.lang_path(LangItem::ControlFlowContinue);
1841 let cf_break = self.lang_path(LangItem::ControlFlowBreak);
1842 let try_from_residual = self.lang_path(LangItem::TryTraitFromResidual);
1843 let operand = self.collect_expr_opt(e.expr());
1844 let try_branch = self.alloc_expr(try_branch.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1845 let expr = self
1846 .alloc_expr(Expr::Call { callee: try_branch, args: Box::new([operand]) }, syntax_ptr);
1847 let continue_name = Name::generate_new_name(self.store.bindings.len());
1848 let continue_binding = self.alloc_binding(
1849 continue_name.clone(),
1850 BindingAnnotation::Unannotated,
1851 HygieneId::ROOT,
1852 );
1853 let continue_bpat =
1854 self.alloc_pat_desugared(Pat::Bind { id: continue_binding, subpat: None });
1855 self.add_definition_to_binding(continue_binding, continue_bpat);
1856 let continue_arm = MatchArm {
1857 pat: self.alloc_pat_desugared(Pat::TupleStruct {
1858 path: cf_continue.map(Box::new),
1859 args: Box::new([continue_bpat]),
1860 ellipsis: None,
1861 }),
1862 guard: None,
1863 expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
1864 };
1865 let break_name = Name::generate_new_name(self.store.bindings.len());
1866 let break_binding =
1867 self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated, HygieneId::ROOT);
1868 let break_bpat = self.alloc_pat_desugared(Pat::Bind { id: break_binding, subpat: None });
1869 self.add_definition_to_binding(break_binding, break_bpat);
1870 let break_arm = MatchArm {
1871 pat: self.alloc_pat_desugared(Pat::TupleStruct {
1872 path: cf_break.map(Box::new),
1873 args: Box::new([break_bpat]),
1874 ellipsis: None,
1875 }),
1876 guard: None,
1877 expr: {
1878 let it = self.alloc_expr(Expr::Path(Path::from(break_name)), syntax_ptr);
1879 let callee = self
1880 .alloc_expr(try_from_residual.map_or(Expr::Missing, Expr::Path), syntax_ptr);
1881 let result =
1882 self.alloc_expr(Expr::Call { callee, args: Box::new([it]) }, syntax_ptr);
1883 self.alloc_expr(
1884 match self.current_try_block_label {
1885 Some(label) => Expr::Break { expr: Some(result), label: Some(label) },
1886 None => Expr::Return { expr: Some(result) },
1887 },
1888 syntax_ptr,
1889 )
1890 },
1891 };
1892 let arms = Box::new([continue_arm, break_arm]);
1893 self.alloc_expr(Expr::Match { expr, arms }, syntax_ptr)
1894 }
1895
1896 fn collect_macro_call<T, U>(
1897 &mut self,
1898 mcall: ast::MacroCall,
1899 syntax_ptr: AstPtr<ast::MacroCall>,
1900 record_diagnostics: bool,
1901 collector: impl FnOnce(&mut Self, Option<T>) -> U,
1902 ) -> U
1903 where
1904 T: ast::AstNode,
1905 {
1906 let macro_call_ptr = self.expander.in_file(syntax_ptr);
1907 let module = self.module.local_id;
1908
1909 let block_call = self.def_map.modules[self.module.local_id].scope.macro_invoc(
1910 self.expander.in_file(self.expander.ast_id_map().ast_id_for_ptr(syntax_ptr)),
1911 );
1912 let res = match block_call {
1913 Some(call) => Ok(self.expander.enter_expand_id(self.db, call)),
1915 None => {
1916 let resolver = |path: &_| {
1917 self.def_map
1918 .resolve_path(
1919 self.local_def_map,
1920 self.db,
1921 module,
1922 path,
1923 crate::item_scope::BuiltinShadowMode::Other,
1924 Some(MacroSubNs::Bang),
1925 )
1926 .0
1927 .take_macros()
1928 };
1929 self.expander.enter_expand(
1930 self.db,
1931 mcall,
1932 self.module.krate(),
1933 resolver,
1934 &mut |ptr, call| {
1935 _ = self.store.expansions.insert(ptr.map(|(it, _)| it), call);
1936 },
1937 )
1938 }
1939 };
1940
1941 let res = match res {
1942 Ok(res) => res,
1943 Err(UnresolvedMacro { path }) => {
1944 if record_diagnostics {
1945 self.store.diagnostics.push(ExpressionStoreDiagnostics::UnresolvedMacroCall {
1946 node: self.expander.in_file(syntax_ptr),
1947 path,
1948 });
1949 }
1950 return collector(self, None);
1951 }
1952 };
1953 match res.value {
1956 Some((mark, expansion)) => {
1957 if let Some(macro_file) = self.expander.current_file_id().macro_file() {
1960 self.store.expansions.insert(macro_call_ptr, macro_file);
1961 }
1962
1963 let id = collector(self, expansion.map(|it| it.tree()));
1964 self.expander.exit(mark);
1965 id
1966 }
1967 None => collector(self, None),
1968 }
1969 }
1970
1971 fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
1972 match expr {
1973 Some(expr) => self.collect_expr(expr),
1974 None => self.missing_expr(),
1975 }
1976 }
1977
1978 fn collect_macro_as_stmt(
1979 &mut self,
1980 statements: &mut Vec<Statement>,
1981 mac: ast::MacroExpr,
1982 ) -> Option<ExprId> {
1983 let mac_call = mac.macro_call()?;
1984 let syntax_ptr = AstPtr::new(&ast::Expr::from(mac));
1985 let macro_ptr = AstPtr::new(&mac_call);
1986 let expansion = self.collect_macro_call(
1987 mac_call,
1988 macro_ptr,
1989 false,
1990 |this, expansion: Option<ast::MacroStmts>| match expansion {
1991 Some(expansion) => {
1992 expansion.statements().for_each(|stmt| this.collect_stmt(statements, stmt));
1993 expansion.expr().and_then(|expr| match expr {
1994 ast::Expr::MacroExpr(mac) => this.collect_macro_as_stmt(statements, mac),
1995 expr => Some(this.collect_expr(expr)),
1996 })
1997 }
1998 None => None,
1999 },
2000 );
2001 expansion.inspect(|&tail| {
2002 let src = self.expander.in_file(syntax_ptr);
2005 self.store.expr_map.insert(src, tail.into());
2006 })
2007 }
2008
2009 fn collect_stmt(&mut self, statements: &mut Vec<Statement>, s: ast::Stmt) {
2010 match s {
2011 ast::Stmt::LetStmt(stmt) => {
2012 if !self.check_cfg(&stmt) {
2013 return;
2014 }
2015 let pat = self.collect_pat_top(stmt.pat());
2016 let type_ref = stmt.ty().map(|it| self.lower_type_ref_disallow_impl_trait(it));
2017 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
2018 let else_branch = stmt
2019 .let_else()
2020 .and_then(|let_else| let_else.block_expr())
2021 .map(|block| self.collect_block(block));
2022 statements.push(Statement::Let { pat, type_ref, initializer, else_branch });
2023 }
2024 ast::Stmt::ExprStmt(stmt) => {
2025 let expr = stmt.expr();
2026 match &expr {
2027 Some(expr) if !self.check_cfg(expr) => return,
2028 _ => (),
2029 }
2030 let has_semi = stmt.semicolon_token().is_some();
2031 if let Some(ast::Expr::MacroExpr(mac)) = expr {
2033 if let Some(expr) = self.collect_macro_as_stmt(statements, mac) {
2034 statements.push(Statement::Expr { expr, has_semi })
2035 }
2036 } else {
2037 let expr = self.collect_expr_opt(expr);
2038 statements.push(Statement::Expr { expr, has_semi });
2039 }
2040 }
2041 ast::Stmt::Item(ast::Item::MacroDef(macro_)) => {
2042 if !self.check_cfg(¯o_) {
2043 return;
2044 }
2045 let Some(name) = macro_.name() else {
2046 statements.push(Statement::Item(Item::Other));
2047 return;
2048 };
2049 let name = name.as_name();
2050 let macro_id = self.def_map.modules[DefMap::ROOT].scope.get(&name).take_macros();
2051 self.collect_macro_def(statements, macro_id);
2052 }
2053 ast::Stmt::Item(ast::Item::MacroRules(macro_)) => {
2054 if !self.check_cfg(¯o_) {
2055 return;
2056 }
2057 let Some(name) = macro_.name() else {
2058 statements.push(Statement::Item(Item::Other));
2059 return;
2060 };
2061 let name = name.as_name();
2062 let macro_defs_count =
2063 self.current_block_legacy_macro_defs_count.entry(name.clone()).or_insert(0);
2064 let macro_id = self.def_map.modules[DefMap::ROOT]
2065 .scope
2066 .get_legacy_macro(&name)
2067 .and_then(|it| it.get(*macro_defs_count))
2068 .copied();
2069 *macro_defs_count += 1;
2070 self.collect_macro_def(statements, macro_id);
2071 }
2072 ast::Stmt::Item(_item) => statements.push(Statement::Item(Item::Other)),
2073 }
2074 }
2075
2076 fn collect_macro_def(&mut self, statements: &mut Vec<Statement>, macro_id: Option<MacroId>) {
2077 let Some(macro_id) = macro_id else {
2078 never!("def map should have macro definition, but it doesn't");
2079 statements.push(Statement::Item(Item::Other));
2080 return;
2081 };
2082 let macro_id = self.db.macro_def(macro_id);
2083 statements.push(Statement::Item(Item::MacroDef(Box::new(macro_id))));
2084 self.label_ribs.push(LabelRib::new(RibKind::MacroDef(Box::new(macro_id))));
2085 }
2086
2087 fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
2088 self.collect_block_(block, |id, statements, tail| Expr::Block {
2089 id,
2090 statements,
2091 tail,
2092 label: None,
2093 })
2094 }
2095
2096 fn collect_block_(
2097 &mut self,
2098 block: ast::BlockExpr,
2099 mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr,
2100 ) -> ExprId {
2101 let block_id = self.expander.ast_id_map().ast_id_for_block(&block).map(|file_local_id| {
2102 let ast_id = self.expander.in_file(file_local_id);
2103 self.db.intern_block(BlockLoc { ast_id, module: self.module })
2104 });
2105
2106 let (module, def_map) =
2107 match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) {
2108 Some((def_map, block_id)) => {
2109 self.store.block_scopes.push(block_id);
2110 (def_map.module_id(DefMap::ROOT), def_map)
2111 }
2112 None => (self.module, self.def_map),
2113 };
2114 let prev_def_map = mem::replace(&mut self.def_map, def_map);
2115 let prev_local_module = mem::replace(&mut self.module, module);
2116 let prev_legacy_macros_count = mem::take(&mut self.current_block_legacy_macro_defs_count);
2117
2118 let mut statements = Vec::new();
2119 block.statements().for_each(|s| self.collect_stmt(&mut statements, s));
2120 let tail = block.tail_expr().and_then(|e| match e {
2121 ast::Expr::MacroExpr(mac) => self.collect_macro_as_stmt(&mut statements, mac),
2122 expr => self.maybe_collect_expr(expr),
2123 });
2124 let tail = tail.or_else(|| {
2125 let stmt = statements.pop()?;
2126 if let Statement::Expr { expr, has_semi: false } = stmt {
2127 return Some(expr);
2128 }
2129 statements.push(stmt);
2130 None
2131 });
2132
2133 let syntax_node_ptr = AstPtr::new(&block.into());
2134 let expr_id = self
2135 .alloc_expr(mk_block(block_id, statements.into_boxed_slice(), tail), syntax_node_ptr);
2136
2137 self.def_map = prev_def_map;
2138 self.module = prev_local_module;
2139 self.current_block_legacy_macro_defs_count = prev_legacy_macros_count;
2140 expr_id
2141 }
2142
2143 fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
2144 match expr {
2145 Some(block) => self.collect_block(block),
2146 None => self.missing_expr(),
2147 }
2148 }
2149
2150 fn collect_labelled_block_opt(
2151 &mut self,
2152 label: Option<(HygieneId, LabelId)>,
2153 expr: Option<ast::BlockExpr>,
2154 ) -> ExprId {
2155 match label {
2156 Some((hygiene, label)) => {
2157 self.with_labeled_rib(label, hygiene, |this| this.collect_block_opt(expr))
2158 }
2159 None => self.collect_block_opt(expr),
2160 }
2161 }
2162
2163 fn collect_pat_top(&mut self, pat: Option<ast::Pat>) -> PatId {
2166 match pat {
2167 Some(pat) => self.collect_pat(pat, &mut BindingList::default()),
2168 None => self.missing_pat(),
2169 }
2170 }
2171
2172 fn collect_pat(&mut self, pat: ast::Pat, binding_list: &mut BindingList) -> PatId {
2173 let pattern = match &pat {
2174 ast::Pat::IdentPat(bp) => {
2175 let name = bp.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
2176 let hygiene = bp
2177 .name()
2178 .map(|name| self.hygiene_id_for(name.syntax().text_range()))
2179 .unwrap_or(HygieneId::ROOT);
2180
2181 let annotation =
2182 BindingAnnotation::new(bp.mut_token().is_some(), bp.ref_token().is_some());
2183 let subpat = bp.pat().map(|subpat| self.collect_pat(subpat, binding_list));
2184
2185 let is_simple_ident_pat =
2186 annotation == BindingAnnotation::Unannotated && subpat.is_none();
2187 let (binding, pattern) = if is_simple_ident_pat {
2188 let (resolved, _) = self.def_map.resolve_path(
2191 self.local_def_map,
2192 self.db,
2193 self.module.local_id,
2194 &name.clone().into(),
2195 BuiltinShadowMode::Other,
2196 None,
2197 );
2198 match resolved.take_values() {
2202 Some(ModuleDefId::ConstId(_)) => (None, Pat::Path(name.into())),
2203 Some(ModuleDefId::EnumVariantId(variant))
2204 if variant.fields(self.db).shape != FieldsShape::Record =>
2206 {
2207 (None, Pat::Path(name.into()))
2208 }
2209 Some(ModuleDefId::AdtId(AdtId::StructId(s)))
2210 if self.db.struct_signature(s).shape != FieldsShape::Record =>
2212 {
2213 (None, Pat::Path(name.into()))
2214 }
2215 _ => {
2217 let id = binding_list.find(self, name, hygiene, annotation);
2218 (Some(id), Pat::Bind { id, subpat })
2219 }
2220 }
2221 } else {
2222 let id = binding_list.find(self, name, hygiene, annotation);
2223 (Some(id), Pat::Bind { id, subpat })
2224 };
2225
2226 let ptr = AstPtr::new(&pat);
2227 let pat = self.alloc_pat(pattern, ptr);
2228 if let Some(binding_id) = binding {
2229 self.add_definition_to_binding(binding_id, pat);
2230 }
2231 return pat;
2232 }
2233 ast::Pat::TupleStructPat(p) => {
2234 let path = p
2235 .path()
2236 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
2237 .map(Box::new);
2238 let (args, ellipsis) = self.collect_tuple_pat(
2239 p.fields(),
2240 comma_follows_token(p.l_paren_token()),
2241 binding_list,
2242 );
2243 Pat::TupleStruct { path, args, ellipsis }
2244 }
2245 ast::Pat::RefPat(p) => {
2246 let pat = self.collect_pat_opt(p.pat(), binding_list);
2247 let mutability = Mutability::from_mutable(p.mut_token().is_some());
2248 Pat::Ref { pat, mutability }
2249 }
2250 ast::Pat::PathPat(p) => {
2251 let path = p
2252 .path()
2253 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator));
2254 path.map(Pat::Path).unwrap_or(Pat::Missing)
2255 }
2256 ast::Pat::OrPat(p) => 'b: {
2257 let prev_is_used = mem::take(&mut binding_list.is_used);
2258 let prev_reject_new = mem::take(&mut binding_list.reject_new);
2259 let mut pats = Vec::with_capacity(p.pats().count());
2260 let mut it = p.pats();
2261 let Some(first) = it.next() else {
2262 break 'b Pat::Or(Box::new([]));
2263 };
2264 pats.push(self.collect_pat(first, binding_list));
2265 binding_list.reject_new = true;
2266 for rest in it {
2267 for (_, it) in binding_list.is_used.iter_mut() {
2268 *it = false;
2269 }
2270 pats.push(self.collect_pat(rest, binding_list));
2271 for (&id, &is_used) in binding_list.is_used.iter() {
2272 if !is_used {
2273 self.store.bindings[id].problems =
2274 Some(BindingProblems::NotBoundAcrossAll);
2275 }
2276 }
2277 }
2278 binding_list.reject_new = prev_reject_new;
2279 let current_is_used = mem::replace(&mut binding_list.is_used, prev_is_used);
2280 for (id, _) in current_is_used.into_iter() {
2281 binding_list.check_is_used(self, id);
2282 }
2283 if let &[pat] = &*pats {
2284 return pat;
2286 }
2287 Pat::Or(pats.into())
2288 }
2289 ast::Pat::ParenPat(p) => return self.collect_pat_opt(p.pat(), binding_list),
2290 ast::Pat::TuplePat(p) => {
2291 let (args, ellipsis) = self.collect_tuple_pat(
2292 p.fields(),
2293 comma_follows_token(p.l_paren_token()),
2294 binding_list,
2295 );
2296 Pat::Tuple { args, ellipsis }
2297 }
2298 ast::Pat::WildcardPat(_) => Pat::Wild,
2299 ast::Pat::RecordPat(p) => {
2300 let path = p
2301 .path()
2302 .and_then(|path| self.lower_path(path, &mut Self::impl_trait_error_allocator))
2303 .map(Box::new);
2304 let record_pat_field_list =
2305 &p.record_pat_field_list().expect("every struct should have a field list");
2306 let args = record_pat_field_list
2307 .fields()
2308 .filter_map(|f| {
2309 if !self.check_cfg(&f) {
2310 return None;
2311 }
2312 let ast_pat = f.pat()?;
2313 let pat = self.collect_pat(ast_pat, binding_list);
2314 let name = f.field_name()?.as_name();
2315 let src = self.expander.in_file(AstPtr::new(&f).wrap_right());
2316 self.store.pat_field_map_back.insert(pat, src);
2317 Some(RecordFieldPat { name, pat })
2318 })
2319 .collect();
2320
2321 let ellipsis = record_pat_field_list.rest_pat().is_some();
2322
2323 Pat::Record { path, args, ellipsis }
2324 }
2325 ast::Pat::SlicePat(p) => {
2326 let SlicePatComponents { prefix, slice, suffix } = p.components();
2327
2328 Pat::Slice {
2330 prefix: prefix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
2331 slice: slice.map(|p| self.collect_pat(p, binding_list)),
2332 suffix: suffix.into_iter().map(|p| self.collect_pat(p, binding_list)).collect(),
2333 }
2334 }
2335 ast::Pat::LiteralPat(lit) => 'b: {
2336 let Some((hir_lit, ast_lit)) = pat_literal_to_hir(lit) else {
2337 break 'b Pat::Missing;
2338 };
2339 let expr = Expr::Literal(hir_lit);
2340 let expr_ptr = AstPtr::new(&ast::Expr::Literal(ast_lit));
2341 let expr_id = self.alloc_expr(expr, expr_ptr);
2342 Pat::Lit(expr_id)
2343 }
2344 ast::Pat::RestPat(_) => {
2345 Pat::Missing
2352 }
2353 ast::Pat::BoxPat(boxpat) => {
2354 let inner = self.collect_pat_opt(boxpat.pat(), binding_list);
2355 Pat::Box { inner }
2356 }
2357 ast::Pat::ConstBlockPat(const_block_pat) => {
2358 if let Some(block) = const_block_pat.block_expr() {
2359 let expr_id = self.with_label_rib(RibKind::Constant, |this| {
2360 let syntax_ptr = AstPtr::new(&block.clone().into());
2361 this.collect_as_a_binding_owner_bad(
2362 |this| this.collect_block(block),
2363 syntax_ptr,
2364 )
2365 });
2366 Pat::ConstBlock(expr_id)
2367 } else {
2368 Pat::Missing
2369 }
2370 }
2371 ast::Pat::MacroPat(mac) => match mac.macro_call() {
2372 Some(call) => {
2373 let macro_ptr = AstPtr::new(&call);
2374 let src = self.expander.in_file(AstPtr::new(&pat));
2375 let pat =
2376 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
2377 this.collect_pat_opt(expanded_pat, binding_list)
2378 });
2379 self.store.pat_map.insert(src, pat.into());
2380 return pat;
2381 }
2382 None => Pat::Missing,
2383 },
2384 ast::Pat::RangePat(p) => {
2385 let mut range_part_lower = |p: Option<ast::Pat>| -> Option<ExprId> {
2386 p.and_then(|it| {
2387 let ptr = PatPtr::new(&it);
2388 match &it {
2389 ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat(
2390 Expr::Literal(pat_literal_to_hir(it)?.0),
2391 ptr,
2392 )),
2393 ast::Pat::IdentPat(ident) if ident.is_simple_ident() => ident
2394 .name()
2395 .map(|name| name.as_name())
2396 .map(Path::from)
2397 .map(|path| self.alloc_expr_from_pat(Expr::Path(path), ptr)),
2398 ast::Pat::PathPat(p) => p
2399 .path()
2400 .and_then(|path| {
2401 self.lower_path(path, &mut Self::impl_trait_error_allocator)
2402 })
2403 .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)),
2404 _ => None,
2407 }
2408 })
2409 };
2410 let start = range_part_lower(p.start());
2411 let end = range_part_lower(p.end());
2412 Pat::Range { start, end }
2413 }
2414 };
2415 let ptr = AstPtr::new(&pat);
2416 self.alloc_pat(pattern, ptr)
2417 }
2418
2419 fn collect_pat_opt(&mut self, pat: Option<ast::Pat>, binding_list: &mut BindingList) -> PatId {
2420 match pat {
2421 Some(pat) => self.collect_pat(pat, binding_list),
2422 None => self.missing_pat(),
2423 }
2424 }
2425
2426 fn collect_tuple_pat(
2427 &mut self,
2428 args: AstChildren<ast::Pat>,
2429 has_leading_comma: bool,
2430 binding_list: &mut BindingList,
2431 ) -> (Box<[PatId]>, Option<u32>) {
2432 let args: Vec<_> = args.map(|p| self.collect_pat_possibly_rest(p, binding_list)).collect();
2433 let ellipsis = args.iter().position(|p| p.is_right()).map(|it| it as u32);
2436
2437 let mut args: Vec<_> = args.into_iter().filter_map(Either::left).collect();
2439 if has_leading_comma {
2442 args.insert(0, self.missing_pat());
2443 }
2444
2445 (args.into_boxed_slice(), ellipsis)
2446 }
2447
2448 fn collect_pat_possibly_rest(
2451 &mut self,
2452 pat: ast::Pat,
2453 binding_list: &mut BindingList,
2454 ) -> Either<PatId, ()> {
2455 match &pat {
2456 ast::Pat::RestPat(_) => Either::Right(()),
2457 ast::Pat::MacroPat(mac) => match mac.macro_call() {
2458 Some(call) => {
2459 let macro_ptr = AstPtr::new(&call);
2460 let src = self.expander.in_file(AstPtr::new(&pat));
2461 let pat =
2462 self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| {
2463 if let Some(expanded_pat) = expanded_pat {
2464 this.collect_pat_possibly_rest(expanded_pat, binding_list)
2465 } else {
2466 Either::Left(this.missing_pat())
2467 }
2468 });
2469 if let Some(pat) = pat.left() {
2470 self.store.pat_map.insert(src, pat.into());
2471 }
2472 pat
2473 }
2474 None => {
2475 let ptr = AstPtr::new(&pat);
2476 Either::Left(self.alloc_pat(Pat::Missing, ptr))
2477 }
2478 },
2479 _ => Either::Left(self.collect_pat(pat, binding_list)),
2480 }
2481 }
2482
2483 fn check_cfg(&mut self, owner: &dyn ast::HasAttrs) -> bool {
2488 let enabled = self.expander.is_cfg_enabled(self.db, owner, self.cfg_options);
2489 match enabled {
2490 Ok(()) => true,
2491 Err(cfg) => {
2492 self.store.diagnostics.push(ExpressionStoreDiagnostics::InactiveCode {
2493 node: self.expander.in_file(SyntaxNodePtr::new(owner.syntax())),
2494 cfg,
2495 opts: self.cfg_options.clone(),
2496 });
2497 false
2498 }
2499 }
2500 }
2501
2502 fn add_definition_to_binding(&mut self, binding_id: BindingId, pat_id: PatId) {
2503 self.store.binding_definitions.entry(binding_id).or_default().push(pat_id);
2504 }
2505
2506 fn collect_label(&mut self, ast_label: ast::Label) -> LabelId {
2509 let label = Label {
2510 name: ast_label
2511 .lifetime()
2512 .as_ref()
2513 .map_or_else(Name::missing, |lt| Name::new_lifetime(<.text())),
2514 };
2515 self.alloc_label(label, AstPtr::new(&ast_label))
2516 }
2517
2518 fn resolve_label(
2519 &self,
2520 lifetime: Option<ast::Lifetime>,
2521 ) -> Result<Option<LabelId>, ExpressionStoreDiagnostics> {
2522 let Some(lifetime) = lifetime else { return Ok(None) };
2523 let mut hygiene_id =
2524 self.expander.hygiene_for_range(self.db, lifetime.syntax().text_range());
2525 let mut hygiene_info = if hygiene_id.is_root() {
2526 None
2527 } else {
2528 hygiene_id.lookup().outer_expn(self.db).map(|expansion| {
2529 let expansion = self.db.lookup_intern_macro_call(expansion.into());
2530 (hygiene_id.lookup().parent(self.db), expansion.def)
2531 })
2532 };
2533 let name = Name::new_lifetime(&lifetime.text());
2534
2535 for (rib_idx, rib) in self.label_ribs.iter().enumerate().rev() {
2536 match &rib.kind {
2537 RibKind::Normal(label_name, id, label_hygiene) => {
2538 if *label_name == name && *label_hygiene == hygiene_id {
2539 return if self.is_label_valid_from_rib(rib_idx) {
2540 Ok(Some(*id))
2541 } else {
2542 Err(ExpressionStoreDiagnostics::UnreachableLabel {
2543 name,
2544 node: self.expander.in_file(AstPtr::new(&lifetime)),
2545 })
2546 };
2547 }
2548 }
2549 RibKind::MacroDef(macro_id) => {
2550 if let Some((parent_ctx, label_macro_id)) = hygiene_info
2551 && label_macro_id == **macro_id
2552 {
2553 hygiene_id = HygieneId::new(parent_ctx.opaque_and_semitransparent(self.db));
2558 hygiene_info = parent_ctx.outer_expn(self.db).map(|expansion| {
2559 let expansion = self.db.lookup_intern_macro_call(expansion.into());
2560 (parent_ctx.parent(self.db), expansion.def)
2561 });
2562 }
2563 }
2564 _ => {}
2565 }
2566 }
2567
2568 Err(ExpressionStoreDiagnostics::UndeclaredLabel {
2569 name,
2570 node: self.expander.in_file(AstPtr::new(&lifetime)),
2571 })
2572 }
2573
2574 fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
2575 !self.label_ribs[rib_index + 1..].iter().any(|rib| rib.kind.is_label_barrier())
2576 }
2577
2578 fn pop_label_rib(&mut self) {
2579 while let Some(LabelRib { kind: RibKind::MacroDef(_) }) = self.label_ribs.pop() {
2581 }
2583 }
2584
2585 fn with_label_rib<T>(&mut self, kind: RibKind, f: impl FnOnce(&mut Self) -> T) -> T {
2586 self.label_ribs.push(LabelRib::new(kind));
2587 let res = f(self);
2588 self.pop_label_rib();
2589 res
2590 }
2591
2592 fn with_labeled_rib<T>(
2593 &mut self,
2594 label: LabelId,
2595 hygiene: HygieneId,
2596 f: impl FnOnce(&mut Self) -> T,
2597 ) -> T {
2598 self.label_ribs.push(LabelRib::new(RibKind::Normal(
2599 self.store.labels[label].name.clone(),
2600 label,
2601 hygiene,
2602 )));
2603 let res = f(self);
2604 self.pop_label_rib();
2605 res
2606 }
2607
2608 fn with_opt_labeled_rib<T>(
2609 &mut self,
2610 label: Option<(HygieneId, LabelId)>,
2611 f: impl FnOnce(&mut Self) -> T,
2612 ) -> T {
2613 match label {
2614 None => f(self),
2615 Some((hygiene, label)) => self.with_labeled_rib(label, hygiene, f),
2616 }
2617 }
2618 fn expand_macros_to_string(&mut self, expr: ast::Expr) -> Option<(ast::String, bool)> {
2622 let m = match expr {
2623 ast::Expr::MacroExpr(m) => m,
2624 ast::Expr::Literal(l) => {
2625 return match l.kind() {
2626 ast::LiteralKind::String(s) => Some((s, true)),
2627 _ => None,
2628 };
2629 }
2630 _ => return None,
2631 };
2632 let e = m.macro_call()?;
2633 let macro_ptr = AstPtr::new(&e);
2634 let (exp, _) = self.collect_macro_call(e, macro_ptr, true, |this, expansion| {
2635 expansion.and_then(|it| this.expand_macros_to_string(it))
2636 })?;
2637 Some((exp, false))
2638 }
2639
2640 fn collect_format_args(
2641 &mut self,
2642 f: ast::FormatArgsExpr,
2643 syntax_ptr: AstPtr<ast::Expr>,
2644 ) -> ExprId {
2645 let mut args = FormatArgumentsCollector::default();
2646 f.args().for_each(|arg| {
2647 args.add(FormatArgument {
2648 kind: match arg.name() {
2649 Some(name) => FormatArgumentKind::Named(name.as_name()),
2650 None => FormatArgumentKind::Normal,
2651 },
2652 expr: self.collect_expr_opt(arg.expr()),
2653 });
2654 });
2655 let template = f.template();
2656 let fmt_snippet = template.as_ref().and_then(|it| match it {
2657 ast::Expr::Literal(literal) => match literal.kind() {
2658 ast::LiteralKind::String(s) => Some(s.text().to_owned()),
2659 _ => None,
2660 },
2661 _ => None,
2662 });
2663 let mut mappings = vec![];
2664 let (fmt, hygiene) = match template.and_then(|template| {
2665 self.expand_macros_to_string(template.clone()).map(|it| (it, template))
2666 }) {
2667 Some(((s, is_direct_literal), template)) => {
2668 let call_ctx = self.expander.call_syntax_ctx();
2669 let hygiene = self.hygiene_id_for(s.syntax().text_range());
2670 let fmt = format_args::parse(
2671 &s,
2672 fmt_snippet,
2673 args,
2674 is_direct_literal,
2675 |name, range| {
2676 let expr_id = self.alloc_expr_desugared(Expr::Path(Path::from(name)));
2677 if let Some(range) = range {
2678 self.store
2679 .template_map
2680 .get_or_insert_with(Default::default)
2681 .implicit_capture_to_source
2682 .insert(
2683 expr_id,
2684 self.expander.in_file((AstPtr::new(&template), range)),
2685 );
2686 }
2687 if !hygiene.is_root() {
2688 self.store.ident_hygiene.insert(expr_id.into(), hygiene);
2689 }
2690 expr_id
2691 },
2692 |name, span| {
2693 if let Some(span) = span {
2694 mappings.push((span, name))
2695 }
2696 },
2697 call_ctx,
2698 );
2699 (fmt, hygiene)
2700 }
2701 None => (
2702 FormatArgs {
2703 template: Default::default(),
2704 arguments: args.finish(),
2705 orphans: Default::default(),
2706 },
2707 HygieneId::ROOT,
2708 ),
2709 };
2710
2711 let mut argmap = FxIndexSet::default();
2714 for piece in fmt.template.iter() {
2715 let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
2716 if let Ok(index) = placeholder.argument.index {
2717 argmap.insert((index, ArgumentType::Format(placeholder.format_trait)));
2718 }
2719 }
2720
2721 let lit_pieces = fmt
2722 .template
2723 .iter()
2724 .enumerate()
2725 .filter_map(|(i, piece)| {
2726 match piece {
2727 FormatArgsPiece::Literal(s) => {
2728 Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))))
2729 }
2730 &FormatArgsPiece::Placeholder(_) => {
2731 if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_))
2733 {
2734 Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(
2735 Symbol::empty(),
2736 ))))
2737 } else {
2738 None
2739 }
2740 }
2741 }
2742 })
2743 .collect();
2744 let lit_pieces =
2745 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: lit_pieces }));
2746 let lit_pieces = self.alloc_expr_desugared(Expr::Ref {
2747 expr: lit_pieces,
2748 rawness: Rawness::Ref,
2749 mutability: Mutability::Shared,
2750 });
2751 let format_options = {
2752 let elements = fmt
2755 .template
2756 .iter()
2757 .filter_map(|piece| {
2758 let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
2759 Some(self.make_format_spec(placeholder, &mut argmap))
2760 })
2761 .collect();
2762 let array = self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements }));
2763 self.alloc_expr_desugared(Expr::Ref {
2764 expr: array,
2765 rawness: Rawness::Ref,
2766 mutability: Mutability::Shared,
2767 })
2768 };
2769
2770 let fmt_args =
2773 || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatArguments);
2774 let fmt_unsafe_arg =
2775 || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatUnsafeArg);
2776 let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
2777
2778 let idx = if use_format_args_since_1_89_0 {
2779 self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
2780 } else {
2781 self.collect_format_args_before_1_89_0_impl(
2782 syntax_ptr,
2783 fmt,
2784 argmap,
2785 lit_pieces,
2786 format_options,
2787 )
2788 };
2789
2790 self.store
2791 .template_map
2792 .get_or_insert_with(Default::default)
2793 .format_args_to_captures
2794 .insert(idx, (hygiene, mappings));
2795 idx
2796 }
2797
2798 fn collect_format_args_before_1_89_0_impl(
2800 &mut self,
2801 syntax_ptr: AstPtr<ast::Expr>,
2802 fmt: FormatArgs,
2803 argmap: FxIndexSet<(usize, ArgumentType)>,
2804 lit_pieces: ExprId,
2805 format_options: ExprId,
2806 ) -> ExprId {
2807 let arguments = &*fmt.arguments.arguments;
2808
2809 let args = if arguments.is_empty() {
2810 let expr = self
2811 .alloc_expr_desugared(Expr::Array(Array::ElementList { elements: Box::default() }));
2812 self.alloc_expr_desugared(Expr::Ref {
2813 expr,
2814 rawness: Rawness::Ref,
2815 mutability: Mutability::Shared,
2816 })
2817 } else {
2818 let args = argmap
2828 .iter()
2829 .map(|&(arg_index, ty)| {
2830 let arg = self.alloc_expr_desugared(Expr::Ref {
2831 expr: arguments[arg_index].expr,
2832 rawness: Rawness::Ref,
2833 mutability: Mutability::Shared,
2834 });
2835 self.make_argument(arg, ty)
2836 })
2837 .collect();
2838 let array =
2839 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
2840 self.alloc_expr_desugared(Expr::Ref {
2841 expr: array,
2842 rawness: Rawness::Ref,
2843 mutability: Mutability::Shared,
2844 })
2845 };
2846
2847 let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
2856 self.db,
2857 self.module.krate(),
2858 Name::new_symbol_root(sym::new_v1_formatted),
2859 );
2860 let unsafe_arg_new = LangItem::FormatUnsafeArg.ty_rel_path(
2861 self.db,
2862 self.module.krate(),
2863 Name::new_symbol_root(sym::new),
2864 );
2865 let new_v1_formatted =
2866 self.alloc_expr_desugared(new_v1_formatted.map_or(Expr::Missing, Expr::Path));
2867
2868 let unsafe_arg_new =
2869 self.alloc_expr_desugared(unsafe_arg_new.map_or(Expr::Missing, Expr::Path));
2870 let unsafe_arg_new =
2871 self.alloc_expr_desugared(Expr::Call { callee: unsafe_arg_new, args: Box::default() });
2872 let mut unsafe_arg_new = self.alloc_expr_desugared(Expr::Unsafe {
2873 id: None,
2874 statements: Box::new([]),
2875 tail: Some(unsafe_arg_new),
2876 });
2877 if !fmt.orphans.is_empty() {
2878 unsafe_arg_new = self.alloc_expr_desugared(Expr::Block {
2879 id: None,
2880 statements: fmt
2885 .orphans
2886 .into_iter()
2887 .map(|expr| Statement::Expr { expr, has_semi: true })
2888 .collect(),
2889 tail: Some(unsafe_arg_new),
2890 label: None,
2891 });
2892 }
2893
2894 self.alloc_expr(
2895 Expr::Call {
2896 callee: new_v1_formatted,
2897 args: Box::new([lit_pieces, args, format_options, unsafe_arg_new]),
2898 },
2899 syntax_ptr,
2900 )
2901 }
2902
2903 fn collect_format_args_impl(
2906 &mut self,
2907 syntax_ptr: AstPtr<ast::Expr>,
2908 fmt: FormatArgs,
2909 argmap: FxIndexSet<(usize, ArgumentType)>,
2910 lit_pieces: ExprId,
2911 format_options: ExprId,
2912 ) -> ExprId {
2913 let arguments = &*fmt.arguments.arguments;
2914
2915 let (let_stmts, args) = if arguments.is_empty() {
2916 (
2917 vec![],
2920 self.alloc_expr_desugared(Expr::Array(Array::ElementList {
2921 elements: Box::default(),
2922 })),
2923 )
2924 } else if argmap.len() == 1 && arguments.len() == 1 {
2925 let args = argmap
2930 .iter()
2931 .map(|&(arg_index, ty)| {
2932 let ref_arg = self.alloc_expr_desugared(Expr::Ref {
2933 expr: arguments[arg_index].expr,
2934 rawness: Rawness::Ref,
2935 mutability: Mutability::Shared,
2936 });
2937 self.make_argument(ref_arg, ty)
2938 })
2939 .collect();
2940 let args =
2941 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
2942 let args_name = Name::new_symbol_root(sym::args);
2943 let args_binding = self.alloc_binding(
2944 args_name.clone(),
2945 BindingAnnotation::Unannotated,
2946 HygieneId::ROOT,
2947 );
2948 let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
2949 self.add_definition_to_binding(args_binding, args_pat);
2950 let let_stmt = Statement::Let {
2952 pat: args_pat,
2953 type_ref: None,
2954 initializer: Some(args),
2955 else_branch: None,
2956 };
2957 (vec![let_stmt], self.alloc_expr_desugared(Expr::Path(args_name.into())))
2958 } else {
2959 let args_name = Name::new_symbol_root(sym::args);
2962 let args_binding = self.alloc_binding(
2963 args_name.clone(),
2964 BindingAnnotation::Unannotated,
2965 HygieneId::ROOT,
2966 );
2967 let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
2968 self.add_definition_to_binding(args_binding, args_pat);
2969 let elements = arguments
2970 .iter()
2971 .map(|arg| {
2972 self.alloc_expr_desugared(Expr::Ref {
2973 expr: arg.expr,
2974 rawness: Rawness::Ref,
2975 mutability: Mutability::Shared,
2976 })
2977 })
2978 .collect();
2979 let args_tuple = self.alloc_expr_desugared(Expr::Tuple { exprs: elements });
2980 let let_stmt1 = Statement::Let {
2982 pat: args_pat,
2983 type_ref: None,
2984 initializer: Some(args_tuple),
2985 else_branch: None,
2986 };
2987
2988 let args = argmap
2996 .iter()
2997 .map(|&(arg_index, ty)| {
2998 let args_ident_expr =
2999 self.alloc_expr_desugared(Expr::Path(args_name.clone().into()));
3000 let arg = self.alloc_expr_desugared(Expr::Field {
3001 expr: args_ident_expr,
3002 name: Name::new_tuple_field(arg_index),
3003 });
3004 self.make_argument(arg, ty)
3005 })
3006 .collect();
3007 let array =
3008 self.alloc_expr_desugared(Expr::Array(Array::ElementList { elements: args }));
3009 let args_binding = self.alloc_binding(
3010 args_name.clone(),
3011 BindingAnnotation::Unannotated,
3012 HygieneId::ROOT,
3013 );
3014 let args_pat = self.alloc_pat_desugared(Pat::Bind { id: args_binding, subpat: None });
3015 self.add_definition_to_binding(args_binding, args_pat);
3016 let let_stmt2 = Statement::Let {
3017 pat: args_pat,
3018 type_ref: None,
3019 initializer: Some(array),
3020 else_branch: None,
3021 };
3022 (vec![let_stmt1, let_stmt2], self.alloc_expr_desugared(Expr::Path(args_name.into())))
3023 };
3024
3025 let args = self.alloc_expr_desugared(Expr::Ref {
3028 expr: args,
3029 rawness: Rawness::Ref,
3030 mutability: Mutability::Shared,
3031 });
3032
3033 let call_block = {
3034 let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
3044 self.db,
3045 self.module.krate(),
3046 Name::new_symbol_root(sym::new_v1_formatted),
3047 );
3048 let new_v1_formatted =
3049 self.alloc_expr_desugared(new_v1_formatted.map_or(Expr::Missing, Expr::Path));
3050 let args = [lit_pieces, args, format_options];
3051 let call = self
3052 .alloc_expr_desugared(Expr::Call { callee: new_v1_formatted, args: args.into() });
3053
3054 Expr::Unsafe { id: None, statements: Box::default(), tail: Some(call) }
3055 };
3056
3057 if !let_stmts.is_empty() {
3058 let call = self.alloc_expr_desugared(call_block);
3065 self.alloc_expr(
3066 Expr::Block {
3067 id: None,
3068 statements: let_stmts.into(),
3069 tail: Some(call),
3070 label: None,
3071 },
3072 syntax_ptr,
3073 )
3074 } else {
3075 self.alloc_expr(call_block, syntax_ptr)
3076 }
3077 }
3078
3079 fn make_format_spec(
3094 &mut self,
3095 placeholder: &FormatPlaceholder,
3096 argmap: &mut FxIndexSet<(usize, ArgumentType)>,
3097 ) -> ExprId {
3098 let position = match placeholder.argument.index {
3099 Ok(arg_index) => {
3100 let (i, _) =
3101 argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
3102 self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
3103 i as u128,
3104 Some(BuiltinUint::Usize),
3105 )))
3106 }
3107 Err(_) => self.missing_expr(),
3108 };
3109 let &FormatOptions {
3110 ref width,
3111 ref precision,
3112 alignment,
3113 fill,
3114 sign,
3115 alternate,
3116 zero_pad,
3117 debug_hex,
3118 } = &placeholder.format_options;
3119
3120 let precision_expr = self.make_count(precision, argmap);
3121 let width_expr = self.make_count(width, argmap);
3122
3123 if self.module.krate().workspace_data(self.db).is_atleast_187() {
3124 let align = match alignment {
3126 Some(FormatAlignment::Left) => 0,
3127 Some(FormatAlignment::Right) => 1,
3128 Some(FormatAlignment::Center) => 2,
3129 None => 3,
3130 };
3131 let flags = fill.unwrap_or(' ') as u32
3133 | ((sign == Some(FormatSign::Plus)) as u32) << 21
3134 | ((sign == Some(FormatSign::Minus)) as u32) << 22
3135 | (alternate as u32) << 23
3136 | (zero_pad as u32) << 24
3137 | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25
3138 | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26
3139 | (width.is_some() as u32) << 27
3140 | (precision.is_some() as u32) << 28
3141 | align << 29
3142 | 1 << 31; let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
3144 flags as u128,
3145 Some(BuiltinUint::U32),
3146 )));
3147
3148 let position =
3149 RecordLitField { name: Name::new_symbol_root(sym::position), expr: position };
3150 let flags = RecordLitField { name: Name::new_symbol_root(sym::flags), expr: flags };
3151 let precision = RecordLitField {
3152 name: Name::new_symbol_root(sym::precision),
3153 expr: precision_expr,
3154 };
3155 let width =
3156 RecordLitField { name: Name::new_symbol_root(sym::width), expr: width_expr };
3157 self.alloc_expr_desugared(Expr::RecordLit {
3158 path: LangItem::FormatPlaceholder.path(self.db, self.module.krate()).map(Box::new),
3159 fields: Box::new([position, flags, precision, width]),
3160 spread: None,
3161 })
3162 } else {
3163 let format_placeholder_new = {
3164 let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
3165 self.db,
3166 self.module.krate(),
3167 Name::new_symbol_root(sym::new),
3168 );
3169 match format_placeholder_new {
3170 Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
3171 None => self.missing_expr(),
3172 }
3173 };
3174 let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
3176 | (((sign == Some(FormatSign::Minus)) as u32) << 1)
3177 | ((alternate as u32) << 2)
3178 | ((zero_pad as u32) << 3)
3179 | (((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4)
3180 | (((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5);
3181 let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
3182 flags as u128,
3183 Some(BuiltinUint::U32),
3184 )));
3185 let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
3186 let align = {
3187 let align = LangItem::FormatAlignment.ty_rel_path(
3188 self.db,
3189 self.module.krate(),
3190 match alignment {
3191 Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left),
3192 Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right),
3193 Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center),
3194 None => Name::new_symbol_root(sym::Unknown),
3195 },
3196 );
3197 match align {
3198 Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
3199 None => self.missing_expr(),
3200 }
3201 };
3202 self.alloc_expr_desugared(Expr::Call {
3203 callee: format_placeholder_new,
3204 args: Box::new([position, fill, align, flags, precision_expr, width_expr]),
3205 })
3206 }
3207 }
3208
3209 fn make_count(
3229 &mut self,
3230 count: &Option<FormatCount>,
3231 argmap: &mut FxIndexSet<(usize, ArgumentType)>,
3232 ) -> ExprId {
3233 match count {
3234 Some(FormatCount::Literal(n)) => {
3235 let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
3236 *n as u128,
3237 None,
3239 )));
3240 let count_is = match LangItem::FormatCount.ty_rel_path(
3241 self.db,
3242 self.module.krate(),
3243 Name::new_symbol_root(sym::Is),
3244 ) {
3245 Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
3246 None => self.missing_expr(),
3247 };
3248 self.alloc_expr_desugared(Expr::Call { callee: count_is, args: Box::new([args]) })
3249 }
3250 Some(FormatCount::Argument(arg)) => {
3251 if let Ok(arg_index) = arg.index {
3252 let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
3253
3254 let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
3255 i as u128,
3256 Some(BuiltinUint::Usize),
3257 )));
3258 let count_param = match LangItem::FormatCount.ty_rel_path(
3259 self.db,
3260 self.module.krate(),
3261 Name::new_symbol_root(sym::Param),
3262 ) {
3263 Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
3264 None => self.missing_expr(),
3265 };
3266 self.alloc_expr_desugared(Expr::Call {
3267 callee: count_param,
3268 args: Box::new([args]),
3269 })
3270 } else {
3271 self.missing_expr()
3274 }
3275 }
3276 None => match LangItem::FormatCount.ty_rel_path(
3277 self.db,
3278 self.module.krate(),
3279 Name::new_symbol_root(sym::Implied),
3280 ) {
3281 Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
3282 None => self.missing_expr(),
3283 },
3284 }
3285 }
3286
3287 fn make_argument(&mut self, arg: ExprId, ty: ArgumentType) -> ExprId {
3295 use ArgumentType::*;
3296 use FormatTrait::*;
3297
3298 let new_fn = match LangItem::FormatArgument.ty_rel_path(
3299 self.db,
3300 self.module.krate(),
3301 Name::new_symbol_root(match ty {
3302 Format(Display) => sym::new_display,
3303 Format(Debug) => sym::new_debug,
3304 Format(LowerExp) => sym::new_lower_exp,
3305 Format(UpperExp) => sym::new_upper_exp,
3306 Format(Octal) => sym::new_octal,
3307 Format(Pointer) => sym::new_pointer,
3308 Format(Binary) => sym::new_binary,
3309 Format(LowerHex) => sym::new_lower_hex,
3310 Format(UpperHex) => sym::new_upper_hex,
3311 Usize => sym::from_usize,
3312 }),
3313 ) {
3314 Some(new_fn) => self.alloc_expr_desugared(Expr::Path(new_fn)),
3315 None => self.missing_expr(),
3316 };
3317 self.alloc_expr_desugared(Expr::Call { callee: new_fn, args: Box::new([arg]) })
3318 }
3319
3320 fn lang_path(&self, lang: LangItem) -> Option<Path> {
3323 lang.path(self.db, self.module.krate())
3324 }
3325}
3326
3327fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)> {
3328 let ast_lit = lit.literal()?;
3329 let mut hir_lit: Literal = ast_lit.kind().into();
3330 if lit.minus_token().is_some() {
3331 hir_lit = hir_lit.negate()?;
3332 }
3333 Some((hir_lit, ast_lit))
3334}
3335
3336impl ExprCollector<'_> {
3337 fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
3338 let src = self.expander.in_file(ptr);
3339 let id = self.store.exprs.alloc(expr);
3340 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
3341 self.store.expr_map.insert(src, id.into());
3342 id
3343 }
3344 fn alloc_expr_desugared(&mut self, expr: Expr) -> ExprId {
3347 self.store.exprs.alloc(expr)
3348 }
3349 fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId {
3350 let src = self.expander.in_file(ptr);
3351 let id = self.store.exprs.alloc(expr);
3352 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_left));
3353 id
3356 }
3357 fn missing_expr(&mut self) -> ExprId {
3358 self.alloc_expr_desugared(Expr::Missing)
3359 }
3360
3361 fn alloc_binding(
3362 &mut self,
3363 name: Name,
3364 mode: BindingAnnotation,
3365 hygiene: HygieneId,
3366 ) -> BindingId {
3367 let binding = self.store.bindings.alloc(Binding { name, mode, problems: None, hygiene });
3368 if let Some(owner) = self.current_binding_owner {
3369 self.store.binding_owners.insert(binding, owner);
3370 }
3371 binding
3372 }
3373
3374 fn alloc_pat_from_expr(&mut self, pat: Pat, ptr: ExprPtr) -> PatId {
3375 let src = self.expander.in_file(ptr);
3376 let id = self.store.pats.alloc(pat);
3377 self.store.expr_map.insert(src, id.into());
3378 self.store.pat_map_back.insert(id, src.map(AstPtr::wrap_left));
3379 id
3380 }
3381
3382 fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId {
3383 let src = self.expander.in_file(ptr);
3384 let id = self.store.exprs.alloc(expr);
3385 self.store.pat_map.insert(src, id.into());
3386 self.store.expr_map_back.insert(id, src.map(AstPtr::wrap_right));
3387 id
3388 }
3389
3390 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
3391 let src = self.expander.in_file(ptr);
3392 let id = self.store.pats.alloc(pat);
3393 self.store.pat_map_back.insert(id, src.map(AstPtr::wrap_right));
3394 self.store.pat_map.insert(src, id.into());
3395 id
3396 }
3397 fn alloc_pat_desugared(&mut self, pat: Pat) -> PatId {
3399 self.store.pats.alloc(pat)
3400 }
3401 fn missing_pat(&mut self) -> PatId {
3402 self.store.pats.alloc(Pat::Missing)
3403 }
3404
3405 fn alloc_label(&mut self, label: Label, ptr: LabelPtr) -> LabelId {
3406 let src = self.expander.in_file(ptr);
3407 let id = self.store.labels.alloc(label);
3408 self.store.label_map_back.insert(id, src);
3409 self.store.label_map.insert(src, id);
3410 id
3411 }
3412 fn alloc_label_desugared(&mut self, label: Label) -> LabelId {
3414 self.store.labels.alloc(label)
3415 }
3416
3417 fn is_lowering_awaitable_block(&self) -> &Awaitable {
3418 self.awaitable_context.as_ref().unwrap_or(&Awaitable::No("unknown"))
3419 }
3420
3421 fn with_awaitable_block<T>(
3422 &mut self,
3423 awaitable: Awaitable,
3424 f: impl FnOnce(&mut Self) -> T,
3425 ) -> T {
3426 let orig = self.awaitable_context.replace(awaitable);
3427 let res = f(self);
3428 self.awaitable_context = orig;
3429 res
3430 }
3431
3432 fn hygiene_id_for(&self, range: TextRange) -> HygieneId {
3433 self.expander.hygiene_for_range(self.db, range)
3434 }
3435}
3436
3437fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
3438 (|| syntax::algo::skip_trivia_token(t?.next_token()?, syntax::Direction::Next))()
3439 .is_some_and(|it| it.kind() == syntax::T![,])
3440}
3441
3442#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
3443enum ArgumentType {
3444 Format(FormatTrait),
3445 Usize,
3446}
3447
3448pub fn hir_assoc_type_binding_to_ast(
3450 segment_args: &ast::GenericArgList,
3451 binding_idx: u32,
3452) -> Option<ast::AssocTypeArg> {
3453 segment_args
3454 .generic_args()
3455 .filter_map(|arg| match arg {
3456 ast::GenericArg::AssocTypeArg(it) => Some(it),
3457 _ => None,
3458 })
3459 .filter(|binding| binding.param_list().is_none() && binding.name_ref().is_some())
3460 .nth(binding_idx as usize)
3461}
3462
3463pub fn hir_generic_arg_to_ast(
3465 args: &ast::GenericArgList,
3466 arg_idx: u32,
3467 has_self_arg: bool,
3468) -> Option<ast::GenericArg> {
3469 args.generic_args()
3470 .filter(|arg| match arg {
3471 ast::GenericArg::AssocTypeArg(_) => false,
3472 ast::GenericArg::LifetimeArg(arg) => arg.lifetime().is_some(),
3473 ast::GenericArg::ConstArg(_) | ast::GenericArg::TypeArg(_) => true,
3474 })
3475 .nth(arg_idx as usize - has_self_arg as usize)
3476}